Leaked source code of windows server 2003
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.

3881 lines
118 KiB

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