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.

3654 lines
113 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1996-2000 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // Res.cpp
  7. //
  8. // Abstract:
  9. // Implementation of the CResource class.
  10. //
  11. // Author:
  12. // David Potter (davidp) May 6, 1996
  13. //
  14. // Revision History:
  15. //
  16. // Notes:
  17. //
  18. /////////////////////////////////////////////////////////////////////////////
  19. #include "StdAfx.h"
  20. #include "CluAdmin.h"
  21. #include "ConstDef.h"
  22. #include "Res.h"
  23. #include "ClusItem.inl"
  24. #include "ResProp.h"
  25. #include "ExcOper.h"
  26. #include "TraceTag.h"
  27. #include "Cluster.h"
  28. #include "DelRes.h"
  29. #include "MoveRes.h"
  30. #include "WaitDlg.h"
  31. #ifdef _DEBUG
  32. #define new DEBUG_NEW
  33. #undef THIS_FILE
  34. static char THIS_FILE[] = __FILE__;
  35. #endif
  36. /////////////////////////////////////////////////////////////////////////////
  37. // Global Variables
  38. /////////////////////////////////////////////////////////////////////////////
  39. #ifdef _DEBUG
  40. CTraceTag g_tagResource(_T("Document"), _T("RESOURCE"), 0);
  41. CTraceTag g_tagResNotify(_T("Notify"), _T("RES NOTIFY"), 0);
  42. CTraceTag g_tagResRegNotify(_T("Notify"), _T("RES REG NOTIFY"), 0);
  43. #endif
  44. /////////////////////////////////////////////////////////////////////////////
  45. // CResource
  46. /////////////////////////////////////////////////////////////////////////////
  47. IMPLEMENT_DYNCREATE(CResource, CClusterItem)
  48. /////////////////////////////////////////////////////////////////////////////
  49. // Message Maps
  50. BEGIN_MESSAGE_MAP(CResource, CClusterItem)
  51. //{{AFX_MSG_MAP(CResource)
  52. ON_UPDATE_COMMAND_UI(ID_FILE_BRING_ONLINE, OnUpdateBringOnline)
  53. ON_UPDATE_COMMAND_UI(ID_FILE_TAKE_OFFLINE, OnUpdateTakeOffline)
  54. ON_UPDATE_COMMAND_UI(ID_FILE_INITIATE_FAILURE, OnUpdateInitiateFailure)
  55. ON_UPDATE_COMMAND_UI(ID_FILE_MOVE_RESOURCE_1, OnUpdateMoveResource1)
  56. ON_UPDATE_COMMAND_UI(ID_FILE_MOVE_RESOURCE_2, OnUpdateMoveResourceRest)
  57. ON_UPDATE_COMMAND_UI(ID_FILE_MOVE_RESOURCE_3, OnUpdateMoveResourceRest)
  58. ON_UPDATE_COMMAND_UI(ID_FILE_MOVE_RESOURCE_4, OnUpdateMoveResourceRest)
  59. ON_UPDATE_COMMAND_UI(ID_FILE_MOVE_RESOURCE_5, OnUpdateMoveResourceRest)
  60. ON_UPDATE_COMMAND_UI(ID_FILE_MOVE_RESOURCE_6, OnUpdateMoveResourceRest)
  61. ON_UPDATE_COMMAND_UI(ID_FILE_MOVE_RESOURCE_7, OnUpdateMoveResourceRest)
  62. ON_UPDATE_COMMAND_UI(ID_FILE_MOVE_RESOURCE_8, OnUpdateMoveResourceRest)
  63. ON_UPDATE_COMMAND_UI(ID_FILE_MOVE_RESOURCE_9, OnUpdateMoveResourceRest)
  64. ON_UPDATE_COMMAND_UI(ID_FILE_MOVE_RESOURCE_10, OnUpdateMoveResourceRest)
  65. ON_UPDATE_COMMAND_UI(ID_FILE_MOVE_RESOURCE_11, OnUpdateMoveResourceRest)
  66. ON_UPDATE_COMMAND_UI(ID_FILE_MOVE_RESOURCE_12, OnUpdateMoveResourceRest)
  67. ON_UPDATE_COMMAND_UI(ID_FILE_MOVE_RESOURCE_13, OnUpdateMoveResourceRest)
  68. ON_UPDATE_COMMAND_UI(ID_FILE_MOVE_RESOURCE_14, OnUpdateMoveResourceRest)
  69. ON_UPDATE_COMMAND_UI(ID_FILE_MOVE_RESOURCE_15, OnUpdateMoveResourceRest)
  70. ON_UPDATE_COMMAND_UI(ID_FILE_MOVE_RESOURCE_16, OnUpdateMoveResourceRest)
  71. ON_UPDATE_COMMAND_UI(ID_FILE_MOVE_RESOURCE_17, OnUpdateMoveResourceRest)
  72. ON_UPDATE_COMMAND_UI(ID_FILE_MOVE_RESOURCE_18, OnUpdateMoveResourceRest)
  73. ON_UPDATE_COMMAND_UI(ID_FILE_MOVE_RESOURCE_19, OnUpdateMoveResourceRest)
  74. ON_UPDATE_COMMAND_UI(ID_FILE_MOVE_RESOURCE_20, OnUpdateMoveResourceRest)
  75. ON_UPDATE_COMMAND_UI(ID_FILE_DELETE, OnUpdateDelete)
  76. ON_UPDATE_COMMAND_UI(ID_FILE_PROPERTIES, OnUpdateProperties)
  77. ON_COMMAND(ID_FILE_BRING_ONLINE, OnCmdBringOnline)
  78. ON_COMMAND(ID_FILE_TAKE_OFFLINE, OnCmdTakeOffline)
  79. ON_COMMAND(ID_FILE_INITIATE_FAILURE, OnCmdInitiateFailure)
  80. ON_COMMAND(ID_FILE_DELETE, OnCmdDelete)
  81. //}}AFX_MSG_MAP
  82. END_MESSAGE_MAP()
  83. /////////////////////////////////////////////////////////////////////////////
  84. //++
  85. //
  86. // CResource::CResource
  87. //
  88. // Routine Description:
  89. // Default constructor.
  90. //
  91. // Arguments:
  92. // None.
  93. //
  94. // Return Value:
  95. // None.
  96. //
  97. //--
  98. /////////////////////////////////////////////////////////////////////////////
  99. CResource::CResource(void)
  100. : CClusterItem(NULL, IDS_ITEMTYPE_RESOURCE)
  101. {
  102. CommonConstruct();
  103. } //*** CResoruce::CResource()
  104. /////////////////////////////////////////////////////////////////////////////
  105. //++
  106. //
  107. // CResource::CResource
  108. //
  109. // Routine Description:
  110. // Constructor.
  111. //
  112. // Arguments:
  113. // bDocObj [IN] TRUE = object is part of the document.
  114. //
  115. // Return Value:
  116. // None.
  117. //
  118. //--
  119. /////////////////////////////////////////////////////////////////////////////
  120. CResource::CResource(IN BOOL bDocObj)
  121. : CClusterItem(NULL, IDS_ITEMTYPE_RESOURCE)
  122. {
  123. CommonConstruct();
  124. m_bDocObj = bDocObj;
  125. } //*** CResource::CResource(bDocObj)
  126. /////////////////////////////////////////////////////////////////////////////
  127. //++
  128. //
  129. // CResource::CommonConstruct
  130. //
  131. // Routine Description:
  132. // Common construction.
  133. //
  134. // Arguments:
  135. // None.
  136. //
  137. // Return Value:
  138. // None.
  139. //
  140. //--
  141. /////////////////////////////////////////////////////////////////////////////
  142. void CResource::CommonConstruct(void)
  143. {
  144. m_idmPopupMenu = IDM_RESOURCE_POPUP;
  145. m_bInitializing = FALSE;
  146. m_bDeleting = FALSE;
  147. m_hresource = NULL;
  148. m_bSeparateMonitor = FALSE;
  149. m_nLooksAlive = CLUSTER_RESOURCE_DEFAULT_LOOKS_ALIVE;
  150. m_nIsAlive = CLUSTER_RESOURCE_DEFAULT_IS_ALIVE;
  151. m_crraRestartAction = CLUSTER_RESOURCE_DEFAULT_RESTART_ACTION;
  152. m_nRestartThreshold = CLUSTER_RESOURCE_DEFAULT_RESTART_THRESHOLD;
  153. m_nRestartPeriod = CLUSTER_RESOURCE_DEFAULT_RESTART_PERIOD;
  154. m_nPendingTimeout = CLUSTER_RESOURCE_DEFAULT_PENDING_TIMEOUT;
  155. m_rciResClassInfo.rc = CLUS_RESCLASS_UNKNOWN;
  156. m_rciResClassInfo.SubClass = 0;
  157. m_dwCharacteristics = CLUS_CHAR_UNKNOWN;
  158. m_dwFlags = 0;
  159. m_pciOwner = NULL;
  160. m_pciGroup = NULL;
  161. m_pciResourceType = NULL;
  162. m_pcrd = NULL;
  163. m_plpciresDependencies = NULL;
  164. m_plpcinodePossibleOwners = NULL;
  165. // Set the object type image.
  166. m_iimgObjectType = GetClusterAdminApp()->Iimg(IMGLI_RES);
  167. // Setup the property array.
  168. {
  169. m_rgProps[epropName].Set(CLUSREG_NAME_RES_NAME, m_strName, m_strName);
  170. m_rgProps[epropType].Set(CLUSREG_NAME_RES_TYPE, m_strResourceType, m_strResourceType);
  171. m_rgProps[epropDescription].Set(CLUSREG_NAME_RES_DESC, m_strDescription, m_strDescription);
  172. m_rgProps[epropSeparateMonitor].Set(CLUSREG_NAME_RES_SEPARATE_MONITOR, m_bSeparateMonitor, m_bSeparateMonitor);
  173. m_rgProps[epropLooksAlive].Set(CLUSREG_NAME_RES_LOOKS_ALIVE, m_nLooksAlive, m_nLooksAlive);
  174. m_rgProps[epropIsAlive].Set(CLUSREG_NAME_RES_IS_ALIVE, m_nIsAlive, m_nIsAlive);
  175. m_rgProps[epropRestartAction].Set(CLUSREG_NAME_RES_RESTART_ACTION, (DWORD &) m_crraRestartAction, (DWORD &) m_crraRestartAction);
  176. m_rgProps[epropRestartThreshold].Set(CLUSREG_NAME_RES_RESTART_THRESHOLD, m_nRestartThreshold, m_nRestartThreshold);
  177. m_rgProps[epropRestartPeriod].Set(CLUSREG_NAME_RES_RESTART_PERIOD, m_nRestartPeriod, m_nRestartPeriod);
  178. m_rgProps[epropPendingTimeout].Set(CLUSREG_NAME_RES_PENDING_TIMEOUT, m_nPendingTimeout, m_nPendingTimeout);
  179. } // Setup the property array
  180. #ifdef _CLUADMIN_USE_OLE_
  181. EnableAutomation();
  182. #endif
  183. // To keep the application running as long as an OLE automation
  184. // object is active, the constructor calls AfxOleLockApp.
  185. // AfxOleLockApp();
  186. } //*** CResource::CommonConstruct()
  187. /////////////////////////////////////////////////////////////////////////////
  188. //++
  189. //
  190. // CResource::~CResource
  191. //
  192. // Routine Description:
  193. // Destructor.
  194. //
  195. // Arguments:
  196. // None.
  197. //
  198. // Return Value:
  199. // None.
  200. //
  201. //--
  202. /////////////////////////////////////////////////////////////////////////////
  203. CResource::~CResource(void)
  204. {
  205. // Cleanup this object.
  206. Cleanup();
  207. delete m_plpciresDependencies;
  208. delete m_plpcinodePossibleOwners;
  209. delete [] (PBYTE) m_pcrd;
  210. // Close the resource handle.
  211. if (Hresource() != NULL)
  212. {
  213. CloseClusterResource(Hresource());
  214. m_hresource = NULL;
  215. } // if: resource is open
  216. // To terminate the application when all objects created with
  217. // with OLE automation, the destructor calls AfxOleUnlockApp.
  218. // AfxOleUnlockApp();
  219. } //*** CResource::~CResource
  220. /////////////////////////////////////////////////////////////////////////////
  221. //++
  222. //
  223. // CResource::Cleanup
  224. //
  225. // Routine Description:
  226. // Cleanup the item.
  227. //
  228. // Arguments:
  229. // None.
  230. //
  231. // Return Value:
  232. // None.
  233. //
  234. // Exceptions Thrown:
  235. // None.
  236. //
  237. //--
  238. /////////////////////////////////////////////////////////////////////////////
  239. void CResource::Cleanup(void)
  240. {
  241. // Delete the Dependencies list.
  242. if (m_plpciresDependencies != NULL)
  243. m_plpciresDependencies->RemoveAll();
  244. // Delete the PossibleOwners list.
  245. if (m_plpcinodePossibleOwners != NULL)
  246. m_plpcinodePossibleOwners->RemoveAll();
  247. // If we are active on a node, remove ourselves from that active list.
  248. if (PciOwner() != NULL)
  249. {
  250. if (BDocObj())
  251. PciOwner()->RemoveActiveResource(this);
  252. PciOwner()->Release();
  253. m_pciOwner = NULL;
  254. } // if: there is an owner
  255. // Remove ourselves from the group's list.
  256. if (PciGroup() != NULL)
  257. {
  258. if (BDocObj())
  259. PciGroup()->RemoveResource(this);
  260. PciGroup()->Release();
  261. m_pciGroup = NULL;
  262. } // if: there is a group
  263. // Update the reference count to the resource type
  264. if (PciResourceType() != NULL)
  265. {
  266. PciResourceType()->Release();
  267. m_pciResourceType = NULL;
  268. } // if: there is a resource type
  269. // Remove the item from the resource list.
  270. if (BDocObj())
  271. {
  272. POSITION posPci;
  273. posPci = Pdoc()->LpciResources().Find(this);
  274. if (posPci != NULL)
  275. {
  276. Pdoc()->LpciResources().RemoveAt(posPci);
  277. } // if: found in the document's list
  278. } // if: this is a document object
  279. } //*** CResource::Cleanup()
  280. /////////////////////////////////////////////////////////////////////////////
  281. //++
  282. //
  283. // CResource::Create
  284. //
  285. // Routine Description:
  286. // Create a resource.
  287. //
  288. // Arguments:
  289. // pdoc [IN OUT] Document to which this item belongs.
  290. // lpszName [IN] Name of the resource.
  291. // lpszType [IN] Type of the resource.
  292. // lpszGroup [IN] Group in which to create the resource.
  293. // bSeparateMonitor [IN] TRUE = run resource in separate monitor.
  294. //
  295. // Return Value:
  296. // None.
  297. //
  298. // Exceptions Thrown:
  299. // CNTException Errors from CreateClusterResource.
  300. // Any exceptions thrown by CResource::Init(), CResourceList::new(),
  301. // or CNodeList::new().
  302. //
  303. //--
  304. /////////////////////////////////////////////////////////////////////////////
  305. void CResource::Create(
  306. IN OUT CClusterDoc * pdoc,
  307. IN LPCTSTR lpszName,
  308. IN LPCTSTR lpszType,
  309. IN LPCTSTR lpszGroup,
  310. IN BOOL bSeparateMonitor
  311. )
  312. {
  313. DWORD dwStatus;
  314. DWORD dwFlags;
  315. HRESOURCE hresource;
  316. CGroup * pciGroup;
  317. CString strName(lpszName); // Required if built non-Unicode
  318. CString strType(lpszType); // Required if built non-Unicode
  319. CWaitCursor wc;
  320. ASSERT(Hresource() == NULL);
  321. ASSERT(Hkey() == NULL);
  322. ASSERT_VALID(pdoc);
  323. ASSERT(lpszName != NULL);
  324. ASSERT(lpszType != NULL);
  325. ASSERT(lpszGroup != NULL);
  326. // Find the specified group.
  327. pciGroup = pdoc->LpciGroups().PciGroupFromName(lpszGroup);
  328. ASSERT_VALID(pciGroup);
  329. // Set the flags.
  330. if (bSeparateMonitor)
  331. dwFlags = CLUSTER_RESOURCE_SEPARATE_MONITOR;
  332. else
  333. dwFlags = 0;
  334. // Create the resource.
  335. hresource = CreateClusterResource(pciGroup->Hgroup(), strName, strType, dwFlags);
  336. if (hresource == NULL)
  337. {
  338. dwStatus = GetLastError();
  339. ThrowStaticException(dwStatus, IDS_CREATE_RESOURCE_ERROR, lpszName);
  340. } // if: error creating the cluster resource
  341. CloseClusterResource(hresource);
  342. // Open the resource.
  343. Init(pdoc, lpszName);
  344. } //*** CResource::Create()
  345. /////////////////////////////////////////////////////////////////////////////
  346. //++
  347. //
  348. // CResource::Init
  349. //
  350. // Routine Description:
  351. // Initialize the item.
  352. //
  353. // Arguments:
  354. // pdoc [IN OUT] Document to which this item belongs.
  355. // lpszName [IN] Name of the item.
  356. //
  357. // Return Value:
  358. // None.
  359. //
  360. // Exceptions Thrown:
  361. // CNTException Errors from OpenClusterResource or GetClusterResourceKey.
  362. // Any exceptions thrown by new.
  363. //
  364. //--
  365. /////////////////////////////////////////////////////////////////////////////
  366. void CResource::Init(IN OUT CClusterDoc * pdoc, IN LPCTSTR lpszName)
  367. {
  368. DWORD dwStatus = ERROR_SUCCESS;
  369. LONG lResult;
  370. CString strName(lpszName); // Required if built non-Unicode
  371. CWaitCursor wc;
  372. ASSERT(Hresource() == NULL);
  373. ASSERT(Hkey() == NULL);
  374. // Call the base class method.
  375. CClusterItem::Init(pdoc, lpszName);
  376. try
  377. {
  378. // Open the resource.
  379. m_hresource = OpenClusterResource(Hcluster(), strName);
  380. if (Hresource() == NULL)
  381. {
  382. dwStatus = GetLastError();
  383. ThrowStaticException(dwStatus, IDS_OPEN_RESOURCE_ERROR, lpszName);
  384. } // if: error opening the cluster resource
  385. // Get the resource registry key.
  386. m_hkey = GetClusterResourceKey(Hresource(), MAXIMUM_ALLOWED);
  387. if (Hkey() == NULL)
  388. ThrowStaticException(GetLastError(), IDS_GET_RESOURCE_KEY_ERROR, lpszName);
  389. if (BDocObj())
  390. {
  391. ASSERT(Pcnk() != NULL);
  392. Trace(g_tagClusItemNotify, _T("CResource::Init() - Registering for resource notifications (%08.8x) for '%s'"), Pcnk(), StrName());
  393. // Register for resource notifications.
  394. lResult = RegisterClusterNotify(
  395. GetClusterAdminApp()->HchangeNotifyPort(),
  396. (CLUSTER_CHANGE_RESOURCE_STATE
  397. | CLUSTER_CHANGE_RESOURCE_DELETED
  398. | CLUSTER_CHANGE_RESOURCE_PROPERTY),
  399. Hresource(),
  400. (DWORD_PTR) Pcnk()
  401. );
  402. if (lResult != ERROR_SUCCESS)
  403. {
  404. dwStatus = lResult;
  405. ThrowStaticException(dwStatus, IDS_RES_NOTIF_REG_ERROR, lpszName);
  406. } // if: error registering for resource notifications
  407. // Register for registry notifications.
  408. if (Hkey != NULL)
  409. {
  410. lResult = RegisterClusterNotify(
  411. GetClusterAdminApp()->HchangeNotifyPort(),
  412. (CLUSTER_CHANGE_REGISTRY_NAME
  413. | CLUSTER_CHANGE_REGISTRY_ATTRIBUTES
  414. | CLUSTER_CHANGE_REGISTRY_VALUE
  415. | CLUSTER_CHANGE_REGISTRY_SUBTREE),
  416. Hkey(),
  417. (DWORD_PTR) Pcnk()
  418. );
  419. if (lResult != ERROR_SUCCESS)
  420. {
  421. dwStatus = lResult;
  422. ThrowStaticException(dwStatus, IDS_RES_NOTIF_REG_ERROR, lpszName);
  423. } // if: error registering for registry notifications
  424. } // if: there is a key
  425. } // if: document object
  426. // Allocate lists.
  427. m_plpciresDependencies = new CResourceList;
  428. if ( m_plpciresDependencies == NULL )
  429. {
  430. AfxThrowMemoryException();
  431. } // if: error allocating the dependency list
  432. m_plpcinodePossibleOwners = new CNodeList;
  433. if ( m_plpcinodePossibleOwners == NULL )
  434. {
  435. AfxThrowMemoryException();
  436. } // if: error allocating the possible owners list
  437. // Read the initial state.
  438. UpdateState();
  439. } // try
  440. catch (CException *)
  441. {
  442. if (Hkey() != NULL)
  443. {
  444. ClusterRegCloseKey(Hkey());
  445. m_hkey = NULL;
  446. } // if: registry key opened
  447. if (Hresource() != NULL)
  448. {
  449. CloseClusterResource(Hresource());
  450. m_hresource = NULL;
  451. } // if: resource opened
  452. m_bReadOnly = TRUE;
  453. throw;
  454. } // catch: CException
  455. } //*** CResource::Init()
  456. /////////////////////////////////////////////////////////////////////////////
  457. //++
  458. //
  459. // CResource::ReadItem
  460. //
  461. // Routine Description:
  462. // Read the item parameters from the cluster database.
  463. //
  464. // Arguments:
  465. // None.
  466. //
  467. // Return Value:
  468. // None.
  469. //
  470. // Exceptions Thrown:
  471. // CNTException Errors from CClusterItem::DwReadValue().
  472. //
  473. //--
  474. /////////////////////////////////////////////////////////////////////////////
  475. void CResource::ReadItem(void)
  476. {
  477. DWORD dwStatus;
  478. DWORD dwRetStatus = ERROR_SUCCESS;
  479. CWaitCursor wc;
  480. ASSERT_VALID(this);
  481. m_bInitializing = FALSE;
  482. if (Hresource() != NULL)
  483. {
  484. m_rgProps[epropDescription].m_value.pstr = &m_strDescription;
  485. m_rgProps[epropSeparateMonitor].m_value.pb = &m_bSeparateMonitor;
  486. m_rgProps[epropLooksAlive].m_value.pdw = &m_nLooksAlive;
  487. m_rgProps[epropIsAlive].m_value.pdw = &m_nIsAlive;
  488. m_rgProps[epropRestartAction].m_value.pdw = (DWORD *) &m_crraRestartAction;
  489. m_rgProps[epropRestartThreshold].m_value.pdw = &m_nRestartThreshold;
  490. m_rgProps[epropRestartPeriod].m_value.pdw = &m_nRestartPeriod;
  491. m_rgProps[epropPendingTimeout].m_value.pdw = &m_nPendingTimeout;
  492. // Call the base class method.
  493. Trace( g_tagResource, _T("(%s) (%s (%x)) - CResource::ReadItem() - Calling CClusterItem::ReadItem()"), Pdoc()->StrNode(), StrName(), this );
  494. CClusterItem::ReadItem();
  495. // Read and parse the common properties.
  496. {
  497. CClusPropList cpl;
  498. Trace( g_tagResource, _T("(%s) (%s (%x)) - CResource::ReadItem() - Getting common properties"), Pdoc()->StrNode(), StrName(), this );
  499. dwStatus = cpl.ScGetResourceProperties(
  500. Hresource(),
  501. CLUSCTL_RESOURCE_GET_COMMON_PROPERTIES
  502. );
  503. if (dwStatus == ERROR_SUCCESS)
  504. {
  505. Trace( g_tagResource, _T("(%s) (%s (%x)) - CResource::ReadItem() - Parsing common properties"), Pdoc()->StrNode(), StrName(), this );
  506. dwStatus = DwParseProperties(cpl);
  507. } // if: properties read successfully
  508. if (dwStatus != ERROR_SUCCESS)
  509. {
  510. Trace( g_tagError, _T("(%s) (%s (%x)) - CResource::ReadItem() - Error 0x%08.8x getting or parsing common properties"), Pdoc()->StrNode(), StrName(), this, dwStatus );
  511. dwRetStatus = dwStatus;
  512. } // if: error reading or parsing properties
  513. } // Read and parse the common properties
  514. // Read and parse the read-only common properties.
  515. if (dwRetStatus == ERROR_SUCCESS)
  516. {
  517. CClusPropList cpl;
  518. Trace( g_tagResource, _T("(%s) (%s (%x)) - CResource::ReadItem() - Getting common RO properties"), Pdoc()->StrNode(), StrName(), this );
  519. dwStatus = cpl.ScGetResourceProperties(
  520. Hresource(),
  521. CLUSCTL_RESOURCE_GET_RO_COMMON_PROPERTIES
  522. );
  523. if (dwStatus == ERROR_SUCCESS)
  524. {
  525. Trace( g_tagResource, _T("(%s) (%s (%x)) - CResource::ReadItem() - Parsing common RO properties"), Pdoc()->StrNode(), StrName(), this );
  526. dwStatus = DwParseProperties(cpl);
  527. } // if: properties read successfully
  528. if (dwStatus != ERROR_SUCCESS)
  529. {
  530. Trace( g_tagError, _T("(%s) (%s (%x)) - CResource::ReadItem() - Error 0x%08.8x getting or parsing common RO properties"), Pdoc()->StrNode(), StrName(), this, dwStatus );
  531. dwRetStatus = dwStatus;
  532. } // if: error reading or parsing properties
  533. } // if: no error yet
  534. // Find the resource type object.
  535. {
  536. CResourceType * pciResType;
  537. pciResType = Pdoc()->LpciResourceTypes().PciResTypeFromName(StrResourceType());
  538. if (m_pciResourceType != NULL)
  539. m_pciResourceType->Release();
  540. m_pciResourceType = pciResType;
  541. if (m_pciResourceType != NULL)
  542. m_pciResourceType->AddRef();
  543. } // Find the resource type object
  544. // Read the required dependencies.
  545. if (dwRetStatus == ERROR_SUCCESS)
  546. {
  547. PCLUSPROP_REQUIRED_DEPENDENCY pcrd;
  548. Trace( g_tagResource, _T("(%s) (%s (%x)) - CResource::ReadItem() - Getting required dependencies"), Pdoc()->StrNode(), StrName(), this );
  549. dwStatus = DwResourceControlGet(CLUSCTL_RESOURCE_GET_REQUIRED_DEPENDENCIES, (PBYTE *) &pcrd);
  550. if (dwStatus != ERROR_SUCCESS)
  551. {
  552. Trace( g_tagError, _T("(%s) (%s (%x)) - CResource::ReadItem() - Error 0x%08.8x getting required dependencies"), Pdoc()->StrNode(), StrName(), this, dwStatus );
  553. dwRetStatus = dwStatus;
  554. } // if: error getting required dependencies
  555. delete [] (PBYTE) m_pcrd;
  556. m_pcrd = pcrd;
  557. } // if: no error yet
  558. // Read the resource class.
  559. if (dwRetStatus == ERROR_SUCCESS)
  560. {
  561. DWORD cbReturned;
  562. dwStatus = ClusterResourceControl(
  563. Hresource(),
  564. NULL,
  565. CLUSCTL_RESOURCE_GET_CLASS_INFO,
  566. NULL,
  567. NULL,
  568. &m_rciResClassInfo,
  569. sizeof(m_rciResClassInfo),
  570. &cbReturned
  571. );
  572. if (dwStatus != ERROR_SUCCESS)
  573. dwRetStatus = dwStatus;
  574. else
  575. {
  576. ASSERT(cbReturned == sizeof(m_rciResClassInfo));
  577. } // else: data retrieved successfully
  578. } // if: no error yet
  579. // Read the characteristics.
  580. if (dwRetStatus == ERROR_SUCCESS)
  581. {
  582. DWORD cbReturned;
  583. dwStatus = ClusterResourceControl(
  584. Hresource(),
  585. NULL,
  586. CLUSCTL_RESOURCE_GET_CHARACTERISTICS,
  587. NULL,
  588. NULL,
  589. &m_dwCharacteristics,
  590. sizeof(m_dwCharacteristics),
  591. &cbReturned
  592. );
  593. if (dwStatus != ERROR_SUCCESS)
  594. dwRetStatus = dwStatus;
  595. else
  596. {
  597. ASSERT(cbReturned == sizeof(m_dwCharacteristics));
  598. } // else: data retrieved successfully
  599. } // if: no error yet
  600. // Read the flags.
  601. if (dwRetStatus == ERROR_SUCCESS)
  602. {
  603. DWORD cbReturned;
  604. dwStatus = ClusterResourceControl(
  605. Hresource(),
  606. NULL,
  607. CLUSCTL_RESOURCE_GET_FLAGS,
  608. NULL,
  609. NULL,
  610. &m_dwFlags,
  611. sizeof(m_dwFlags),
  612. &cbReturned
  613. );
  614. if (dwStatus != ERROR_SUCCESS)
  615. dwRetStatus = dwStatus;
  616. else
  617. {
  618. ASSERT(cbReturned == sizeof(m_dwFlags));
  619. } // else: data retrieved successfully
  620. } // if: no error yet
  621. // Construct the list of extensions.
  622. ReadExtensions();
  623. if (dwRetStatus == ERROR_SUCCESS)
  624. {
  625. // Construct the lists.
  626. CollectPossibleOwners(NULL);
  627. CollectDependencies(NULL);
  628. } // if: no error reading properties
  629. } // if: resource is available
  630. // Read the initial state.
  631. UpdateState();
  632. // If any errors occurred, throw an exception.
  633. if (dwRetStatus != ERROR_SUCCESS)
  634. {
  635. m_bReadOnly = TRUE;
  636. if ( (dwRetStatus != ERROR_RESOURCE_NOT_AVAILABLE)
  637. && (dwRetStatus != ERROR_KEY_DELETED))
  638. ThrowStaticException(dwRetStatus, IDS_READ_RESOURCE_PROPS_ERROR, StrName());
  639. } // if: error reading properties
  640. MarkAsChanged(FALSE);
  641. } //*** CResource::ReadItem()
  642. /////////////////////////////////////////////////////////////////////////////
  643. //++
  644. //
  645. // CResource::DwResourceControlGet
  646. //
  647. // Routine Description:
  648. // Send a control function to the resource to get information from it.
  649. //
  650. // Arguments:
  651. // dwFunctionCode [IN] Control function code.
  652. // pbInBuf [IN] Input buffer to pass to the resource.
  653. // cbInBuf [IN] Size of data in input buffer.
  654. // ppbOutBuf [OUT] Output buffer.
  655. //
  656. // Return Value:
  657. // Any status returned from ClusterResourceControl().
  658. //
  659. //--
  660. /////////////////////////////////////////////////////////////////////////////
  661. DWORD CResource::DwResourceControlGet(
  662. IN DWORD dwFunctionCode,
  663. IN PBYTE pbInBuf,
  664. IN DWORD cbInBuf,
  665. OUT PBYTE * ppbOutBuf
  666. )
  667. {
  668. DWORD dwStatus = ERROR_SUCCESS;
  669. DWORD cbOutBuf = 512;
  670. CWaitCursor wc;
  671. ASSERT(ppbOutBuf != NULL);
  672. *ppbOutBuf = NULL;
  673. // Allocate memory for the buffer.
  674. try
  675. {
  676. *ppbOutBuf = new BYTE[cbOutBuf];
  677. if ( *ppbOutBuf == NULL )
  678. {
  679. AfxThrowMemoryException();
  680. } // if: error allocating the output buffer
  681. } // try
  682. catch (CMemoryException * pme)
  683. {
  684. *ppbOutBuf = NULL;
  685. dwStatus = ERROR_NOT_ENOUGH_MEMORY;
  686. pme->Delete();
  687. } // catch: CMemoryException
  688. if (dwStatus != ERROR_SUCCESS)
  689. return dwStatus;
  690. // Call the control function to get the data.
  691. dwStatus = ClusterResourceControl(
  692. Hresource(),
  693. NULL,
  694. dwFunctionCode,
  695. pbInBuf,
  696. cbInBuf,
  697. *ppbOutBuf,
  698. cbOutBuf,
  699. &cbOutBuf
  700. );
  701. if (dwStatus == ERROR_MORE_DATA)
  702. {
  703. // Allocate more memory for the buffer.
  704. try
  705. {
  706. dwStatus = ERROR_SUCCESS;
  707. delete [] *ppbOutBuf;
  708. *ppbOutBuf = new BYTE[cbOutBuf];
  709. if ( *ppbOutBuf == NULL )
  710. {
  711. AfxThrowMemoryException();
  712. } // if: error allocating the output buffer
  713. } // try
  714. catch (CMemoryException * pme)
  715. {
  716. *ppbOutBuf = NULL;
  717. dwStatus = ERROR_NOT_ENOUGH_MEMORY;
  718. pme->Delete();
  719. } // catch: CMemoryException
  720. if (dwStatus != ERROR_SUCCESS)
  721. return dwStatus;
  722. // Call the control function again to get the data.
  723. dwStatus = ClusterResourceControl(
  724. Hresource(),
  725. NULL,
  726. dwFunctionCode,
  727. pbInBuf,
  728. cbInBuf,
  729. *ppbOutBuf,
  730. cbOutBuf,
  731. &cbOutBuf
  732. );
  733. } // if: our buffer is too small
  734. if ((dwStatus != ERROR_SUCCESS) || (cbOutBuf == 0))
  735. {
  736. delete [] *ppbOutBuf;
  737. *ppbOutBuf = NULL;
  738. } // if: error getting data or no data returned
  739. return dwStatus;
  740. } //*** CResource::DwResourceControlGet()
  741. /////////////////////////////////////////////////////////////////////////////
  742. //++
  743. //
  744. // CResource::PlstrExtension
  745. //
  746. // Routine Description:
  747. // Return the list of admin extensions.
  748. //
  749. // Arguments:
  750. // None.
  751. //
  752. // Return Value:
  753. // plstr List of extensions.
  754. // NULL No extension associated with this object.
  755. //
  756. // Exceptions Thrown:
  757. // None.
  758. //
  759. //--
  760. /////////////////////////////////////////////////////////////////////////////
  761. const CStringList * CResource::PlstrExtensions(void) const
  762. {
  763. return &LstrCombinedExtensions();
  764. } //*** CResource::PlstrExtensions()
  765. /////////////////////////////////////////////////////////////////////////////
  766. //++
  767. //
  768. // CResource::ReadExtensions
  769. //
  770. // Routine Description:
  771. // Read extension lists.
  772. //
  773. // Arguments:
  774. // None.
  775. //
  776. // Return Value:
  777. // None.
  778. //
  779. // Exceptions Thrown:
  780. // None.
  781. //
  782. //--
  783. /////////////////////////////////////////////////////////////////////////////
  784. void CResource::ReadExtensions(void)
  785. {
  786. CWaitCursor wc;
  787. // Construct the list of extensions.
  788. {
  789. POSITION posStr;
  790. const CStringList * plstr;
  791. ASSERT_VALID(Pdoc());
  792. m_lstrCombinedExtensions.RemoveAll();
  793. // Add resource-specific extensions first.
  794. if (PciResourceType() != NULL)
  795. {
  796. ASSERT_VALID(PciResourceType());
  797. plstr = &PciResourceType()->LstrAdminExtensions();
  798. posStr = plstr->GetHeadPosition();
  799. while (posStr != NULL)
  800. {
  801. m_lstrCombinedExtensions.AddTail(plstr->GetNext(posStr));
  802. } // while: more extensions available
  803. } // if: valid resource type found
  804. // Add extensions for all resources next.
  805. plstr = &Pdoc()->PciCluster()->LstrResourceExtensions();
  806. posStr = plstr->GetHeadPosition();
  807. while (posStr != NULL)
  808. {
  809. m_lstrCombinedExtensions.AddTail(plstr->GetNext(posStr));
  810. } // while: more extensions available
  811. } // Construct the list of extensions
  812. } //*** CResource::ReadExtensions()
  813. /////////////////////////////////////////////////////////////////////////////
  814. //++
  815. //
  816. // CResource::CollecPossibleOwners
  817. //
  818. // Routine Description:
  819. // Construct a list of node items which are enumerable on the
  820. // resource.
  821. //
  822. // Arguments:
  823. // plpci [IN OUT] List to fill.
  824. //
  825. // Return Value:
  826. // None.
  827. //
  828. // Exceptions Thrown:
  829. // CNTException Errors from ClusterResourceOpenEnum() or
  830. // ClusterResourceEnum().
  831. // Any exceptions thrown by new or CList::AddTail().
  832. //
  833. //--
  834. /////////////////////////////////////////////////////////////////////////////
  835. void CResource::CollectPossibleOwners(IN OUT CNodeList * plpci) const
  836. {
  837. DWORD dwStatus;
  838. HRESENUM hresenum;
  839. int ienum;
  840. LPWSTR pwszName = NULL;
  841. DWORD cchName;
  842. DWORD cchmacName;
  843. DWORD dwRetType;
  844. CClusterNode * pciNode;
  845. CWaitCursor wc;
  846. ASSERT_VALID(Pdoc());
  847. ASSERT(Hresource() != NULL);
  848. if (plpci == NULL)
  849. plpci = m_plpcinodePossibleOwners;
  850. ASSERT(plpci != NULL);
  851. // Remove the previous contents of the list.
  852. plpci->RemoveAll();
  853. if (Hresource() != NULL)
  854. {
  855. // Open the enumeration.
  856. hresenum = ClusterResourceOpenEnum(Hresource(), CLUSTER_RESOURCE_ENUM_NODES);
  857. if (hresenum == NULL)
  858. ThrowStaticException(GetLastError(), IDS_ENUM_POSSIBLE_OWNERS_ERROR, StrName());
  859. try
  860. {
  861. // Allocate a name buffer.
  862. cchmacName = 128;
  863. pwszName = new WCHAR[cchmacName];
  864. if ( pwszName == NULL )
  865. {
  866. AfxThrowMemoryException();
  867. } // if: error allocating the name buffer
  868. // Loop through the enumeration and add each dependent resource to the list.
  869. for (ienum = 0 ; ; ienum++)
  870. {
  871. // Get the next item in the enumeration.
  872. cchName = cchmacName;
  873. dwStatus = ClusterResourceEnum(hresenum, ienum, &dwRetType, pwszName, &cchName);
  874. if (dwStatus == ERROR_MORE_DATA)
  875. {
  876. delete [] pwszName;
  877. cchmacName = ++cchName;
  878. pwszName = new WCHAR[cchmacName];
  879. if ( pwszName == NULL )
  880. {
  881. AfxThrowMemoryException();
  882. } // if: error allocating the name buffer
  883. dwStatus = ClusterResourceEnum(hresenum, ienum, &dwRetType, pwszName, &cchName);
  884. } // if: name buffer was too small
  885. if (dwStatus == ERROR_NO_MORE_ITEMS)
  886. break;
  887. else if (dwStatus != ERROR_SUCCESS)
  888. ThrowStaticException(dwStatus, IDS_ENUM_POSSIBLE_OWNERS_ERROR, StrName());
  889. ASSERT(dwRetType == CLUSTER_RESOURCE_ENUM_NODES);
  890. // Find the item in the list of resources on the document.
  891. pciNode = Pdoc()->LpciNodes().PciNodeFromName(pwszName);
  892. ASSERT_VALID(pciNode);
  893. // Add the resource to the list.
  894. if (pciNode != NULL)
  895. {
  896. plpci->AddTail(pciNode);
  897. } // if: found node in list
  898. } // for: each item in the group
  899. delete [] pwszName;
  900. ClusterResourceCloseEnum(hresenum);
  901. } // try
  902. catch (CException *)
  903. {
  904. delete [] pwszName;
  905. ClusterResourceCloseEnum(hresenum);
  906. throw;
  907. } // catch: any exception
  908. } // if: resource is available
  909. } //*** CResource::CollecPossibleOwners()
  910. /*
  911. /////////////////////////////////////////////////////////////////////////////
  912. //++
  913. //
  914. // CResource::RemoveNodeFromPossibleOwners
  915. //
  916. // Routine Description:
  917. // Remove the passed in node from the possible owners list.
  918. //
  919. // Arguments:
  920. // plpci [IN OUT] List to fill.
  921. // pNode [IN] The node to remove from the list
  922. //
  923. // Return Value:
  924. // None.
  925. //
  926. // Exceptions Thrown:
  927. // Any exceptions thrown by CList.
  928. //
  929. //--
  930. /////////////////////////////////////////////////////////////////////////////
  931. void CResource::RemoveNodeFromPossibleOwners(
  932. IN OUT CNodeList * plpci,
  933. IN const CClusterNode * pNode
  934. )
  935. {
  936. if (plpci == NULL)
  937. {
  938. plpci = m_plpcinodePossibleOwners;
  939. } // if: plpci is NULL
  940. ASSERT(plpci != NULL);
  941. POSITION _pos;
  942. CClusterNode * _pnode = plpci->PciNodeFromName(pNode->StrName(), &_pos);
  943. if ((_pnode != NULL) && (_pos != NULL))
  944. {
  945. plpci->RemoveAt(_pos);
  946. } // if: node was found in the list
  947. } //*** CResource::RemoveNodeFromPossibleOwners()
  948. */
  949. /////////////////////////////////////////////////////////////////////////////
  950. //++
  951. //
  952. // CResource::CollectDependencies
  953. //
  954. // Routine Description:
  955. // Collect the resources on which this resource is dependent.
  956. //
  957. // Arguments:
  958. // plpci [IN OUT] List to fill.
  959. // bFullTree [IN] TRUE = collect dependencies of dependencies.
  960. //
  961. // Return Value:
  962. // None.
  963. //
  964. // Exceptions Thrown:
  965. // CNTException Errors from ClusterResourceOpenEnum() or
  966. // ClusterResourceEnum().
  967. // Any exceptions thrown by new or CList::AddTail().
  968. //
  969. //--
  970. /////////////////////////////////////////////////////////////////////////////
  971. void CResource::CollectDependencies(
  972. IN OUT CResourceList * plpci,
  973. IN BOOL bFullTree
  974. ) const
  975. {
  976. DWORD dwStatus;
  977. HRESENUM hresenum;
  978. int ienum;
  979. LPWSTR pwszName = NULL;
  980. DWORD cchName;
  981. DWORD cchmacName;
  982. DWORD dwRetType;
  983. CResource * pciRes;
  984. CWaitCursor wc;
  985. ASSERT_VALID(Pdoc());
  986. ASSERT(Hresource() != NULL);
  987. if (plpci == NULL)
  988. plpci = m_plpciresDependencies;
  989. ASSERT(plpci != NULL);
  990. // Remove the previous contents of the list.
  991. if (!bFullTree)
  992. plpci->RemoveAll();
  993. if (Hresource() != NULL)
  994. {
  995. // Open the enumeration.
  996. hresenum = ClusterResourceOpenEnum(Hresource(), CLUSTER_RESOURCE_ENUM_DEPENDS);
  997. if (hresenum == NULL)
  998. ThrowStaticException(GetLastError(), IDS_ENUM_DEPENDENCIES_ERROR, StrName());
  999. try
  1000. {
  1001. // Allocate a name buffer.
  1002. cchmacName = 128;
  1003. pwszName = new WCHAR[cchmacName];
  1004. if ( pwszName == NULL )
  1005. {
  1006. AfxThrowMemoryException();
  1007. } // if: error allocating the name buffer
  1008. // Loop through the enumeration and add each dependent resource to the list.
  1009. for (ienum = 0 ; ; ienum++)
  1010. {
  1011. // Get the next item in the enumeration.
  1012. cchName = cchmacName;
  1013. dwStatus = ClusterResourceEnum(hresenum, ienum, &dwRetType, pwszName, &cchName);
  1014. if (dwStatus == ERROR_MORE_DATA)
  1015. {
  1016. delete [] pwszName;
  1017. cchmacName = ++cchName;
  1018. pwszName = new WCHAR[cchmacName];
  1019. if ( pwszName == NULL )
  1020. {
  1021. AfxThrowMemoryException();
  1022. } // if: error allocating the name buffer
  1023. dwStatus = ClusterResourceEnum(hresenum, ienum, &dwRetType, pwszName, &cchName);
  1024. } // if: name buffer was too small
  1025. if (dwStatus == ERROR_NO_MORE_ITEMS)
  1026. break;
  1027. else if (dwStatus != ERROR_SUCCESS)
  1028. ThrowStaticException(dwStatus, IDS_ENUM_DEPENDENCIES_ERROR, StrName());
  1029. ASSERT(dwRetType == CLUSTER_RESOURCE_ENUM_DEPENDS);
  1030. // Find the item in the list of resources on the document and
  1031. // add its dependencies to the list.
  1032. pciRes = Pdoc()->LpciResources().PciResFromName(pwszName);
  1033. if (pciRes != NULL)
  1034. {
  1035. // Add this resource to the list.
  1036. if (plpci->Find(pciRes) == NULL)
  1037. {
  1038. plpci->AddTail(pciRes);
  1039. } // if: resource not in the list yet
  1040. // Add the resources on which this resource is dependent to the list.
  1041. if (bFullTree)
  1042. pciRes->CollectDependencies(plpci, bFullTree);
  1043. } // if: resource found in the list
  1044. } // for: each item in the group
  1045. delete [] pwszName;
  1046. ClusterResourceCloseEnum(hresenum);
  1047. } // try
  1048. catch (CException *)
  1049. {
  1050. delete [] pwszName;
  1051. if (hresenum != NULL)
  1052. ClusterResourceCloseEnum(hresenum);
  1053. throw;
  1054. } // catch: any exception
  1055. } // if: resource is available
  1056. } //*** CResource::CollectDependencies()
  1057. /////////////////////////////////////////////////////////////////////////////
  1058. //++
  1059. //
  1060. // CResource::CollectProvidesFor
  1061. //
  1062. // Routine Description:
  1063. // Collect the list of resources which are dependent on this resource.
  1064. //
  1065. // Arguments:
  1066. // plpci [IN OUT] List of resources.
  1067. // bFullTree [IN] TRUE = collect dependencies of dependencies.
  1068. //
  1069. // Return Value:
  1070. // None.
  1071. //
  1072. // Exceptions Thrown:
  1073. // CNTException Errors from ClusterResourceOpenEnum() or
  1074. // ClusterResourceEnum().
  1075. // Any exceptions thrown by CList::AddHead().
  1076. //
  1077. //--
  1078. /////////////////////////////////////////////////////////////////////////////
  1079. void CResource::CollectProvidesFor(
  1080. IN OUT CResourceList * plpci,
  1081. IN BOOL bFullTree
  1082. ) const
  1083. {
  1084. DWORD dwStatus;
  1085. HRESENUM hresenum = NULL;
  1086. WCHAR * pwszName = NULL;
  1087. int ienum;
  1088. DWORD cchName;
  1089. DWORD cchmacName;
  1090. DWORD dwType;
  1091. CResource * pciRes;
  1092. CWaitCursor wc;
  1093. ASSERT_VALID(this);
  1094. ASSERT(Hresource != NULL);
  1095. ASSERT(plpci != NULL);
  1096. // Remove the previous contents of the list.
  1097. if (!bFullTree)
  1098. plpci->RemoveAll();
  1099. if (Hresource() != NULL)
  1100. {
  1101. try
  1102. {
  1103. // Allocate a name buffer.
  1104. cchmacName = 128;
  1105. pwszName = new WCHAR[cchmacName];
  1106. if ( pwszName == NULL )
  1107. {
  1108. AfxThrowMemoryException();
  1109. } // if: error allocating the name buffer
  1110. // Open the enumeration.
  1111. hresenum = ClusterResourceOpenEnum(Hresource(), CLUSTER_RESOURCE_ENUM_PROVIDES);
  1112. if (hresenum == NULL)
  1113. ThrowStaticException(GetLastError(), IDS_ENUM_PROVIDES_FOR_ERROR, StrName());
  1114. // Loop through the enumeration and add each one's providers to the list.
  1115. for (ienum = 0 ; ; ienum++)
  1116. {
  1117. // Get the next item in the enumeration.
  1118. cchName = cchmacName;
  1119. dwStatus = ClusterResourceEnum(hresenum, ienum, &dwType, pwszName, &cchName);
  1120. if (dwStatus == ERROR_MORE_DATA)
  1121. {
  1122. delete [] pwszName;
  1123. cchmacName = ++cchName;
  1124. pwszName = new WCHAR[cchmacName];
  1125. if ( pwszName == NULL )
  1126. {
  1127. AfxThrowMemoryException();
  1128. } // if: error allocating the name buffer
  1129. dwStatus = ClusterResourceEnum(hresenum, ienum, &dwType, pwszName, &cchName);
  1130. } // if: name buffer was too small
  1131. if (dwStatus == ERROR_NO_MORE_ITEMS)
  1132. break;
  1133. else if (dwStatus != ERROR_SUCCESS)
  1134. ThrowStaticException(dwStatus, IDS_ENUM_PROVIDES_FOR_ERROR, StrName());
  1135. ASSERT(dwType == CLUSTER_RESOURCE_ENUM_PROVIDES);
  1136. // Find the item in the list of resources on the document and
  1137. // add its providers to the list.
  1138. pciRes = Pdoc()->LpciResources().PciResFromName(pwszName);
  1139. if (pciRes != NULL)
  1140. {
  1141. // Add this resource to the list.
  1142. if (plpci->Find(pciRes) == NULL)
  1143. {
  1144. plpci->AddHead(pciRes);
  1145. } // if: resource not in the list yet
  1146. // Add the resources this resource provides for to the list.
  1147. if (bFullTree)
  1148. pciRes->CollectProvidesFor(plpci, bFullTree);
  1149. } // if: resource found in the list
  1150. } // for: each dependent resource
  1151. // Close the enumeration.
  1152. delete [] pwszName;
  1153. pwszName = NULL;
  1154. ClusterResourceCloseEnum(hresenum);
  1155. hresenum = NULL;
  1156. } // try
  1157. catch (CException *)
  1158. {
  1159. delete [] pwszName;
  1160. if (hresenum != NULL)
  1161. ClusterResourceCloseEnum(hresenum);
  1162. throw;
  1163. } // catch: CException
  1164. } // if: resource is available
  1165. } //*** CResource::CollectProvidesFor()
  1166. /////////////////////////////////////////////////////////////////////////////
  1167. //++
  1168. //
  1169. // CResource::CollectDependencyTree
  1170. //
  1171. // Routine Description:
  1172. // Collect the resources on which this resource is dependent and which
  1173. // are dependent on it.
  1174. //
  1175. // Arguments:
  1176. // plpci [IN OUT] List to fill.
  1177. //
  1178. // Return Value:
  1179. // None.
  1180. //
  1181. // Exceptions Thrown:
  1182. // CNTException Errors from ClusterResourceOpenEnum() or
  1183. // ClusterResourceEnum().
  1184. // Any exceptions thrown by new or CList::AddTail().
  1185. //
  1186. //--
  1187. /////////////////////////////////////////////////////////////////////////////
  1188. void CResource::CollectDependencyTree(
  1189. IN OUT CResourceList * plpci
  1190. ) const
  1191. {
  1192. DWORD dwStatus;
  1193. HRESENUM hresenum = NULL;
  1194. int ienum;
  1195. LPWSTR pwszName = NULL;
  1196. DWORD cchName;
  1197. DWORD cchmacName;
  1198. DWORD dwRetType;
  1199. CResource * pciRes;
  1200. CWaitCursor wc;
  1201. int iType;
  1202. static DWORD rgdwType[] = { CLUSTER_RESOURCE_ENUM_DEPENDS, CLUSTER_RESOURCE_ENUM_PROVIDES };
  1203. static IDS rgidsTypeError[] = { IDS_ENUM_DEPENDENCIES_ERROR, IDS_ENUM_PROVIDES_FOR_ERROR };
  1204. ASSERT_VALID(Pdoc());
  1205. ASSERT(Hresource() != NULL);
  1206. ASSERT(plpci != NULL);
  1207. if (Hresource() != NULL)
  1208. {
  1209. try
  1210. {
  1211. // Allocate a name buffer.
  1212. cchmacName = 128;
  1213. pwszName = new WCHAR[cchmacName];
  1214. if ( pwszName == NULL )
  1215. {
  1216. AfxThrowMemoryException();
  1217. } // if: error allocating the name buffer
  1218. for (iType = 0 ; iType < sizeof(rgdwType) / sizeof(DWORD) ; iType++)
  1219. {
  1220. // Open the enumeration.
  1221. hresenum = ClusterResourceOpenEnum(Hresource(), rgdwType[iType]);
  1222. if (hresenum == NULL)
  1223. ThrowStaticException(GetLastError(), rgidsTypeError[iType], StrName());
  1224. // Loop through the enumeration and add each dependent or
  1225. // provider resource to the list.
  1226. for (ienum = 0 ; ; ienum++)
  1227. {
  1228. // Get the next item in the enumeration.
  1229. cchName = cchmacName;
  1230. dwStatus = ClusterResourceEnum(hresenum, ienum, &dwRetType, pwszName, &cchName);
  1231. if (dwStatus == ERROR_MORE_DATA)
  1232. {
  1233. delete [] pwszName;
  1234. cchmacName = ++cchName;
  1235. pwszName = new WCHAR[cchmacName];
  1236. if ( pwszName == NULL )
  1237. {
  1238. AfxThrowMemoryException();
  1239. } // if: error allocating the name buffer
  1240. dwStatus = ClusterResourceEnum(hresenum, ienum, &dwRetType, pwszName, &cchName);
  1241. } // if: name buffer was too small
  1242. if (dwStatus == ERROR_NO_MORE_ITEMS)
  1243. break;
  1244. else if (dwStatus != ERROR_SUCCESS)
  1245. ThrowStaticException(dwStatus, rgidsTypeError[iType], StrName());
  1246. ASSERT(dwRetType == rgdwType[iType]);
  1247. // Find the item in the list of resources on the document and
  1248. // add its dependencies and providers to the list.
  1249. pciRes = Pdoc()->LpciResources().PciResFromName(pwszName);
  1250. if (pciRes != NULL)
  1251. {
  1252. // Add this resource to the list.
  1253. if (plpci->Find(pciRes) == NULL)
  1254. {
  1255. plpci->AddTail(pciRes);
  1256. pciRes->CollectDependencyTree(plpci);
  1257. } // if: resource not in the list yet
  1258. } // if: resource found in the list
  1259. } // for: each item in the group
  1260. ClusterResourceCloseEnum(hresenum);
  1261. hresenum = NULL;
  1262. } // for: each type of enumeration
  1263. delete [] pwszName;
  1264. } // try
  1265. catch (CException *)
  1266. {
  1267. delete [] pwszName;
  1268. if (hresenum != NULL)
  1269. ClusterResourceCloseEnum(hresenum);
  1270. throw;
  1271. } // catch: any exception
  1272. } // if: resource is available
  1273. } //*** CResource::CollectDependencyTree()
  1274. /////////////////////////////////////////////////////////////////////////////
  1275. //++
  1276. //
  1277. // CResource::SetName
  1278. //
  1279. // Routine Description:
  1280. // Set the name of this resource.
  1281. //
  1282. // Arguments:
  1283. // pszName [IN] New name of the resource.
  1284. //
  1285. // Return Value:
  1286. // None.
  1287. //
  1288. // Exceptions Thrown:
  1289. // Any exceptions thrown by Rename.
  1290. //--
  1291. /////////////////////////////////////////////////////////////////////////////
  1292. void CResource::SetName(IN LPCTSTR pszName)
  1293. {
  1294. Rename(pszName);
  1295. } //*** CResource::SetName()
  1296. /////////////////////////////////////////////////////////////////////////////
  1297. //++
  1298. //
  1299. // CResource::SetGroup
  1300. //
  1301. // Routine Description:
  1302. // Set the group to which this resource belongs.
  1303. //
  1304. // Arguments:
  1305. // pszGroup [IN] New group for the resource.
  1306. //
  1307. // Return Value:
  1308. // None.
  1309. //
  1310. // Exceptions Thrown:
  1311. // CNTException IDS_MOVE_RESOURCE_ERROR - errors from
  1312. // ChangeClusterResourceGroup().
  1313. //--
  1314. /////////////////////////////////////////////////////////////////////////////
  1315. void CResource::SetGroup(IN LPCTSTR pszGroup)
  1316. {
  1317. DWORD dwStatus;
  1318. CGroup * pciGroup;
  1319. CString strGroup(pszGroup); // Required if built non-Unicode
  1320. CWaitCursor wc;
  1321. ASSERT(pszGroup != NULL);
  1322. ASSERT(Hresource() != NULL);
  1323. if ((Hresource() != NULL) && (StrGroup() != pszGroup))
  1324. {
  1325. // Find the group.
  1326. pciGroup = Pdoc()->LpciGroups().PciGroupFromName(pszGroup);
  1327. ASSERT_VALID(pciGroup);
  1328. // Change the group.
  1329. dwStatus = ChangeClusterResourceGroup(Hresource(), pciGroup->Hgroup());
  1330. if (dwStatus != ERROR_SUCCESS)
  1331. ThrowStaticException(dwStatus, IDS_MOVE_RESOURCE_ERROR, StrName(), pszGroup);
  1332. SetGroupState(pciGroup->StrName());
  1333. } // if: the name changed
  1334. } //*** CResource::SetGroup()
  1335. /////////////////////////////////////////////////////////////////////////////
  1336. //++
  1337. //
  1338. // CResource::SetDependencies
  1339. //
  1340. // Routine Description:
  1341. // Set the list of resources on which this resource depends on
  1342. // in the cluster database.
  1343. //
  1344. // Arguments:
  1345. // rlpci [IN] List of resources on which this resource depends on.
  1346. //
  1347. // Return Value:
  1348. // None.
  1349. //
  1350. // Exceptions Thrown:
  1351. // CNTException(dwStatus) Errors from AddClusterResourceDependency()
  1352. // and RemoveClusterResourceDependency().
  1353. //--
  1354. /////////////////////////////////////////////////////////////////////////////
  1355. void CResource::SetDependencies(IN const CResourceList & rlpci)
  1356. {
  1357. DWORD dwStatus;
  1358. CWaitCursor wc;
  1359. ASSERT(Hresource() != NULL);
  1360. if (Hresource() != NULL)
  1361. {
  1362. // Add any entries that are in the new last but not in the old list as
  1363. // new dependencies.
  1364. {
  1365. POSITION posPci;
  1366. CResource * pciRes;
  1367. posPci = rlpci.GetHeadPosition();
  1368. while (posPci != NULL)
  1369. {
  1370. pciRes = (CResource *) rlpci.GetNext(posPci);
  1371. ASSERT_VALID(pciRes);
  1372. if (LpciresDependencies().Find(pciRes) == NULL)
  1373. {
  1374. // Add the resource as a dependency of this one.
  1375. dwStatus = AddClusterResourceDependency(Hresource(), pciRes->Hresource());
  1376. if (dwStatus != ERROR_SUCCESS)
  1377. ThrowStaticException(dwStatus, IDS_ADD_DEPENDENCY_ERROR, pciRes->StrName(), StrName());
  1378. // Add the resource into our list.
  1379. m_plpciresDependencies->AddTail(pciRes);
  1380. } // if: item not found in existing list
  1381. } // while: more items in the list
  1382. } // Add new dependencies
  1383. // Delete any entries that are in the new old but not in the new list.
  1384. {
  1385. POSITION posPci;
  1386. POSITION posPrev;
  1387. CResource * pciRes;
  1388. posPci = LpciresDependencies().GetHeadPosition();
  1389. while (posPci != NULL)
  1390. {
  1391. posPrev = posPci;
  1392. pciRes = (CResource *) LpciresDependencies().GetNext(posPci);
  1393. if (rlpci.Find(pciRes) == NULL)
  1394. {
  1395. // Remove the resource as a dependency of this one.
  1396. dwStatus = RemoveClusterResourceDependency(Hresource(), pciRes->Hresource());
  1397. if (dwStatus != ERROR_SUCCESS)
  1398. ThrowStaticException(dwStatus, IDS_REMOVE_DEPENDENCY_ERROR, pciRes->StrName(), StrName());
  1399. // Remove the resource from our list.
  1400. m_plpciresDependencies->RemoveAt(posPrev);
  1401. } // if: item not found in new list
  1402. } // while: more items in the list
  1403. } // Remove old dependencies
  1404. } // if: resource is available
  1405. } //*** CResource::SetDependencies()
  1406. /////////////////////////////////////////////////////////////////////////////
  1407. //++
  1408. //
  1409. // CResource::SetPossibleOwners
  1410. //
  1411. // Routine Description:
  1412. // Set the list of possible owners of this resource in the cluster
  1413. // database.
  1414. //
  1415. // Arguments:
  1416. // rlpci [IN] List of possible owners (nodes).
  1417. //
  1418. // Return Value:
  1419. // None.
  1420. //
  1421. // Exceptions Thrown:
  1422. // CNTException IDS_TAKE_RESOURCE_OFFLINE_ERROR.
  1423. // CNTException(dwStatus) Errors from AddClusterResourceNode()
  1424. // and RemoveClusterResourceNode().
  1425. //--
  1426. /////////////////////////////////////////////////////////////////////////////
  1427. void CResource::SetPossibleOwners(IN const CNodeList & rlpci)
  1428. {
  1429. DWORD dwStatus;
  1430. CWaitCursor wc;
  1431. ASSERT(Hresource() != NULL);
  1432. if (Hresource() != NULL)
  1433. {
  1434. // If the list of possible owners is empty, make sure this resource
  1435. // is offline.
  1436. if ((rlpci.GetCount() == 0) && (Crs() == ClusterResourceOnline))
  1437. {
  1438. dwStatus = OfflineClusterResource(Hresource());
  1439. if ((dwStatus != ERROR_SUCCESS)
  1440. && (dwStatus != ERROR_IO_PENDING))
  1441. ThrowStaticException(dwStatus, IDS_TAKE_RESOURCE_OFFLINE_ERROR, StrName());
  1442. } // if: no possible owners
  1443. // Add any entries that are in the new list but not in the old list as
  1444. // new owners.
  1445. {
  1446. POSITION posPci;
  1447. CClusterNode * pciNode;
  1448. posPci = rlpci.GetHeadPosition();
  1449. while (posPci != NULL)
  1450. {
  1451. pciNode = (CClusterNode *) rlpci.GetNext(posPci);
  1452. ASSERT_VALID(pciNode);
  1453. if (LpcinodePossibleOwners().Find(pciNode) == NULL)
  1454. {
  1455. // Add the node as an owner of this resource.
  1456. dwStatus = AddClusterResourceNode(Hresource(), pciNode->Hnode());
  1457. if (dwStatus != ERROR_SUCCESS)
  1458. ThrowStaticException(dwStatus, IDS_ADD_RES_OWNER_ERROR, pciNode->StrName(), StrName());
  1459. // Add the node into our list.
  1460. m_plpcinodePossibleOwners->AddTail(pciNode);
  1461. } // if: item not found in existing list
  1462. } // while: more items in the list
  1463. } // Add new owner
  1464. // Delete any entries that are in the old but not in the new list.
  1465. {
  1466. POSITION posPci;
  1467. POSITION posPrev;
  1468. CClusterNode * pciNode;
  1469. posPci = LpcinodePossibleOwners().GetHeadPosition();
  1470. while (posPci != NULL)
  1471. {
  1472. posPrev = posPci;
  1473. pciNode = (CClusterNode *) LpcinodePossibleOwners().GetNext(posPci);
  1474. if (rlpci.Find(pciNode) == NULL)
  1475. {
  1476. // Remove the node as an owner of this resource.
  1477. dwStatus = RemoveClusterResourceNode(Hresource(), pciNode->Hnode());
  1478. if (dwStatus != ERROR_SUCCESS)
  1479. ThrowStaticException(dwStatus, IDS_REMOVE_RES_OWNER_ERROR, pciNode->StrName(), StrName());
  1480. // Remove the node from our list.
  1481. m_plpcinodePossibleOwners->RemoveAt(posPrev);
  1482. } // if: item not found in new list
  1483. } // while: more items in the list
  1484. } // Remove old owners
  1485. } // if: resource is available
  1486. } //*** CResource::SetPossibleOwners()
  1487. /////////////////////////////////////////////////////////////////////////////
  1488. //++
  1489. //
  1490. // CResource::SetCommonProperties
  1491. //
  1492. // Routine Description:
  1493. // Set the common properties for this resource in the cluster database.
  1494. //
  1495. // Arguments:
  1496. // rstrDesc [IN] Description string.
  1497. // bSeparate [IN] TRUE = run resource in separate monitor, FALSE = run with other resources.
  1498. // nLooksAlive [IN] Looks Alive poll interval.
  1499. // nIsAlive [IN] Is Alive poll interval.
  1500. // crra [IN] Restart action.
  1501. // nThreshold [IN] Restart threshold.
  1502. // nPeriod [IN] Restart period.
  1503. // nTimeout [IN] Pending timeout in minutes.
  1504. // bValidateOnly [IN] Only validate the data.
  1505. //
  1506. // Return Value:
  1507. // None.
  1508. //
  1509. // Exceptions Thrown:
  1510. // Any exceptions thrown by CClusterItem::SetCommonProperties().
  1511. //
  1512. //--
  1513. /////////////////////////////////////////////////////////////////////////////
  1514. void CResource::SetCommonProperties(
  1515. IN const CString & rstrDesc,
  1516. IN BOOL bSeparate,
  1517. IN DWORD nLooksAlive,
  1518. IN DWORD nIsAlive,
  1519. IN CRRA crra,
  1520. IN DWORD nThreshold,
  1521. IN DWORD nPeriod,
  1522. IN DWORD nTimeout,
  1523. IN BOOL bValidateOnly
  1524. )
  1525. {
  1526. CNTException nte(ERROR_SUCCESS, 0, NULL, NULL, FALSE /*bAutoDelete*/);
  1527. m_rgProps[epropDescription].m_value.pstr = (CString *) &rstrDesc;
  1528. m_rgProps[epropSeparateMonitor].m_value.pb = &bSeparate;
  1529. m_rgProps[epropLooksAlive].m_value.pdw = &nLooksAlive;
  1530. m_rgProps[epropIsAlive].m_value.pdw = &nIsAlive;
  1531. m_rgProps[epropRestartAction].m_value.pdw = (DWORD *) &crra;
  1532. m_rgProps[epropRestartThreshold].m_value.pdw = &nThreshold;
  1533. m_rgProps[epropRestartPeriod].m_value.pdw = &nPeriod;
  1534. m_rgProps[epropPendingTimeout].m_value.pdw = &nTimeout;
  1535. try
  1536. {
  1537. CClusterItem::SetCommonProperties(bValidateOnly);
  1538. } // try
  1539. catch (CNTException * pnte)
  1540. {
  1541. nte.SetOperation(
  1542. pnte->Sc(),
  1543. pnte->IdsOperation(),
  1544. pnte->PszOperArg1(),
  1545. pnte->PszOperArg2()
  1546. );
  1547. } // catch: CNTException
  1548. m_rgProps[epropDescription].m_value.pstr = &m_strDescription;
  1549. m_rgProps[epropSeparateMonitor].m_value.pb = &m_bSeparateMonitor;
  1550. m_rgProps[epropLooksAlive].m_value.pdw = &m_nLooksAlive;
  1551. m_rgProps[epropIsAlive].m_value.pdw = &m_nIsAlive;
  1552. m_rgProps[epropRestartAction].m_value.pdw = (DWORD *) &m_crraRestartAction;
  1553. m_rgProps[epropRestartThreshold].m_value.pdw = &m_nRestartThreshold;
  1554. m_rgProps[epropRestartPeriod].m_value.pdw = &m_nRestartPeriod;
  1555. m_rgProps[epropPendingTimeout].m_value.pdw = &m_nPendingTimeout;
  1556. if (nte.Sc() != ERROR_SUCCESS)
  1557. ThrowStaticException(
  1558. nte.Sc(),
  1559. nte.IdsOperation(),
  1560. nte.PszOperArg1(),
  1561. nte.PszOperArg2()
  1562. );
  1563. } //*** CResource::SetCommonProperties()
  1564. /////////////////////////////////////////////////////////////////////////////
  1565. //++
  1566. //
  1567. // CResource::DwSetCommonProperties
  1568. //
  1569. // Routine Description:
  1570. // Set the common properties for this resource in the cluster database.
  1571. //
  1572. // Arguments:
  1573. // rcpl [IN] Property list to set.
  1574. // bValidateOnly [IN] Only validate the data.
  1575. //
  1576. // Return Value:
  1577. // Any status returned by ClusterResourceControl().
  1578. //
  1579. //--
  1580. /////////////////////////////////////////////////////////////////////////////
  1581. DWORD CResource::DwSetCommonProperties(
  1582. IN const CClusPropList & rcpl,
  1583. IN BOOL bValidateOnly
  1584. )
  1585. {
  1586. DWORD dwStatus;
  1587. CWaitCursor wc;
  1588. ASSERT(Hresource());
  1589. if ((rcpl.PbPropList() != NULL) && (rcpl.CbPropList() > 0))
  1590. {
  1591. DWORD cbProps;
  1592. DWORD dwControl;
  1593. if (bValidateOnly)
  1594. dwControl = CLUSCTL_RESOURCE_VALIDATE_COMMON_PROPERTIES;
  1595. else
  1596. dwControl = CLUSCTL_RESOURCE_SET_COMMON_PROPERTIES;
  1597. // Set common properties.
  1598. dwStatus = ClusterResourceControl(
  1599. Hresource(),
  1600. NULL, // hNode
  1601. dwControl,
  1602. rcpl.PbPropList(),
  1603. rcpl.CbPropList(),
  1604. NULL, // lpOutBuffer
  1605. 0, // nOutBufferSize
  1606. &cbProps
  1607. );
  1608. } // if: there is data to set
  1609. else
  1610. dwStatus = ERROR_SUCCESS;
  1611. return dwStatus;
  1612. } //*** CResource::DwSetCommonProperties()
  1613. /////////////////////////////////////////////////////////////////////////////
  1614. //++
  1615. //
  1616. // CResource::BRequiredDependenciesPresent
  1617. //
  1618. // Routine Description:
  1619. // Determine if the specified list contains each required resource
  1620. // for this type of resource.
  1621. //
  1622. // Arguments:
  1623. // rlpciRes [IN] List of resources.
  1624. // rstrMissing [OUT] String in which to return a missing resource
  1625. // class name or type name.
  1626. //
  1627. // Return Value:
  1628. // None.
  1629. //
  1630. // Exceptions Thrown:
  1631. // Any exceptions thrown by CString::LoadString() or CString::operator=().
  1632. //
  1633. //--
  1634. /////////////////////////////////////////////////////////////////////////////
  1635. BOOL CResource::BRequiredDependenciesPresent(
  1636. IN const CResourceList & rlpciRes,
  1637. OUT CString & rstrMissing
  1638. )
  1639. {
  1640. POSITION pos;
  1641. BOOL bFound = TRUE;
  1642. const CResource * pciRes;
  1643. CLUSPROP_BUFFER_HELPER props;
  1644. if (Pcrd() == NULL)
  1645. return TRUE;
  1646. // Collect the list of required dependencies.
  1647. props.pRequiredDependencyValue = Pcrd();
  1648. // Loop through each required dependency and make sure
  1649. // there is a dependency on a resource of that type.
  1650. while (props.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK)
  1651. {
  1652. bFound = FALSE;
  1653. pos = rlpciRes.GetHeadPosition();
  1654. while (pos != NULL)
  1655. {
  1656. // Get the next resource.
  1657. pciRes = (CResource *) rlpciRes.GetNext(pos);
  1658. ASSERT_VALID(pciRes);
  1659. ASSERT_KINDOF(CResource, pciRes);
  1660. // If this is the right type, we've satisfied the
  1661. // requirement so exit the loop.
  1662. if (props.pSyntax->dw == CLUSPROP_SYNTAX_RESCLASS)
  1663. {
  1664. if (props.pResourceClassValue->rc == pciRes->ResClass())
  1665. {
  1666. bFound = TRUE;
  1667. props.pb += sizeof(*props.pResourceClassValue);
  1668. } // if: match found
  1669. } // if: resource class
  1670. else if (props.pSyntax->dw == CLUSPROP_SYNTAX_NAME)
  1671. {
  1672. if (pciRes->StrRealResourceType().CompareNoCase(props.pStringValue->sz) == 0)
  1673. {
  1674. bFound = TRUE;
  1675. props.pb += sizeof(*props.pStringValue) + ALIGN_CLUSPROP(props.pStringValue->cbLength);
  1676. } // if: match found
  1677. } // else if: resource name
  1678. else
  1679. {
  1680. ASSERT(0);
  1681. break;
  1682. } // else: unknown data type
  1683. if (bFound)
  1684. break;
  1685. } // while: more items in the list
  1686. // If a match was not found, changes cannot be applied.
  1687. if (!bFound)
  1688. {
  1689. if (props.pSyntax->dw == CLUSPROP_SYNTAX_RESCLASS)
  1690. {
  1691. if (!rstrMissing.LoadString(IDS_RESCLASS_UNKNOWN + props.pResourceClassValue->rc))
  1692. rstrMissing.LoadString(IDS_RESCLASS_UNKNOWN);
  1693. } // if: resource class not found
  1694. else if (props.pSyntax->dw == CLUSPROP_SYNTAX_NAME)
  1695. {
  1696. CResourceType * pciResType;
  1697. // Find the resource type in our list.
  1698. pciResType = (CResourceType *) Pdoc()->LpciResourceTypes().PciFromName(props.pStringValue->sz);
  1699. if (pciResType != NULL)
  1700. rstrMissing = pciResType->StrDisplayName();
  1701. else
  1702. rstrMissing = props.pStringValue->sz;
  1703. } // else if: resource type name not found
  1704. break;
  1705. } // if: not found
  1706. } // while: more dependencies required
  1707. return bFound;
  1708. } //*** CResource::BRequiredDependenciesPresent()
  1709. /////////////////////////////////////////////////////////////////////////////
  1710. //++
  1711. //
  1712. // CResource::DeleteResource
  1713. //
  1714. // Routine Description:
  1715. // Delete this resource and all dependent resources.
  1716. //
  1717. // Arguments:
  1718. // rlpci [IN] List of resources to delete in addition to this one.
  1719. //
  1720. // Return Value:
  1721. // None.
  1722. //
  1723. // Exceptions Thrown:
  1724. // Any exceptions thrown by CResource::DeleteResource().
  1725. //
  1726. //--
  1727. /////////////////////////////////////////////////////////////////////////////
  1728. void CResource::DeleteResource(IN const CResourceList & rlpci)
  1729. {
  1730. CWaitCursor wc;
  1731. // Delete each resource in the list.
  1732. {
  1733. POSITION pos;
  1734. CResource * pciRes;
  1735. pos = rlpci.GetHeadPosition();
  1736. while (pos != NULL)
  1737. {
  1738. pciRes = (CResource *) rlpci.GetNext(pos);
  1739. if (pciRes != NULL)
  1740. pciRes->DeleteResource();
  1741. } // while: more items in the list
  1742. } // Delete each resource in the list
  1743. // Delete this resource.
  1744. DeleteResource();
  1745. } //*** CResource::DeleteResource(rlpci)
  1746. /////////////////////////////////////////////////////////////////////////////
  1747. //++
  1748. //
  1749. // CResource::DeleteResource
  1750. //
  1751. // Routine Description:
  1752. // Delete this resource.
  1753. //
  1754. // Arguments:
  1755. // None.
  1756. //
  1757. // Return Value:
  1758. // None.
  1759. //
  1760. // Exceptions Thrown:
  1761. // CNTException Errors from DeleteClusterResource().
  1762. //
  1763. //--
  1764. /////////////////////////////////////////////////////////////////////////////
  1765. void CResource::DeleteResource(void)
  1766. {
  1767. DWORD dwStatus;
  1768. BOOL bWeTookOffline = FALSE;
  1769. CWaitCursor wc;
  1770. ASSERT(!BDeleting());
  1771. if (Hresource() != NULL)
  1772. {
  1773. // Make sure the resource is offline.
  1774. if ( (Crs() != ClusterResourceOffline)
  1775. && (Crs() != ClusterResourceFailed))
  1776. {
  1777. dwStatus = OfflineClusterResource(Hresource());
  1778. if (dwStatus == ERROR_IO_PENDING)
  1779. {
  1780. WaitForOffline();
  1781. if ( (Crs() != ClusterResourceOffline)
  1782. && (Crs() != ClusterResourceFailed))
  1783. {
  1784. ThrowStaticException(IDS_DELETE_RESOURCE_ERROR_OFFLINE_PENDING, StrName());
  1785. } // if: resource still not offline
  1786. } // if: offline pending
  1787. else if ( (dwStatus != ERROR_SUCCESS)
  1788. && (dwStatus != ERROR_FILE_NOT_FOUND)
  1789. && (dwStatus != ERROR_RESOURCE_NOT_AVAILABLE))
  1790. {
  1791. ThrowStaticException(dwStatus, IDS_TAKE_RESOURCE_OFFLINE_ERROR, StrName());
  1792. }
  1793. bWeTookOffline = TRUE;
  1794. } // if: resource is not offline
  1795. // Delete the resource itself.
  1796. Trace(g_tagResource, _T("(%s) DeleteResource() - Deleting '%s' (%x)"), Pdoc()->StrNode(), StrName(), this);
  1797. dwStatus = DeleteClusterResource(Hresource());
  1798. if ( (dwStatus != ERROR_SUCCESS)
  1799. && (dwStatus != ERROR_FILE_NOT_FOUND)
  1800. && (dwStatus != ERROR_RESOURCE_NOT_AVAILABLE))
  1801. {
  1802. if (bWeTookOffline)
  1803. {
  1804. OnlineClusterResource(Hresource());
  1805. }
  1806. ThrowStaticException(dwStatus, IDS_DELETE_RESOURCE_ERROR, StrName());
  1807. } // if: error occurred
  1808. m_bDeleting = TRUE;
  1809. UpdateState();
  1810. } // if: resource has been opened/created
  1811. } //*** CResource::DeleteResource()
  1812. /////////////////////////////////////////////////////////////////////////////
  1813. //++
  1814. //
  1815. // CResource::WaitForOffline
  1816. //
  1817. // Routine Description:
  1818. // Wait for the resource to go offline.
  1819. //
  1820. // Arguments:
  1821. // None.
  1822. //
  1823. // Return Value:
  1824. // None.
  1825. //
  1826. // Exceptions Thrown:
  1827. // Any exceptions thrown by CResource::Move().
  1828. //
  1829. //--
  1830. /////////////////////////////////////////////////////////////////////////////
  1831. void CResource::WaitForOffline( void )
  1832. {
  1833. CWaitForResourceOfflineDlg dlg( this, AfxGetMainWnd() );
  1834. dlg.DoModal();
  1835. UpdateState();
  1836. } //*** CResource::WaitForOffline()
  1837. /////////////////////////////////////////////////////////////////////////////
  1838. //++
  1839. //
  1840. // CResource::Move
  1841. //
  1842. // Routine Description:
  1843. // Move this resource and all dependent and depending resources to
  1844. // another group.
  1845. //
  1846. // Arguments:
  1847. // pciGroup [IN] Group to move resources to.
  1848. // rlpci [IN] List of resources to move in addition to this one.
  1849. //
  1850. // Return Value:
  1851. // None.
  1852. //
  1853. // Exceptions Thrown:
  1854. // Any exceptions thrown by CResource::Move().
  1855. //
  1856. //--
  1857. /////////////////////////////////////////////////////////////////////////////
  1858. void CResource::Move(
  1859. IN const CGroup * pciGroup,
  1860. IN const CResourceList & rlpci
  1861. )
  1862. {
  1863. CWaitCursor wc;
  1864. // Move each resource in the list.
  1865. {
  1866. POSITION pos;
  1867. CResource * pciRes;
  1868. pos = rlpci.GetHeadPosition();
  1869. while (pos != NULL)
  1870. {
  1871. pciRes = (CResource *) rlpci.GetNext(pos);
  1872. if (pciRes != NULL)
  1873. pciRes->Move(pciGroup);
  1874. } // while: more items in the list
  1875. } // Move each resource in the list
  1876. // Move this resource.
  1877. Move(pciGroup);
  1878. } //*** CResource::Move(rlpci)
  1879. /////////////////////////////////////////////////////////////////////////////
  1880. //++
  1881. //
  1882. // CResource::Move
  1883. //
  1884. // Routine Description:
  1885. // Move this resource.
  1886. //
  1887. // Arguments:
  1888. // pciGroup [IN] Group to move resources to.
  1889. //
  1890. // Return Value:
  1891. // None.
  1892. //
  1893. // Exceptions Thrown:
  1894. // CNTException Errors from ChangeClusterResourceGroup().
  1895. //
  1896. //--
  1897. /////////////////////////////////////////////////////////////////////////////
  1898. void CResource::Move(IN const CGroup * pciGroup)
  1899. {
  1900. DWORD dwStatus;
  1901. ASSERT_VALID(pciGroup);
  1902. if ((Hresource() != NULL)
  1903. && (pciGroup != NULL)
  1904. && (pciGroup->Hgroup() != NULL))
  1905. {
  1906. // Move the resource.
  1907. Trace(g_tagResource, _T("(%s) Move() - moving '%s' (%x) from '%s' (%x) to '%s' (%x)"), Pdoc()->StrNode(), StrName(), this, StrGroup(), PciGroup(), pciGroup->StrName(), pciGroup);
  1908. dwStatus = ChangeClusterResourceGroup(Hresource(), pciGroup->Hgroup());
  1909. if ((dwStatus != ERROR_SUCCESS)
  1910. && (dwStatus != ERROR_FILE_NOT_FOUND))
  1911. ThrowStaticException(dwStatus, IDS_MOVE_RESOURCE_ERROR, StrName(), pciGroup->StrName());
  1912. UpdateState();
  1913. } // if: resource has been opened/created
  1914. } //*** CResource::Move()
  1915. /////////////////////////////////////////////////////////////////////////////
  1916. //++
  1917. //
  1918. // CResource::OnFinalRelease
  1919. //
  1920. // Routine Description:
  1921. // Called when the last OLE reference to or from the object is released.
  1922. //
  1923. // Arguments:
  1924. // None.
  1925. //
  1926. // Return Value:
  1927. // None.
  1928. //
  1929. //--
  1930. /////////////////////////////////////////////////////////////////////////////
  1931. void CResource::OnFinalRelease(void)
  1932. {
  1933. // When the last reference for an automation object is released
  1934. // OnFinalRelease is called. The base class will automatically
  1935. // deletes the object. Add additional cleanup required for your
  1936. // object before calling the base class.
  1937. CClusterItem::OnFinalRelease();
  1938. } //*** CResource::OnFinalRelease()
  1939. /////////////////////////////////////////////////////////////////////////////
  1940. //++
  1941. //
  1942. // CResource::BCanBeDependent
  1943. //
  1944. // Routine Description:
  1945. // Determine whether this resource can be dependent on the specified one.
  1946. //
  1947. // Arguments:
  1948. // pciRes [IN] Resource to check.
  1949. //
  1950. // Return Value:
  1951. // TRUE Resource can be a dependent.
  1952. // FALSE Resource can NOT be a dependent.
  1953. //
  1954. //--
  1955. /////////////////////////////////////////////////////////////////////////////
  1956. BOOL CResource::BCanBeDependent(IN CResource * pciRes)
  1957. {
  1958. CWaitCursor wc;
  1959. ASSERT_VALID(pciRes);
  1960. if ((Hresource() != NULL)
  1961. && (pciRes->Hresource() != NULL)
  1962. && (pciRes != this)
  1963. && (StrGroup() == pciRes->StrGroup())
  1964. )
  1965. return ::CanResourceBeDependent(Hresource(), pciRes->Hresource());
  1966. else
  1967. return FALSE;
  1968. } //*** CResource::BCanBeDependent()
  1969. /////////////////////////////////////////////////////////////////////////////
  1970. //++
  1971. //
  1972. // CResource::BIsDependent
  1973. //
  1974. // Routine Description:
  1975. // Determine whether this resource is dependent on the specified one.
  1976. //
  1977. // Arguments:
  1978. // pciRes [IN] Resource to check.
  1979. //
  1980. // Return Value:
  1981. // TRUE Resource is a dependent.
  1982. // FALSE Resource is NOT a dependent.
  1983. //
  1984. //--
  1985. /////////////////////////////////////////////////////////////////////////////
  1986. BOOL CResource::BIsDependent(IN CResource * pciRes)
  1987. {
  1988. ASSERT_VALID(pciRes);
  1989. if ((m_plpciresDependencies != NULL)
  1990. && (LpciresDependencies().Find(pciRes) != NULL))
  1991. return TRUE;
  1992. else
  1993. return FALSE;
  1994. } //*** CResource::BIsDependent()
  1995. /////////////////////////////////////////////////////////////////////////////
  1996. //++
  1997. //
  1998. // CResource::BGetNetworkName
  1999. //
  2000. // Routine Description:
  2001. // Returns the name of the network name of the first Network Name
  2002. // resource on which the specified resource depends.
  2003. //
  2004. // Arguments:
  2005. // lpszNetName [OUT] String in which to return the network name.
  2006. // pcchNetName [IN OUT] Points to a variable that specifies the
  2007. // maximum size, in characters, of the buffer. This
  2008. // value should be large enough to contain
  2009. // MAX_COMPUTERNAME_LENGTH + 1 characters. Upon
  2010. // return it contains the actual number of characters
  2011. // copied.
  2012. //
  2013. // Return Value:
  2014. // TRUE Resource is dependent on a network name resource.
  2015. // FALSE Resource is NOT dependent on a network name resource.
  2016. //
  2017. //--
  2018. /////////////////////////////////////////////////////////////////////////////
  2019. BOOL CResource::BGetNetworkName(
  2020. OUT WCHAR * lpszNetName,
  2021. IN OUT DWORD * pcchNetName
  2022. )
  2023. {
  2024. CWaitCursor wc;
  2025. ASSERT_VALID(this);
  2026. ASSERT(m_hresource != NULL);
  2027. ASSERT(lpszNetName != NULL);
  2028. ASSERT(pcchNetName != NULL);
  2029. return GetClusterResourceNetworkName(m_hresource, lpszNetName, pcchNetName);
  2030. } //*** CResource::BGetNetworkName()
  2031. /////////////////////////////////////////////////////////////////////////////
  2032. //++
  2033. //
  2034. // CResource::BGetNetworkName
  2035. //
  2036. // Routine Description:
  2037. // Returns the name of the network name of the first Network Name
  2038. // resource on which the specified resource depends.
  2039. //
  2040. // Arguments:
  2041. // rstrNetName [OUT] String in which to return the network name.
  2042. //
  2043. // Return Value:
  2044. // TRUE Resource is dependent on a network name resource.
  2045. // FALSE Resource is NOT dependent on a network name resource.
  2046. //
  2047. //--
  2048. /////////////////////////////////////////////////////////////////////////////
  2049. BOOL CResource::BGetNetworkName(OUT CString & rstrNetName)
  2050. {
  2051. BOOL bSuccess;
  2052. WCHAR szNetName[MAX_COMPUTERNAME_LENGTH + 1];
  2053. DWORD nSize = sizeof(szNetName) / sizeof(WCHAR);
  2054. bSuccess = BGetNetworkName(szNetName, &nSize);
  2055. if (bSuccess)
  2056. rstrNetName = szNetName;
  2057. else
  2058. rstrNetName = _T("");
  2059. return bSuccess;
  2060. } //*** CResource::BGetNetworkName()
  2061. /////////////////////////////////////////////////////////////////////////////
  2062. //++
  2063. //
  2064. // CResource::UpdateState
  2065. //
  2066. // Routine Description:
  2067. // Update the current state of the item.
  2068. //
  2069. // Arguments:
  2070. // None.
  2071. //
  2072. // Return Value:
  2073. // None.
  2074. //
  2075. //--
  2076. /////////////////////////////////////////////////////////////////////////////
  2077. void CResource::UpdateState(void)
  2078. {
  2079. CClusterAdminApp * papp = GetClusterAdminApp();
  2080. WCHAR * pwszOwner = NULL;
  2081. WCHAR * pwszGroup = NULL;
  2082. WCHAR * prgwszOwner = NULL;
  2083. WCHAR * prgwszGroup = NULL;
  2084. DWORD cchOwner;
  2085. DWORD cchGroup;
  2086. DWORD sc;
  2087. DWORD oldcchOwner;
  2088. DWORD oldcchGroup;
  2089. Trace(g_tagResource, _T("(%s) (%s (%x)) - Updating state"), Pdoc()->StrNode(), StrName(), this);
  2090. // Get the current state of the resource.
  2091. if (Hresource() == NULL)
  2092. m_crs = ClusterResourceStateUnknown;
  2093. else
  2094. {
  2095. CWaitCursor wc;
  2096. cchOwner = 100;
  2097. oldcchOwner = cchOwner;
  2098. prgwszOwner = new WCHAR[cchOwner];
  2099. if( prgwszOwner == NULL )
  2100. {
  2101. AfxThrowMemoryException();
  2102. } // if: error allocating the buffer
  2103. cchGroup = 100;
  2104. oldcchGroup = cchGroup;
  2105. prgwszGroup = new WCHAR[cchGroup];
  2106. if( prgwszGroup == NULL )
  2107. {
  2108. AfxThrowMemoryException();
  2109. } // if: error allocating the buffer
  2110. m_crs = GetClusterResourceState(Hresource(), prgwszOwner, &cchOwner, prgwszGroup, &cchGroup);
  2111. sc = GetLastError();
  2112. if( sc == ERROR_MORE_DATA )
  2113. {
  2114. //
  2115. // Increment before the check. This way we'll know whether we'll need to resize the buffer,
  2116. // and if not then we report it as being just big enough.
  2117. //
  2118. cchOwner++;
  2119. if( cchOwner > oldcchOwner )
  2120. {
  2121. delete [] prgwszOwner;
  2122. oldcchOwner = cchOwner;
  2123. prgwszOwner = new WCHAR[cchOwner];
  2124. if( prgwszOwner == NULL )
  2125. {
  2126. AfxThrowMemoryException();
  2127. } // if: error allocating the buffer
  2128. }
  2129. cchGroup++;
  2130. if( cchGroup > oldcchGroup )
  2131. {
  2132. delete [] prgwszGroup;
  2133. oldcchGroup = cchGroup;
  2134. prgwszGroup = new WCHAR[cchGroup];
  2135. if( prgwszGroup == NULL )
  2136. {
  2137. AfxThrowMemoryException();
  2138. } // if: error allocating the buffer
  2139. }
  2140. //
  2141. // Note that it's possible that the owning group or node changed since the last call to
  2142. // GetClusterResourceState. In that case our buffers may still be too small. Hit F5 to refresh.
  2143. //
  2144. m_crs = GetClusterResourceState(Hresource(), prgwszOwner, &cchOwner, prgwszGroup, &cchGroup);
  2145. }
  2146. pwszOwner = prgwszOwner;
  2147. pwszGroup = prgwszGroup;
  2148. } // else: resource is available
  2149. // Save the current state image index.
  2150. switch (Crs())
  2151. {
  2152. case ClusterResourceStateUnknown:
  2153. m_iimgState = papp->Iimg(IMGLI_RES_UNKNOWN);
  2154. pwszOwner = NULL;
  2155. pwszGroup = NULL;
  2156. break;
  2157. case ClusterResourceOnline:
  2158. m_iimgState = papp->Iimg(IMGLI_RES);
  2159. break;
  2160. case ClusterResourceOnlinePending:
  2161. m_iimgState = papp->Iimg(IMGLI_RES_PENDING);
  2162. break;
  2163. case ClusterResourceOffline:
  2164. m_iimgState = papp->Iimg(IMGLI_RES_OFFLINE);
  2165. break;
  2166. case ClusterResourceOfflinePending:
  2167. m_iimgState = papp->Iimg(IMGLI_RES_PENDING);
  2168. break;
  2169. case ClusterResourceFailed:
  2170. m_iimgState = papp->Iimg(IMGLI_RES_FAILED);
  2171. break;
  2172. default:
  2173. Trace(g_tagResource, _T("(%s) (%s (%x)) - UpdateState: Unknown state '%d' for resource '%s'"), Pdoc()->StrNode(), StrName(), this, Crs(), StrName());
  2174. m_iimgState = (UINT) -1;
  2175. break;
  2176. } // switch: Crs()
  2177. SetOwnerState(pwszOwner);
  2178. SetGroupState(pwszGroup);
  2179. if( NULL != prgwszOwner )
  2180. {
  2181. delete [] prgwszOwner;
  2182. }
  2183. if( NULL != prgwszGroup )
  2184. {
  2185. delete [] prgwszGroup;
  2186. }
  2187. // Call the base class method.
  2188. CClusterItem::UpdateState();
  2189. } //*** CResource::UpdateState()
  2190. /////////////////////////////////////////////////////////////////////////////
  2191. //++
  2192. //
  2193. // CResource::SetOwnerState
  2194. //
  2195. // Routine Description:
  2196. // Set a new owner for this resource.
  2197. //
  2198. // Arguments:
  2199. // pszNewOwner [IN] Name of the new owner.
  2200. //
  2201. // Return Value:
  2202. // None.
  2203. //
  2204. //--
  2205. /////////////////////////////////////////////////////////////////////////////
  2206. void CResource::SetOwnerState(IN LPCTSTR pszNewOwner)
  2207. {
  2208. CClusterNode * pciOldOwner = PciOwner();
  2209. CClusterNode * pciNewOwner;
  2210. Trace(g_tagResource, _T("(%s) (%s (%x)) - Setting owner to '%s'"), Pdoc()->StrNode(), StrName(), this, pszNewOwner);
  2211. if (pszNewOwner == NULL)
  2212. pciNewOwner = NULL;
  2213. else
  2214. pciNewOwner = Pdoc()->LpciNodes().PciNodeFromName(pszNewOwner);
  2215. if (pciNewOwner != pciOldOwner)
  2216. {
  2217. #ifdef _DEBUG
  2218. if (g_tagResource.BAny())
  2219. {
  2220. CString strMsg;
  2221. CString strMsg2;
  2222. strMsg.Format(_T("(%s) (%s (%x)) - Changing owner from "), Pdoc()->StrNode(), StrName(), this);
  2223. if (pciOldOwner == NULL)
  2224. strMsg += _T("nothing ");
  2225. else
  2226. {
  2227. strMsg2.Format(_T("'%s' "), pciOldOwner->StrName());
  2228. strMsg += strMsg2;
  2229. } // else: previous owner
  2230. if (pciNewOwner == NULL)
  2231. strMsg += _T("to nothing");
  2232. else
  2233. {
  2234. strMsg2.Format(_T("to '%s'"), pciNewOwner->StrName());
  2235. strMsg += strMsg2;
  2236. } // else: new owner
  2237. Trace(g_tagResource, strMsg);
  2238. } // if: trace tag turned on
  2239. #endif
  2240. m_strOwner = pszNewOwner;
  2241. m_pciOwner = pciNewOwner;
  2242. // Update reference counts.
  2243. if (pciOldOwner != NULL)
  2244. pciOldOwner->Release();
  2245. if (pciNewOwner != NULL)
  2246. pciNewOwner->AddRef();
  2247. if (BDocObj())
  2248. {
  2249. if (pciOldOwner != NULL)
  2250. pciOldOwner->RemoveActiveResource(this);
  2251. if (pciNewOwner != NULL)
  2252. pciNewOwner->AddActiveResource(this);
  2253. } // if: this is a document object
  2254. } // if: owner changed
  2255. else if ((pszNewOwner != NULL) && (StrOwner() != pszNewOwner))
  2256. m_strOwner = pszNewOwner;
  2257. } //*** CResource::SetOwnerState()
  2258. /////////////////////////////////////////////////////////////////////////////
  2259. //++
  2260. //
  2261. // CResource::SetGroupState
  2262. //
  2263. // Routine Description:
  2264. // Set a new group for this resource.
  2265. //
  2266. // Arguments:
  2267. // pszNewGroup [IN] Name of the new group.
  2268. //
  2269. // Return Value:
  2270. // None.
  2271. //
  2272. //--
  2273. /////////////////////////////////////////////////////////////////////////////
  2274. void CResource::SetGroupState(IN LPCTSTR pszNewGroup)
  2275. {
  2276. CGroup * pciOldGroup = PciGroup();
  2277. CGroup * pciNewGroup;
  2278. Trace(g_tagResource, _T("(%s) (%s (%x)) - Setting group to '%s'"), Pdoc()->StrNode(), StrName(), this, (pszNewGroup == NULL ? _T("") : pszNewGroup));
  2279. if (pszNewGroup == NULL)
  2280. pciNewGroup = NULL;
  2281. else
  2282. pciNewGroup = Pdoc()->LpciGroups().PciGroupFromName(pszNewGroup);
  2283. if (pciNewGroup != pciOldGroup)
  2284. {
  2285. #ifdef _DEBUG
  2286. if (g_tagResource.BAny())
  2287. {
  2288. CString strMsg;
  2289. CString strMsg2;
  2290. strMsg.Format(_T("(%s) (%s (%x)) - Changing group from "), Pdoc()->StrNode(), StrName(), this);
  2291. if (pciOldGroup == NULL)
  2292. strMsg += _T("nothing ");
  2293. else
  2294. {
  2295. strMsg2.Format(_T("'%s' "), pciOldGroup->StrName());
  2296. strMsg += strMsg2;
  2297. } // else: previous group
  2298. if (pciNewGroup == NULL)
  2299. strMsg += _T("to nothing");
  2300. else
  2301. {
  2302. strMsg2.Format(_T("to '%s'"), pciNewGroup->StrName());
  2303. strMsg += strMsg2;
  2304. } // else: new group
  2305. Trace(g_tagResource, strMsg);
  2306. } // if: trace tag turned on
  2307. #endif
  2308. m_strGroup = pszNewGroup;
  2309. m_pciGroup = pciNewGroup;
  2310. // Update reference counts.
  2311. if (pciOldGroup != NULL)
  2312. pciOldGroup->Release();
  2313. if (pciNewGroup != NULL)
  2314. pciNewGroup->AddRef();
  2315. if (BDocObj())
  2316. {
  2317. if (pciOldGroup != NULL)
  2318. pciOldGroup->RemoveResource(this);
  2319. if (pciNewGroup != NULL)
  2320. pciNewGroup->AddResource(this);
  2321. } // if: this is a document object
  2322. } // if: owner changed
  2323. else if ((pszNewGroup != NULL) && (StrGroup() != pszNewGroup))
  2324. m_strGroup = pszNewGroup;
  2325. } //*** CResource::SetGroupState()
  2326. /////////////////////////////////////////////////////////////////////////////
  2327. //++
  2328. //
  2329. // CResource::BGetColumnData
  2330. //
  2331. // Routine Description:
  2332. // Returns a string with the column data.
  2333. //
  2334. // Arguments:
  2335. // colid [IN] Column ID.
  2336. // rstrText [OUT] String in which to return the text for the column.
  2337. //
  2338. // Return Value:
  2339. // TRUE Column data returned.
  2340. // FALSE Column ID not recognized.
  2341. //
  2342. //--
  2343. /////////////////////////////////////////////////////////////////////////////
  2344. BOOL CResource::BGetColumnData(IN COLID colid, OUT CString & rstrText)
  2345. {
  2346. BOOL bSuccess;
  2347. switch (colid)
  2348. {
  2349. case IDS_COLTEXT_STATE:
  2350. GetStateName(rstrText);
  2351. bSuccess = TRUE;
  2352. break;
  2353. case IDS_COLTEXT_RESTYPE:
  2354. rstrText = StrRealResourceTypeDisplayName();
  2355. bSuccess = TRUE;
  2356. break;
  2357. case IDS_COLTEXT_OWNER:
  2358. rstrText = StrOwner();
  2359. bSuccess = TRUE;
  2360. break;
  2361. case IDS_COLTEXT_GROUP:
  2362. if (PciGroup() == NULL)
  2363. rstrText = StrGroup();
  2364. else
  2365. rstrText = PciGroup()->StrName();
  2366. bSuccess = TRUE;
  2367. break;
  2368. case IDS_COLTEXT_RESOURCE: // This is for showing dependencies
  2369. colid = IDS_COLTEXT_NAME;
  2370. // FALL THROUGH
  2371. default:
  2372. bSuccess = CClusterItem::BGetColumnData(colid, rstrText);
  2373. break;
  2374. } // switch: colid
  2375. return bSuccess;
  2376. } //*** CResource::BGetColumnData()
  2377. /////////////////////////////////////////////////////////////////////////////
  2378. //++
  2379. //
  2380. // CResource::GetTreeName
  2381. //
  2382. // Routine Description:
  2383. // Returns a string to be used in a tree control.
  2384. //
  2385. // Arguments:
  2386. // rstrName [OUT] String in which to return the name.
  2387. //
  2388. // Return Value:
  2389. // None.
  2390. //
  2391. //--
  2392. /////////////////////////////////////////////////////////////////////////////
  2393. #ifdef _DISPLAY_STATE_TEXT_IN_TREE
  2394. void CResource::GetTreeName(OUT CString & rstrName) const
  2395. {
  2396. CString strState;
  2397. GetStateName(strState);
  2398. rstrName.Format(_T("%s (%s)"), StrName(), strState);
  2399. } //*** CResource::GetTreeName()
  2400. #endif
  2401. /////////////////////////////////////////////////////////////////////////////
  2402. //++
  2403. //
  2404. // CResource::GetStateName
  2405. //
  2406. // Routine Description:
  2407. // Returns a string with the name of the current state.
  2408. //
  2409. // Arguments:
  2410. // rstrState [OUT] String in which to return the name of the current state.
  2411. //
  2412. // Return Value:
  2413. // None.
  2414. //
  2415. //--
  2416. /////////////////////////////////////////////////////////////////////////////
  2417. void CResource::GetStateName(OUT CString & rstrState) const
  2418. {
  2419. switch (Crs())
  2420. {
  2421. case ClusterResourceStateUnknown:
  2422. rstrState.LoadString(IDS_UNKNOWN);
  2423. break;
  2424. case ClusterResourceOnline:
  2425. rstrState.LoadString(IDS_ONLINE);
  2426. break;
  2427. case ClusterResourceOnlinePending:
  2428. rstrState.LoadString(IDS_ONLINE_PENDING);
  2429. break;
  2430. case ClusterResourceOffline:
  2431. rstrState.LoadString(IDS_OFFLINE);
  2432. break;
  2433. case ClusterResourceOfflinePending:
  2434. rstrState.LoadString(IDS_OFFLINE_PENDING);
  2435. break;
  2436. case ClusterResourceFailed:
  2437. rstrState.LoadString(IDS_FAILED);
  2438. break;
  2439. default:
  2440. rstrState.Empty();
  2441. break;
  2442. } // switch: Crs()
  2443. } //*** CResource::GetStateName()
  2444. /////////////////////////////////////////////////////////////////////////////
  2445. //++
  2446. //
  2447. // CResource::BCanBeEdited
  2448. //
  2449. // Routine Description:
  2450. // Determines if the resource can be renamed.
  2451. //
  2452. // Arguments:
  2453. // None.
  2454. //
  2455. // Return Value:
  2456. // TRUE Resource can be renamed.
  2457. // FALSE Resource cannot be renamed.
  2458. //
  2459. //--
  2460. /////////////////////////////////////////////////////////////////////////////
  2461. BOOL CResource::BCanBeEdited(void) const
  2462. {
  2463. BOOL bCanBeEdited;
  2464. if ( (Crs() == ClusterResourceStateUnknown)
  2465. || BReadOnly())
  2466. bCanBeEdited = FALSE;
  2467. else
  2468. bCanBeEdited = TRUE;
  2469. return bCanBeEdited;
  2470. } //*** CResource::BCanBeEdited()
  2471. /////////////////////////////////////////////////////////////////////////////
  2472. //++
  2473. //
  2474. // CResource::Rename
  2475. //
  2476. // Routine Description:
  2477. // Rename the resource.
  2478. //
  2479. // Arguments:
  2480. // pszName [IN] New name to give to the resource.
  2481. //
  2482. // Return Value:
  2483. // None.
  2484. //
  2485. // Exceptions Thrown:
  2486. // CNTException Errors returned from SetClusterResourceName().
  2487. //
  2488. //--
  2489. /////////////////////////////////////////////////////////////////////////////
  2490. void CResource::Rename(IN LPCTSTR pszName)
  2491. {
  2492. DWORD dwStatus;
  2493. CWaitCursor wc;
  2494. ASSERT(Hresource() != NULL);
  2495. if (StrName() != pszName)
  2496. {
  2497. dwStatus = SetClusterResourceName(Hresource(), pszName);
  2498. if (dwStatus != ERROR_SUCCESS)
  2499. ThrowStaticException(dwStatus, IDS_RENAME_RESOURCE_ERROR, StrName(), pszName);
  2500. m_strName = pszName;
  2501. } // if: the name changed
  2502. } //*** CResource::Rename()
  2503. /////////////////////////////////////////////////////////////////////////////
  2504. //++
  2505. //
  2506. // CResource::OnCmdMsg
  2507. //
  2508. // Routine Description:
  2509. // Processes command messages.
  2510. //
  2511. // Arguments:
  2512. // nID [IN] Command ID.
  2513. // nCode [IN] Notification code.
  2514. // pExtra [IN OUT] Used according to the value of nCode.
  2515. // pHandlerInfo [OUT] ???
  2516. //
  2517. // Return Value:
  2518. // TRUE Message has been handled.
  2519. // FALSE Message has NOT been handled.
  2520. //
  2521. //--
  2522. /////////////////////////////////////////////////////////////////////////////
  2523. BOOL CResource::OnCmdMsg(
  2524. UINT nID,
  2525. int nCode,
  2526. void * pExtra,
  2527. AFX_CMDHANDLERINFO * pHandlerInfo
  2528. )
  2529. {
  2530. BOOL bHandled = FALSE;
  2531. // If this is a MOVE_RESOURCE command, process it here.
  2532. if ((ID_FILE_MOVE_RESOURCE_1 <= nID) && (nID <= ID_FILE_MOVE_RESOURCE_20))
  2533. {
  2534. Trace(g_tagResource, _T("(%s) OnCmdMsg() %s (%x) - ID = %d, code = %d"), Pdoc()->StrNode(), StrName(), this, nID, nCode);
  2535. if (nCode == 0)
  2536. {
  2537. OnCmdMoveResource(nID);
  2538. bHandled = TRUE;
  2539. } // if: code = 0
  2540. } // if: move resource
  2541. if (!bHandled)
  2542. bHandled = CClusterItem::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
  2543. return bHandled;
  2544. } //*** CResource::OnCmdMsg()
  2545. /////////////////////////////////////////////////////////////////////////////
  2546. //++
  2547. //
  2548. // CResource::OnUpdateBringOnline
  2549. //
  2550. // Routine Description:
  2551. // Determines whether menu items corresponding to ID_FILE_BRING_ONLINE
  2552. // should be enabled or not.
  2553. //
  2554. // Arguments:
  2555. // pCmdUI [IN OUT] Command routing object.
  2556. //
  2557. // Return Value:
  2558. // None.
  2559. //
  2560. //--
  2561. /////////////////////////////////////////////////////////////////////////////
  2562. void CResource::OnUpdateBringOnline(CCmdUI * pCmdUI)
  2563. {
  2564. if ((Crs() != ClusterResourceOnline)
  2565. && (Crs() != ClusterResourceOnlinePending)
  2566. && (Crs() != ClusterResourceStateUnknown))
  2567. pCmdUI->Enable(TRUE);
  2568. else
  2569. pCmdUI->Enable(FALSE);
  2570. } //*** CResource::OnUpdateBringOnline()
  2571. /////////////////////////////////////////////////////////////////////////////
  2572. //++
  2573. //
  2574. // CResource::OnUpdateTakeOffline
  2575. //
  2576. // Routine Description:
  2577. // Determines whether menu items corresponding to ID_FILE_TAKE_OFFLINE
  2578. // should be enabled or not.
  2579. //
  2580. // Arguments:
  2581. // pCmdUI [IN OUT] Command routing object.
  2582. //
  2583. // Return Value:
  2584. // None.
  2585. //
  2586. //--
  2587. /////////////////////////////////////////////////////////////////////////////
  2588. void CResource::OnUpdateTakeOffline(CCmdUI * pCmdUI)
  2589. {
  2590. if (Crs() == ClusterResourceOnline)
  2591. pCmdUI->Enable(TRUE);
  2592. else
  2593. pCmdUI->Enable(FALSE);
  2594. } //*** CResource::OnUpdateTakeOffline()
  2595. /////////////////////////////////////////////////////////////////////////////
  2596. //++
  2597. //
  2598. // CResource::OnUpdateInitiateFailure
  2599. //
  2600. // Routine Description:
  2601. // Determines whether menu items corresponding to ID_FILE_INITIATE_FAILURE
  2602. // should be enabled or not.
  2603. //
  2604. // Arguments:
  2605. // pCmdUI [IN OUT] Command routing object.
  2606. //
  2607. // Return Value:
  2608. // None.
  2609. //
  2610. //--
  2611. /////////////////////////////////////////////////////////////////////////////
  2612. void CResource::OnUpdateInitiateFailure(CCmdUI * pCmdUI)
  2613. {
  2614. if (Crs() == ClusterResourceOnline)
  2615. pCmdUI->Enable(TRUE);
  2616. else
  2617. pCmdUI->Enable(FALSE);
  2618. } //*** CResource::OnUpdateInitiateFailure()
  2619. /////////////////////////////////////////////////////////////////////////////
  2620. //++
  2621. //
  2622. // CResource::OnUpdateMoveResource1
  2623. //
  2624. // Routine Description:
  2625. // Determines whether menu items corresponding to
  2626. // ID_FILE_MOVE_RESOURCE_1 should be enabled or not.
  2627. //
  2628. // Arguments:
  2629. // pCmdUI [IN OUT] Command routing object.
  2630. //
  2631. // Return Value:
  2632. // None.
  2633. //
  2634. //--
  2635. /////////////////////////////////////////////////////////////////////////////
  2636. void CResource::OnUpdateMoveResource1(CCmdUI * pCmdUI)
  2637. {
  2638. if (pCmdUI->m_pSubMenu == NULL)
  2639. {
  2640. CString strMenuName;
  2641. if ((pCmdUI->m_pMenu != NULL) && (pCmdUI->m_pSubMenu == NULL))
  2642. pCmdUI->m_pMenu->GetMenuString(pCmdUI->m_nID, strMenuName, MF_BYCOMMAND);
  2643. if ((strMenuName != StrGroup())
  2644. && ((Crs() == ClusterResourceOnline)
  2645. || (Crs() == ClusterResourceOffline)))
  2646. pCmdUI->Enable(TRUE);
  2647. else
  2648. pCmdUI->Enable(FALSE);
  2649. } // if: nested menu is being displayed
  2650. else
  2651. {
  2652. BOOL bEnabled;
  2653. if (Pdoc()->LpciGroups().GetCount() < 2)
  2654. bEnabled = FALSE;
  2655. else
  2656. {
  2657. POSITION pos;
  2658. UINT imenu;
  2659. UINT idMenu;
  2660. UINT cmenu;
  2661. CGroup * pciGroup;
  2662. CMenu * pmenu = pCmdUI->m_pSubMenu;
  2663. bEnabled = TRUE;
  2664. // Delete the items in the menu.
  2665. cmenu = pmenu->GetMenuItemCount();
  2666. while (cmenu-- > 0)
  2667. pmenu->DeleteMenu(0, MF_BYPOSITION);
  2668. // Add each group to the menu.
  2669. pos = Pdoc()->LpciGroups().GetHeadPosition();
  2670. for (imenu = 0, idMenu = ID_FILE_MOVE_RESOURCE_1
  2671. ; pos != NULL
  2672. ; idMenu++)
  2673. {
  2674. pciGroup = (CGroup *) Pdoc()->LpciGroups().GetNext(pos);
  2675. ASSERT_VALID(pciGroup);
  2676. pmenu->InsertMenu(
  2677. imenu++,
  2678. MF_BYPOSITION,
  2679. idMenu,
  2680. pciGroup->StrName()
  2681. );
  2682. } // for: each group
  2683. } // else: move user is available
  2684. // Enable or disable the Move menu.
  2685. pCmdUI->m_pMenu->EnableMenuItem(
  2686. pCmdUI->m_nIndex,
  2687. MF_BYPOSITION
  2688. | (bEnabled ? MF_ENABLED : MF_GRAYED)
  2689. );
  2690. } // else: top-level menu is being displayed
  2691. } //*** CResource::OnUpdateMoveResource1()
  2692. /////////////////////////////////////////////////////////////////////////////
  2693. //++
  2694. //
  2695. // CResource::OnUpdateMoveResourceRest
  2696. //
  2697. // Routine Description:
  2698. // Determines whether menu items corresponding to
  2699. // ID_FILE_MOVE_RESOURCE_2 through ID_FILE_MOVE_RESOURCE_20
  2700. // should be enabled or not.
  2701. //
  2702. // Arguments:
  2703. // pCmdUI [IN OUT] Command routing object.
  2704. //
  2705. // Return Value:
  2706. // None.
  2707. //
  2708. //--
  2709. /////////////////////////////////////////////////////////////////////////////
  2710. void CResource::OnUpdateMoveResourceRest(CCmdUI * pCmdUI)
  2711. {
  2712. CString strMenuName;
  2713. if ((pCmdUI->m_pMenu != NULL) && (pCmdUI->m_pSubMenu == NULL))
  2714. pCmdUI->m_pMenu->GetMenuString(pCmdUI->m_nID, strMenuName, MF_BYCOMMAND);
  2715. if ((strMenuName != StrGroup())
  2716. && ((Crs() == ClusterResourceOnline)
  2717. || (Crs() == ClusterResourceOffline)))
  2718. pCmdUI->Enable(TRUE);
  2719. else
  2720. pCmdUI->Enable(FALSE);
  2721. } //*** CResource::OnUpdateMoveResourceRest()
  2722. /////////////////////////////////////////////////////////////////////////////
  2723. //++
  2724. //
  2725. // CResource::OnUpdateDelete
  2726. //
  2727. // Routine Description:
  2728. // Determines whether menu items corresponding to ID_FILE_DELETE
  2729. // should be enabled or not.
  2730. //
  2731. // Arguments:
  2732. // pCmdUI [IN OUT] Command routing object.
  2733. //
  2734. // Return Value:
  2735. // None.
  2736. //
  2737. //--
  2738. /////////////////////////////////////////////////////////////////////////////
  2739. void CResource::OnUpdateDelete(CCmdUI * pCmdUI)
  2740. {
  2741. if (Crs() != ClusterResourceStateUnknown)
  2742. pCmdUI->Enable(TRUE);
  2743. else
  2744. pCmdUI->Enable(FALSE);
  2745. } //*** CResource::OnUpdateDelete()
  2746. /////////////////////////////////////////////////////////////////////////////
  2747. //++
  2748. //
  2749. // CResource::OnCmdBringOnline
  2750. //
  2751. // Routine Description:
  2752. // Processes the ID_FILE_BRING_ONLINE menu command.
  2753. //
  2754. // Arguments:
  2755. // None.
  2756. //
  2757. // Return Value:
  2758. // None.
  2759. //
  2760. //--
  2761. /////////////////////////////////////////////////////////////////////////////
  2762. void CResource::OnCmdBringOnline(void)
  2763. {
  2764. DWORD dwStatus;
  2765. CWaitCursor wc;
  2766. ASSERT(Hresource() != NULL);
  2767. // Do this in case this object is deleted while we are operating on it.
  2768. AddRef();
  2769. // If there are no possible owners for this resource, display a message.
  2770. if (LpcinodePossibleOwners().GetCount() == 0)
  2771. AfxMessageBox(IDS_NO_POSSIBLE_OWNERS, MB_OK | MB_ICONINFORMATION);
  2772. else
  2773. {
  2774. dwStatus = OnlineClusterResource(Hresource());
  2775. if ((dwStatus != ERROR_SUCCESS)
  2776. && (dwStatus != ERROR_IO_PENDING))
  2777. {
  2778. CNTException nte(dwStatus, IDS_BRING_RESOURCE_ONLINE_ERROR, StrName(), NULL, FALSE /*bAutoDelete*/);
  2779. nte.ReportError();
  2780. } // if: error bringing the resource online
  2781. UpdateState();
  2782. } // else: resource has at least one possible owner
  2783. Release();
  2784. } //*** CResource::OnCmdBringOnline()
  2785. /////////////////////////////////////////////////////////////////////////////
  2786. //++
  2787. //
  2788. // CResource::OnCmdTakeOffline
  2789. //
  2790. // Routine Description:
  2791. // Processes the ID_FILE_TAKE_OFFLINE menu command.
  2792. //
  2793. // Arguments:
  2794. // None.
  2795. //
  2796. // Return Value:
  2797. // None.
  2798. //
  2799. //--
  2800. /////////////////////////////////////////////////////////////////////////////
  2801. void CResource::OnCmdTakeOffline(void)
  2802. {
  2803. DWORD dwStatus;
  2804. CWaitCursor wc;
  2805. ASSERT(Hresource() != NULL);
  2806. // Do this in case this object is deleted while we are operating on it.
  2807. AddRef();
  2808. do // do-while to prevent goto's
  2809. {
  2810. // If this connection was made through the cluster name and this is
  2811. // either the cluster name resource or one of the resources on which
  2812. // it is dependent, warn the user.
  2813. if (!BAllowedToTakeOffline())
  2814. break;
  2815. dwStatus = OfflineClusterResource(Hresource());
  2816. if ((dwStatus != ERROR_SUCCESS)
  2817. && (dwStatus != ERROR_IO_PENDING))
  2818. {
  2819. CNTException nte(dwStatus, IDS_TAKE_RESOURCE_OFFLINE_ERROR, StrName(), NULL, FALSE /*bAutoDelete*/);
  2820. nte.ReportError();
  2821. } // if: error taking the resource offline
  2822. UpdateState();
  2823. } while (0); // do-while to prevent goto's
  2824. Release();
  2825. } //*** CResource::OnCmdTakeOffline()
  2826. /////////////////////////////////////////////////////////////////////////////
  2827. //++
  2828. //
  2829. // CResource::OnCmdInitiateFailure
  2830. //
  2831. // Routine Description:
  2832. // Processes the ID_FILE_INITIATE_FAILURE menu command.
  2833. //
  2834. // Arguments:
  2835. // None.
  2836. //
  2837. // Return Value:
  2838. // None.
  2839. //
  2840. //--
  2841. /////////////////////////////////////////////////////////////////////////////
  2842. void CResource::OnCmdInitiateFailure(void)
  2843. {
  2844. DWORD dwStatus;
  2845. CWaitCursor wc;
  2846. ASSERT(Hresource() != NULL);
  2847. dwStatus = FailClusterResource(Hresource());
  2848. if (dwStatus != ERROR_SUCCESS)
  2849. {
  2850. CNTException nte(dwStatus, IDS_INIT_RESOURCE_FAILURE_ERROR, StrName(), NULL /*bAutoDelete*/);
  2851. nte.ReportError();
  2852. } // if: error initiating failure
  2853. UpdateState();
  2854. } //*** CResource::OnCmdInitiateFailure()
  2855. /////////////////////////////////////////////////////////////////////////////
  2856. //++
  2857. //
  2858. // CResource::OnCmdMoveResource
  2859. //
  2860. // Routine Description:
  2861. // Processes the ID_FILE_MOVE_RESOURCE_# menu commands.
  2862. //
  2863. // Arguments:
  2864. // nID [IN] Command ID.
  2865. //
  2866. // Return Value:
  2867. // None.
  2868. //
  2869. //--
  2870. /////////////////////////////////////////////////////////////////////////////
  2871. void CResource::OnCmdMoveResource(IN UINT nID)
  2872. {
  2873. int ipci;
  2874. ASSERT(Hresource() != NULL);
  2875. // Do this in case this object is deleted while we are operating on it.
  2876. AddRef();
  2877. do // do-while to prevent goto's
  2878. {
  2879. ipci = (int) (nID - ID_FILE_MOVE_RESOURCE_1);
  2880. ASSERT(ipci < Pdoc()->LpciGroups().GetCount());
  2881. if (ipci < Pdoc()->LpciGroups().GetCount())
  2882. {
  2883. POSITION pos;
  2884. CResourceList lpciMove;
  2885. CString strMsg;
  2886. CGroup * pciGroup;
  2887. // Get the group.
  2888. pos = Pdoc()->LpciGroups().FindIndex(ipci);
  2889. ASSERT(pos != NULL);
  2890. pciGroup = (CGroup *) Pdoc()->LpciGroups().GetAt(pos);
  2891. ASSERT_VALID(pciGroup);
  2892. try
  2893. {
  2894. // Verify that the user really wants to move this resource.
  2895. strMsg.FormatMessage(IDS_VERIFY_MOVE_RESOURCE, StrName(), StrGroup(), pciGroup->StrName());
  2896. if (AfxMessageBox(strMsg, MB_YESNO | MB_ICONEXCLAMATION | MB_DEFBUTTON2) == IDNO)
  2897. break;
  2898. // Collect the list of resources which will be moved if confirmed.
  2899. lpciMove.AddTail(this);
  2900. CollectDependencyTree(&lpciMove);
  2901. // If this resource is dependent on or is a dependent of any other resource,
  2902. // display another warning message.
  2903. if (lpciMove.GetCount() > 0)
  2904. {
  2905. CMoveResourcesDlg dlg(this, &lpciMove, AfxGetMainWnd());
  2906. if (dlg.DoModal() != IDOK)
  2907. break;
  2908. } // if: resource is dependent of another resource
  2909. // Move the resource.
  2910. {
  2911. CWaitCursor wc;
  2912. Move(pciGroup);
  2913. } // Move the resource
  2914. } // try
  2915. catch (CException * pe)
  2916. {
  2917. pe->ReportError();
  2918. pe->Delete();
  2919. } // catch: CException
  2920. } // if: valid index
  2921. } while (0); // do-while to prevent goto's
  2922. Release();
  2923. } //*** CResource::OnCmdMoveResource()
  2924. /////////////////////////////////////////////////////////////////////////////
  2925. //++
  2926. //
  2927. // CResource::OnCmdDelete
  2928. //
  2929. // Routine Description:
  2930. // Processes the ID_FILE_DELETE menu command.
  2931. //
  2932. // Arguments:
  2933. // None.
  2934. //
  2935. // Return Value:
  2936. // None.
  2937. //
  2938. //--
  2939. /////////////////////////////////////////////////////////////////////////////
  2940. void CResource::OnCmdDelete(void)
  2941. {
  2942. CResourceList lpci;
  2943. CString strMsg;
  2944. ASSERT(Hresource() != NULL);
  2945. // Do this in case this object is deleted while we are operating on it.
  2946. AddRef();
  2947. do // do-while to prevent goto's
  2948. {
  2949. try
  2950. {
  2951. // If this is a core resource, we can't delete it.
  2952. if (BCore())
  2953. {
  2954. AfxMessageBox(IDS_CANT_DELETE_CORE_RESOURCE, MB_OK | MB_ICONSTOP);
  2955. break;
  2956. } // If this is a core resource
  2957. // Verify that the user really wants to delete this resource.
  2958. strMsg.FormatMessage(IDS_VERIFY_DELETE_RESOURCE, StrName());
  2959. if (AfxMessageBox(strMsg, MB_YESNO | MB_ICONEXCLAMATION | MB_DEFBUTTON2) == IDNO)
  2960. break;
  2961. if (Hresource() != NULL)
  2962. {
  2963. // Collect the list of resources which will be deleted if confirmed.
  2964. CollectProvidesFor(&lpci, TRUE /*bFullTree*/);
  2965. // If any of these resources are core resources, we can't
  2966. // delete any of the resources.
  2967. {
  2968. POSITION pos;
  2969. CResource * pciRes = NULL;
  2970. pos = lpci.GetHeadPosition();
  2971. while (pos != NULL)
  2972. {
  2973. pciRes = (CResource *) lpci.GetNext(pos);
  2974. ASSERT_VALID(pciRes);
  2975. if (pciRes->BCore())
  2976. {
  2977. AfxMessageBox(IDS_CANT_DELETE_CORE_RESOURCE, MB_OK | MB_ICONSTOP);
  2978. break;
  2979. } // if: found a core resource
  2980. pciRes = NULL;
  2981. } // while: more items in the list
  2982. if (pciRes != NULL)
  2983. break;
  2984. } // Check for core resources
  2985. // If this resource is a dependent of any other resource, display
  2986. // another warning message.
  2987. if (lpci.GetCount() > 0)
  2988. {
  2989. CDeleteResourcesDlg dlg(this, &lpci, AfxGetMainWnd());
  2990. if (dlg.DoModal() != IDOK)
  2991. break;
  2992. } // if: resource is dependent of another resource
  2993. // Delete the resource.
  2994. {
  2995. CWaitCursor wc;
  2996. DeleteResource(lpci);
  2997. } // Delete the resource
  2998. } // if: resource still exists
  2999. } // try
  3000. catch (CNTException * pnte)
  3001. {
  3002. if (pnte->Sc() != ERROR_RESOURCE_NOT_AVAILABLE)
  3003. pnte->ReportError();
  3004. pnte->Delete();
  3005. } // catch: CNTException
  3006. catch (CException * pe)
  3007. {
  3008. pe->ReportError();
  3009. pe->Delete();
  3010. } // catch: CException
  3011. } while (0); // do-while to prevent goto's
  3012. Release();
  3013. } //*** CResource::OnCmdDelete()
  3014. /////////////////////////////////////////////////////////////////////////////
  3015. //++
  3016. //
  3017. // CResource::OnUpdateProperties
  3018. //
  3019. // Routine Description:
  3020. // Determines whether menu items corresponding to ID_FILE_PROPERTIES
  3021. // should be enabled or not.
  3022. //
  3023. // Arguments:
  3024. // pCmdUI [IN OUT] Command routing object.
  3025. //
  3026. // Return Value:
  3027. // None.
  3028. //
  3029. //--
  3030. /////////////////////////////////////////////////////////////////////////////
  3031. void CResource::OnUpdateProperties(CCmdUI * pCmdUI)
  3032. {
  3033. pCmdUI->Enable(TRUE);
  3034. } //*** CResource::OnUpdateProperties()
  3035. /////////////////////////////////////////////////////////////////////////////
  3036. //++
  3037. //
  3038. // CResource::BDisplayProperties
  3039. //
  3040. // Routine Description:
  3041. // Display properties for the object.
  3042. //
  3043. // Arguments:
  3044. // bReadOnly [IN] Don't allow edits to the object properties.
  3045. //
  3046. // Return Value:
  3047. // TRUE OK pressed.
  3048. // FALSE OK not pressed.
  3049. //
  3050. //--
  3051. /////////////////////////////////////////////////////////////////////////////
  3052. BOOL CResource::BDisplayProperties(IN BOOL bReadOnly)
  3053. {
  3054. BOOL bChanged = FALSE;
  3055. CResourcePropSheet sht(AfxGetMainWnd());
  3056. // Do this in case this object is deleted while we are operating on it.
  3057. AddRef();
  3058. // If the object has changed, read it.
  3059. if (BChanged())
  3060. ReadItem();
  3061. // Display the property sheet.
  3062. try
  3063. {
  3064. sht.SetReadOnly(bReadOnly);
  3065. if (sht.BInit(this, IimgObjectType()))
  3066. bChanged = ((sht.DoModal() == IDOK) && !bReadOnly);
  3067. } // try
  3068. catch (CException * pe)
  3069. {
  3070. pe->Delete();
  3071. } // catch: CException
  3072. Release();
  3073. return bChanged;
  3074. } //*** CResource::BDisplayProperties()
  3075. /////////////////////////////////////////////////////////////////////////////
  3076. //++
  3077. //
  3078. // CResource::BAllowedToTakeOffline
  3079. //
  3080. // Routine Description:
  3081. // Determine if this resource is allowed to be taken offline.
  3082. //
  3083. // Arguments:
  3084. // None.
  3085. //
  3086. // Return Value:
  3087. // TRUE Resource is allowed to be taken offline.
  3088. // FALSE Resource is NOT allowed to be taken offline.
  3089. //
  3090. //--
  3091. /////////////////////////////////////////////////////////////////////////////
  3092. BOOL CResource::BAllowedToTakeOffline(void)
  3093. {
  3094. BOOL bAllowed = TRUE;
  3095. ASSERT_VALID(Pdoc());
  3096. // Do this in case this object is deleted while we are operating on it.
  3097. AddRef();
  3098. // Check to see if document is connected via the cluster name.
  3099. if (Pdoc()->StrName() == Pdoc()->StrNode())
  3100. {
  3101. // If this is the core network name resource, we need to ask
  3102. // the user first.
  3103. if ( (StrRealResourceType().CompareNoCase(CLUS_RESTYPE_NAME_NETNAME) == 0)
  3104. && BCore() )
  3105. bAllowed = FALSE;
  3106. else
  3107. {
  3108. CResourceList lpci;
  3109. CResource * pciRes;
  3110. POSITION pos;
  3111. // Collect all the resources above this resource in the
  3112. // dependency tree. If one of them is the cluster name
  3113. // resource, we need to ask the user first.
  3114. try
  3115. {
  3116. CollectProvidesFor(&lpci, TRUE /*bFullTree*/);
  3117. pos = lpci.GetHeadPosition();
  3118. while (pos != NULL)
  3119. {
  3120. pciRes = (CResource *) lpci.GetNext(pos);
  3121. ASSERT_VALID(pciRes);
  3122. if ( (pciRes->StrRealResourceType().CompareNoCase(CLUS_RESTYPE_NAME_NETNAME) == 0)
  3123. && pciRes->BCore() )
  3124. bAllowed = FALSE;
  3125. } // while: more resources in the list
  3126. } // try
  3127. catch (CException * pe)
  3128. {
  3129. pe->Delete();
  3130. } // catch: CException
  3131. } // else: not the cluster name resource
  3132. } // if: connected via the cluster name
  3133. // If not allowed to take offline, ask the user to confirm.
  3134. if (!bAllowed)
  3135. {
  3136. ID id;
  3137. CString strMsg;
  3138. strMsg.FormatMessage(IDS_TAKE_CLUSTER_NAME_OFFLINE_QUERY, StrName(), Pdoc()->StrName());
  3139. id = AfxMessageBox(strMsg, MB_OKCANCEL | MB_ICONEXCLAMATION);
  3140. bAllowed = (id == IDOK);
  3141. } // if: not allowed to atake offline
  3142. Release();
  3143. return bAllowed;
  3144. } //*** CResource::BAllowedToTakeOffline()
  3145. /////////////////////////////////////////////////////////////////////////////
  3146. //++
  3147. //
  3148. // CResource::OnClusterNotify
  3149. //
  3150. // Routine Description:
  3151. // Handler for the WM_CAM_CLUSTER_NOTIFY message.
  3152. // Processes cluster notifications for this object.
  3153. //
  3154. // Arguments:
  3155. // pnotify [IN OUT] Object describing the notification.
  3156. //
  3157. // Return Value:
  3158. // Value returned from the application method.
  3159. //
  3160. //--
  3161. /////////////////////////////////////////////////////////////////////////////
  3162. LRESULT CResource::OnClusterNotify(IN OUT CClusterNotify * pnotify)
  3163. {
  3164. ASSERT(pnotify != NULL);
  3165. ASSERT_VALID(this);
  3166. try
  3167. {
  3168. switch (pnotify->m_dwFilterType)
  3169. {
  3170. case CLUSTER_CHANGE_RESOURCE_STATE:
  3171. Trace(g_tagResNotify, _T("(%s) - Resource '%s' (%x) state changed (%s)"), Pdoc()->StrNode(), StrName(), this, pnotify->m_strName);
  3172. UpdateState();
  3173. break;
  3174. case CLUSTER_CHANGE_RESOURCE_DELETED:
  3175. Trace(g_tagResNotify, _T("(%s) - Resource '%s' (%x) deleted (%s)"), Pdoc()->StrNode(), StrName(), this, pnotify->m_strName);
  3176. if (Pdoc()->BClusterAvailable())
  3177. Delete();
  3178. break;
  3179. case CLUSTER_CHANGE_RESOURCE_PROPERTY:
  3180. Trace(g_tagResNotify, _T("(%s) - Resource '%s' (%x) properties changed (%s)"), Pdoc()->StrNode(), StrName(), this, pnotify->m_strName);
  3181. if (!BDeleting() && Pdoc()->BClusterAvailable())
  3182. ReadItem();
  3183. break;
  3184. case CLUSTER_CHANGE_REGISTRY_NAME:
  3185. Trace(g_tagResRegNotify, _T("(%s) - Registry namespace '%s' changed (%s %s (%x))"), Pdoc()->StrNode(), pnotify->m_strName, StrType(), StrName(), this);
  3186. MarkAsChanged();
  3187. break;
  3188. case CLUSTER_CHANGE_REGISTRY_ATTRIBUTES:
  3189. Trace(g_tagResRegNotify, _T("(%s) - Registry attributes for '%s' changed (%s %s (%x))"), Pdoc()->StrNode(), pnotify->m_strName, StrType(), StrName(), this);
  3190. MarkAsChanged();
  3191. break;
  3192. case CLUSTER_CHANGE_REGISTRY_VALUE:
  3193. Trace(g_tagResRegNotify, _T("(%s) - Registry value '%s' changed (%s %s (%x))"), Pdoc()->StrNode(), pnotify->m_strName, StrType(), StrName(), this);
  3194. MarkAsChanged();
  3195. break;
  3196. default:
  3197. Trace(g_tagResNotify, _T("(%s) - Unknown resource notification (%x) for '%s' (%x) (%s)"), Pdoc()->StrNode(), pnotify->m_dwFilterType, StrName(), this, pnotify->m_strName);
  3198. } // switch: dwFilterType
  3199. } // try
  3200. catch (CException * pe)
  3201. {
  3202. // Don't display anything on notification errors.
  3203. // If it's really a problem, the user will see it when
  3204. // refreshing the view.
  3205. //pe->ReportError();
  3206. pe->Delete();
  3207. } // catch: CException
  3208. delete pnotify;
  3209. return 0;
  3210. } //*** CResource::OnClusterNotify()
  3211. //*************************************************************************//
  3212. /////////////////////////////////////////////////////////////////////////////
  3213. // Global Functions
  3214. /////////////////////////////////////////////////////////////////////////////
  3215. /////////////////////////////////////////////////////////////////////////////
  3216. //++
  3217. //
  3218. // DeleteAllItemData
  3219. //
  3220. // Routine Description:
  3221. // Deletes all item data in a CList.
  3222. //
  3223. // Arguments:
  3224. // rlp [IN OUT] List whose data is to be deleted.
  3225. //
  3226. // Return Value:
  3227. // None.
  3228. //
  3229. //--
  3230. /////////////////////////////////////////////////////////////////////////////
  3231. #ifdef NEVER
  3232. void DeleteAllItemData(IN OUT CResourceList & rlp)
  3233. {
  3234. POSITION pos;
  3235. CResource * pci;
  3236. // Delete all the items in the Contained list.
  3237. pos = rlp.GetHeadPosition();
  3238. while (pos != NULL)
  3239. {
  3240. pci = rlp.GetNext(pos);
  3241. ASSERT_VALID(pci);
  3242. // Trace(g_tagClusItemDelete, _T("DeleteAllItemData(rlpcires) - Deleting resource cluster item '%s' (%x)"), pci->StrName(), pci);
  3243. pci->Delete();
  3244. } // while: more items in the list
  3245. } //*** DeleteAllItemData()
  3246. #endif