Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5921 lines
179 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2000-2001 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // PostCfgManager.cpp
  7. //
  8. // Description:
  9. // CPostCfgManager implementation.
  10. //
  11. // Maintained By:
  12. // Galen Barbee (GalenB) 09-JUN-2000
  13. //
  14. //////////////////////////////////////////////////////////////////////////////
  15. #include "pch.h"
  16. #include "guids.h"
  17. #include "clusudef.h"
  18. #include "GroupHandle.h"
  19. #include "ResourceEntry.h"
  20. #include "IPostCfgManager.h"
  21. #include "IPrivatePostCfgResource.h"
  22. #include "PostCfgMgr.h"
  23. #include "CreateServices.h"
  24. #include "PostCreateServices.h"
  25. #include "PreCreateServices.h"
  26. #include "ResTypeServices.h"
  27. #include "..\Wizard\Resource.h"
  28. #include "PostCfgResources.h"
  29. #include "ClusCfgPrivate.h"
  30. #include <ResApi.h>
  31. #include <ClusterUtils.h>
  32. DEFINE_THISCLASS("CPostCfgManager")
  33. #define RESOURCE_INCREMENT 25
  34. //
  35. // Failure code.
  36. //
  37. #define SSR_LOG_ERR( _major, _minor, _hr, _msg ) \
  38. { \
  39. THR( SendStatusReport( m_bstrNodeName, _major, _minor, 0, 0, 0, _hr, _msg, NULL, NULL ) ); \
  40. }
  41. #define SSR_LOG1( _major, _minor, _hr, _fmt, _bstr, _arg1 ) \
  42. { \
  43. HRESULT hrTemp; \
  44. THR( HrFormatStringIntoBSTR( _fmt, &_bstr, _arg1 ) ); \
  45. hrTemp = THR( SendStatusReport( NULL, _major, _minor, 0, 1, 1, _hr, _bstr, NULL, NULL ) ); \
  46. if ( FAILED( hrTemp ) )\
  47. { \
  48. _hr = hrTemp; \
  49. } \
  50. }
  51. #define SSR_LOG2( _major, _minor, _hr, _fmt, _bstr, _arg1, _arg2 ) \
  52. { \
  53. HRESULT hrTemp; \
  54. THR( HrFormatStringIntoBSTR( _fmt, &_bstr, _arg1, _arg2 ) ); \
  55. hrTemp = THR( SendStatusReport( NULL, _major, _minor, 0, 1, 1, _hr, _bstr, NULL, NULL ) ); \
  56. if ( FAILED( hrTemp ) )\
  57. { \
  58. _hr = hrTemp; \
  59. } \
  60. }
  61. //
  62. // Structure that holds the mapping for well known resource types.
  63. //
  64. struct SResTypeGUIDPtrAndName
  65. {
  66. const GUID * m_pcguidTypeGUID;
  67. const WCHAR * m_pszTypeName;
  68. };
  69. // Mapping of well known resource type GUIDs to the type names.
  70. const SResTypeGUIDPtrAndName gc_rgWellKnownResTypeMap[] =
  71. {
  72. {
  73. &RESTYPE_PhysicalDisk,
  74. CLUS_RESTYPE_NAME_PHYS_DISK
  75. },
  76. {
  77. &RESTYPE_IPAddress,
  78. CLUS_RESTYPE_NAME_IPADDR
  79. },
  80. {
  81. &RESTYPE_NetworkName,
  82. CLUS_RESTYPE_NAME_NETNAME
  83. },
  84. {
  85. &RESTYPE_LocalQuorum,
  86. CLUS_RESTYPE_NAME_LKQUORUM
  87. }
  88. };
  89. // Size of the above array.
  90. const int gc_cWellKnownResTypeMapSize = sizeof( gc_rgWellKnownResTypeMap ) / sizeof( gc_rgWellKnownResTypeMap[ 0 ] );
  91. // ************************************************************************
  92. //
  93. // Constructor / Destructor
  94. //
  95. // ************************************************************************
  96. //////////////////////////////////////////////////////////////////////////////
  97. //
  98. // HRESULT
  99. // CPostCfgManager::S_HrCreateInstance(
  100. // IUnknown ** ppunkOut
  101. // )
  102. //
  103. //////////////////////////////////////////////////////////////////////////////
  104. HRESULT
  105. CPostCfgManager::S_HrCreateInstance(
  106. IUnknown ** ppunkOut
  107. )
  108. {
  109. TraceFunc( "" );
  110. HRESULT hr;
  111. Assert( ppunkOut != NULL );
  112. CPostCfgManager * pPostCfgManager = new CPostCfgManager;
  113. if ( pPostCfgManager != NULL )
  114. {
  115. hr = THR( pPostCfgManager->HrInit() );
  116. if ( SUCCEEDED( hr ) )
  117. {
  118. hr = THR( pPostCfgManager->TypeSafeQI( IUnknown, ppunkOut ) );
  119. }
  120. pPostCfgManager->Release();
  121. }
  122. else
  123. {
  124. hr = E_OUTOFMEMORY;
  125. }
  126. HRETURN( hr );
  127. } // S_HrCreateInstance()
  128. //////////////////////////////////////////////////////////////////////////////
  129. //
  130. // CPostCfgManager::CPostCfgManager( void )
  131. //
  132. //////////////////////////////////////////////////////////////////////////////
  133. CPostCfgManager::CPostCfgManager( void )
  134. {
  135. TraceFunc( "" );
  136. InterlockedIncrement( &g_cObjects );
  137. TraceFuncExit();
  138. } // CPostCfgManager()
  139. //////////////////////////////////////////////////////////////////////////////
  140. //
  141. // HRESULT
  142. // CPostCfgManager::HrInit( void )
  143. //
  144. //////////////////////////////////////////////////////////////////////////////
  145. HRESULT
  146. CPostCfgManager::HrInit( void )
  147. {
  148. TraceFunc( "" );
  149. ULONG idxMapEntry;
  150. HRESULT hr = S_OK;
  151. // IUnknown stuff
  152. Assert( m_cRef == 0 );
  153. AddRef(); // Add one count
  154. Assert( m_pcccb == NULL );
  155. Assert( m_lcid == 0 );
  156. // IPostCfgManager
  157. Assert( m_peccmr == NULL );
  158. Assert( m_pccci == NULL );
  159. Assert( m_cAllocedResources == 0 );
  160. Assert( m_cResources == 0 );
  161. Assert( m_rgpResources == NULL );
  162. Assert( m_idxIPAddress == 0 );
  163. Assert( m_idxClusterName == 0 );
  164. Assert( m_idxQuorumResource == 0 );
  165. Assert( m_idxLastStorage == 0 );
  166. Assert( m_hCluster == NULL );
  167. Assert( m_pgnResTypeGUIDNameMap == NULL );
  168. Assert( m_idxNextMapEntry == 0 );
  169. Assert( m_cMapSize == 0 );
  170. Assert( m_ecmCommitChangesMode == cmUNKNOWN );
  171. m_cNetName = 1;
  172. m_cIPAddress = 1;
  173. // Set the boolean flag, m_isQuorumChanged to false;
  174. m_isQuorumChanged = false;
  175. // Default allocation for mappings
  176. m_cMapSize = 20;
  177. m_pgnResTypeGUIDNameMap = new SResTypeGUIDAndName[ m_cMapSize ];
  178. if ( m_pgnResTypeGUIDNameMap == NULL )
  179. goto OutOfMemory;
  180. // Prefill the resource type GUID to name map with well known entries.
  181. for ( idxMapEntry = 0; idxMapEntry < gc_cWellKnownResTypeMapSize; ++idxMapEntry )
  182. {
  183. hr = THR(
  184. HrMapResTypeGUIDToName(
  185. *gc_rgWellKnownResTypeMap[ idxMapEntry ].m_pcguidTypeGUID
  186. , gc_rgWellKnownResTypeMap [ idxMapEntry ].m_pszTypeName
  187. )
  188. );
  189. if ( FAILED( hr ) )
  190. {
  191. SSR_LOG_ERR(
  192. TASKID_Major_Client_And_Server_Log
  193. , TASKID_Minor_Init_MapResTypeGuidToName
  194. , hr
  195. , L""
  196. );
  197. break;
  198. } // if: there was an error creating a mapping
  199. }
  200. hr = THR( HrGetComputerName( ComputerNameNetBIOS, &m_bstrNodeName ) );
  201. Cleanup:
  202. HRETURN( hr );
  203. OutOfMemory:
  204. hr = E_OUTOFMEMORY;
  205. SSR_LOG_ERR(
  206. TASKID_Major_Client_And_Server_Log
  207. , TASKID_Minor_Init_OutOfMemory
  208. , hr
  209. , L"Out of memory"
  210. );
  211. goto Cleanup;
  212. } // HrInit()
  213. //////////////////////////////////////////////////////////////////////////////
  214. //
  215. // CPostCfgManager::~CPostCfgManager()
  216. //
  217. //////////////////////////////////////////////////////////////////////////////
  218. CPostCfgManager::~CPostCfgManager( void )
  219. {
  220. TraceFunc( "" );
  221. ULONG idxMapEntry;
  222. if ( m_peccmr != NULL )
  223. {
  224. m_peccmr->Release();
  225. }
  226. if ( m_pcccb != NULL )
  227. {
  228. m_pcccb->Release();
  229. }
  230. if ( m_pccci != NULL )
  231. {
  232. m_pccci->Release();
  233. }
  234. if ( m_rgpResources != NULL )
  235. {
  236. while ( m_cAllocedResources != 0 )
  237. {
  238. m_cAllocedResources --;
  239. if ( m_rgpResources[ m_cAllocedResources ] != NULL )
  240. {
  241. delete m_rgpResources[ m_cAllocedResources ];
  242. }
  243. }
  244. TraceFree( m_rgpResources );
  245. }
  246. if ( m_hCluster != NULL )
  247. {
  248. CloseCluster( m_hCluster );
  249. }
  250. // Free the resource type GUID to name map entries
  251. for ( idxMapEntry = 0; idxMapEntry < m_idxNextMapEntry; ++idxMapEntry )
  252. {
  253. delete m_pgnResTypeGUIDNameMap[ idxMapEntry ].m_pszTypeName;
  254. } // for: iterate through the map, freeing each entry
  255. // Free the map itself.
  256. delete [] m_pgnResTypeGUIDNameMap;
  257. TraceSysFreeString( m_bstrNodeName );
  258. InterlockedDecrement( &g_cObjects );
  259. TraceFuncExit();
  260. } // ~CPostCfgManager()
  261. // ************************************************************************
  262. //
  263. // IUnknown
  264. //
  265. // ************************************************************************
  266. //////////////////////////////////////////////////////////////////////////////
  267. //
  268. // STDMETHODIMP
  269. // CPostCfgManager::QueryInterface(
  270. // REFIID riid,
  271. // LPVOID *ppv
  272. // )
  273. //
  274. //////////////////////////////////////////////////////////////////////////////
  275. STDMETHODIMP
  276. CPostCfgManager::QueryInterface(
  277. REFIID riid,
  278. LPVOID *ppv
  279. )
  280. {
  281. TraceQIFunc( riid, ppv );
  282. HRESULT hr = E_NOINTERFACE;
  283. if ( IsEqualIID( riid, IID_IUnknown ) )
  284. {
  285. *ppv = static_cast< IPostCfgManager * >( this );
  286. hr = S_OK;
  287. } // if: IUnknown
  288. else if ( IsEqualIID( riid, IID_IPostCfgManager ) )
  289. {
  290. *ppv = TraceInterface( __THISCLASS__, IPostCfgManager, this, 0 );
  291. hr = S_OK;
  292. } // else if: IPostCfgManager
  293. else if ( IsEqualIID( riid, IID_IClusCfgInitialize ) )
  294. {
  295. *ppv = TraceInterface( __THISCLASS__, IClusCfgInitialize, this, 0 );
  296. hr = S_OK;
  297. } // else if: IClusCfgInitialize
  298. else if ( IsEqualIID( riid, IID_IClusCfgCallback ) )
  299. {
  300. *ppv = TraceInterface( __THISCLASS__, IClusCfgCallback, this, 0 );
  301. hr = S_OK;
  302. } // else if: IClusCfgInitialize
  303. if ( SUCCEEDED( hr ) )
  304. {
  305. ((IUnknown*) *ppv)->AddRef();
  306. } // if: success
  307. QIRETURN( hr, riid );
  308. } // QueryInterface()
  309. //////////////////////////////////////////////////////////////////////////////
  310. //
  311. // STDMETHODIMP_(ULONG)
  312. // CPostCfgManager::AddRef( void )
  313. //
  314. //////////////////////////////////////////////////////////////////////////////
  315. STDMETHODIMP_(ULONG)
  316. CPostCfgManager::AddRef( void )
  317. {
  318. TraceFunc( "[IUnknown]" );
  319. m_cRef++; // apartment object
  320. RETURN( m_cRef );
  321. } // AddRef()
  322. //////////////////////////////////////////////////////////////////////////////
  323. //
  324. // STDMETHODIMP_(ULONG)
  325. // CPostCfgManager::Release( void )
  326. //
  327. //////////////////////////////////////////////////////////////////////////////
  328. STDMETHODIMP_(ULONG)
  329. CPostCfgManager::Release( void )
  330. {
  331. TraceFunc( "[IUnknown]" );
  332. m_cRef--; // apartment object
  333. if ( m_cRef )
  334. RETURN( m_cRef );
  335. TraceDo( delete this );
  336. RETURN(0);
  337. } // Release()
  338. //****************************************************************************
  339. //
  340. // IClusCfgInitialize
  341. //
  342. //****************************************************************************
  343. /////////////////////////////////////////////////////////////////////////////
  344. //++
  345. //
  346. // CPostCfgManager::Initialize()
  347. //
  348. // Description:
  349. // Initialize this component.
  350. //
  351. // Arguments:
  352. // punkCallbackIn
  353. // Pointer to the IUnknown interface of a component that implements
  354. // the IClusCfgCallback interface.
  355. //
  356. // lcidIn
  357. // Locale id for this component.
  358. //
  359. // Return Value:
  360. // S_OK
  361. // If the call succeeded
  362. //
  363. // Other HRESULTs
  364. // If the call failed.
  365. //
  366. //--
  367. //////////////////////////////////////////////////////////////////////////////
  368. STDMETHODIMP
  369. CPostCfgManager::Initialize(
  370. IUnknown * punkCallbackIn
  371. , LCID lcidIn
  372. )
  373. {
  374. TraceFunc( "[IClusCfgInitialize]" );
  375. HRESULT hr = S_OK;
  376. IClusCfgCallback * pcccb = NULL;
  377. if ( punkCallbackIn != NULL )
  378. {
  379. hr = THR( punkCallbackIn->TypeSafeQI( IClusCfgCallback, &pcccb ) );
  380. if ( FAILED( hr ) )
  381. {
  382. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log, TASKID_Minor_Initialize_QI, hr, L"" );
  383. goto Cleanup;
  384. }
  385. }
  386. m_lcid = lcidIn;
  387. // Release any previous callback.
  388. if ( m_pcccb != NULL )
  389. {
  390. m_pcccb->Release();
  391. }
  392. // Give ownership away
  393. m_pcccb = pcccb;
  394. pcccb = NULL;
  395. #if defined(DEBUG)
  396. if ( m_pcccb != NULL )
  397. {
  398. m_pcccb = TraceInterface( L"CPostCfgManager!IClusCfgCallback", IClusCfgCallback, m_pcccb, 1 );
  399. }
  400. #endif // DEBUG
  401. Cleanup:
  402. if ( pcccb != NULL )
  403. {
  404. pcccb->Release();
  405. }
  406. HRETURN( hr );
  407. } //*** CPostCfgManager::Initialize()
  408. //****************************************************************************
  409. //
  410. // IPostCfgManager
  411. //
  412. //****************************************************************************
  413. //////////////////////////////////////////////////////////////////////////////
  414. //
  415. // STDMETHODIMP
  416. // CPostCfgManager::CommitChanges(
  417. // IEnumClusCfgManagedResources * peccmrIn,
  418. // IClusCfgClusterInfo * pccciIn
  419. // )
  420. //
  421. //////////////////////////////////////////////////////////////////////////////
  422. STDMETHODIMP
  423. CPostCfgManager::CommitChanges(
  424. IEnumClusCfgManagedResources * peccmrIn,
  425. IClusCfgClusterInfo * pccciIn
  426. )
  427. {
  428. TraceFunc( "[IPostCfgManager]" );
  429. HRESULT hr;
  430. DWORD dw;
  431. IClusCfgResTypeServicesInitialize * pccrtsiResTypeServicesInit = NULL;
  432. // Validate parameters
  433. Assert( peccmrIn != NULL );
  434. Assert( pccciIn != NULL );
  435. //
  436. // Grab our interfaces.
  437. //
  438. if ( m_peccmr != NULL )
  439. {
  440. m_peccmr->Release();
  441. }
  442. hr = THR( peccmrIn->TypeSafeQI( IEnumClusCfgManagedResources, &m_peccmr ) );
  443. if ( FAILED( hr ) )
  444. {
  445. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log, TASKID_Minor_CommitChanges_QI_Resources, hr, L"" );
  446. goto Cleanup;
  447. }
  448. if ( m_pccci != NULL )
  449. {
  450. m_pccci->Release();
  451. }
  452. hr = THR( pccciIn->TypeSafeQI( IClusCfgClusterInfo, &m_pccci ) );
  453. if ( FAILED( hr ) )
  454. {
  455. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log, TASKID_Minor_CommitChanges_QI_ClusterInfo, hr, L"" );
  456. goto Cleanup;
  457. }
  458. //
  459. // Are we creating, adding nodes, or have we been evicted?
  460. //
  461. hr = STHR( pccciIn->GetCommitMode( &m_ecmCommitChangesMode ) );
  462. if ( FAILED( hr ) )
  463. {
  464. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log, TASKID_Minor_CommitChanges_GetCommitMode, hr, L"" );
  465. goto Cleanup;
  466. }
  467. //
  468. // Create an instance of the resource type services component
  469. //
  470. hr = THR(
  471. CoCreateInstance(
  472. CLSID_ClusCfgResTypeServices
  473. , NULL
  474. , CLSCTX_INPROC_SERVER
  475. , __uuidof( pccrtsiResTypeServicesInit )
  476. , reinterpret_cast< void ** >( &pccrtsiResTypeServicesInit )
  477. )
  478. );
  479. if ( FAILED( hr ) )
  480. {
  481. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log,
  482. TASKID_Minor_CommitChanges_CoCreate_ResTypeService,
  483. hr,
  484. L"[PostCfg] Error occurred trying to create the resource type services component"
  485. );
  486. goto Cleanup;
  487. } // if: we could not create the resource type services component
  488. // Initialize the resource type services component.
  489. hr = THR( pccrtsiResTypeServicesInit->SetParameters( m_pccci ) );
  490. if ( FAILED( hr ) )
  491. {
  492. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log,
  493. TASKID_Minor_CommitChanges_SetParameters,
  494. hr,
  495. L"[PostCfg] Error occurred trying to initialize the resource type services component."
  496. );
  497. goto Cleanup;
  498. } // if: we could not initialize the resource type services component
  499. if ( ( m_ecmCommitChangesMode == cmCREATE_CLUSTER ) || ( m_ecmCommitChangesMode == cmADD_NODE_TO_CLUSTER ) )
  500. {
  501. //
  502. // Make sure we have all we need to be successful!
  503. //
  504. if ( m_hCluster == NULL )
  505. {
  506. m_hCluster = OpenCluster( NULL );
  507. if ( m_hCluster == NULL )
  508. {
  509. dw = GetLastError();
  510. hr = HRESULT_FROM_WIN32( TW32( dw ) );
  511. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log,
  512. TASKID_Minor_CommitChanges_OpenCluster,
  513. hr,
  514. L"[PostCfg] Failed to get cluster handle. Aborting."
  515. );
  516. goto Cleanup;
  517. }
  518. }
  519. //
  520. // Configure resource types.
  521. //
  522. hr = THR( HrConfigureResTypes( pccrtsiResTypeServicesInit ) );
  523. if ( FAILED( hr ) )
  524. goto Cleanup;
  525. //
  526. // Create the resource instances.
  527. //
  528. hr = THR( HrPreCreateResources() );
  529. if ( FAILED( hr ) )
  530. goto Cleanup;
  531. hr = THR( HrCreateGroups() );
  532. if ( FAILED( hr ) )
  533. {
  534. //
  535. // MUSTDO: gpease 28-SEP-2000
  536. // For Beta1 will we ignore errors in group creation
  537. // and abort the process.
  538. //
  539. hr = S_OK;
  540. goto Cleanup;
  541. }
  542. hr = THR( HrCreateResources() );
  543. if ( FAILED( hr ) )
  544. goto Cleanup;
  545. hr = THR( HrPostCreateResources() );
  546. if ( FAILED( hr ) )
  547. goto Cleanup;
  548. //
  549. // Notify any components registered on this computer, of a cluster
  550. // member set change ( form, join or evict ).
  551. //
  552. hr = THR( HrNotifyMemberSetChangeListeners() );
  553. if ( FAILED( hr ) )
  554. goto Cleanup;
  555. } // if: we are forming or joining
  556. else if ( m_ecmCommitChangesMode == cmCLEANUP_NODE_AFTER_EVICT )
  557. {
  558. //
  559. // Notify any components registered on this computer, of a cluster
  560. // member set change ( form, join or evict ).
  561. //
  562. hr = THR( HrNotifyMemberSetChangeListeners() );
  563. if ( FAILED( hr ) )
  564. goto Cleanup;
  565. // ISSUE MUSTDO: Decide if we need to add evict processing for managed resources here. ( 03-AUG-2000 Vij Vasu )
  566. //
  567. // Configure resource types.
  568. //
  569. hr = THR( HrConfigureResTypes( pccrtsiResTypeServicesInit ) );
  570. if ( FAILED( hr ) )
  571. goto Cleanup;
  572. } // else if: we have just been evicted
  573. Cleanup:
  574. if ( pccrtsiResTypeServicesInit != NULL )
  575. {
  576. pccrtsiResTypeServicesInit->Release();
  577. } // if: we had created the resource type services component
  578. HRETURN( hr );
  579. } // CommitChanges()
  580. //****************************************************************************
  581. //
  582. // IClusCfgCallback
  583. //
  584. //****************************************************************************
  585. STDMETHODIMP
  586. CPostCfgManager::SendStatusReport(
  587. LPCWSTR pcszNodeNameIn
  588. , CLSID clsidTaskMajorIn
  589. , CLSID clsidTaskMinorIn
  590. , ULONG ulMinIn
  591. , ULONG ulMaxIn
  592. , ULONG ulCurrentIn
  593. , HRESULT hrStatusIn
  594. , LPCWSTR pcszDescriptionIn
  595. , FILETIME * pftTimeIn
  596. , LPCWSTR pcszReferenceIn
  597. )
  598. {
  599. TraceFunc( "[IClusCfgCallback]" );
  600. HRESULT hr = S_OK;
  601. FILETIME ft;
  602. if ( pftTimeIn == NULL )
  603. {
  604. GetSystemTimeAsFileTime( &ft );
  605. pftTimeIn = &ft;
  606. } // if:
  607. if ( m_pcccb != NULL )
  608. {
  609. hr = STHR( m_pcccb->SendStatusReport( pcszNodeNameIn != NULL ? pcszNodeNameIn : m_bstrNodeName,
  610. clsidTaskMajorIn,
  611. clsidTaskMinorIn,
  612. ulMinIn,
  613. ulMaxIn,
  614. ulCurrentIn,
  615. hrStatusIn,
  616. pcszDescriptionIn,
  617. pftTimeIn,
  618. pcszReferenceIn
  619. ) );
  620. }
  621. HRETURN( hr );
  622. } // SendStatusReport()
  623. //****************************************************************************
  624. //
  625. // Private methods
  626. //
  627. //****************************************************************************
  628. //////////////////////////////////////////////////////////////////////////////
  629. //
  630. // HRESULT
  631. // CPostCfgManager::HrPreCreateResources( void )
  632. //
  633. //////////////////////////////////////////////////////////////////////////////
  634. HRESULT
  635. CPostCfgManager::HrPreCreateResources( void )
  636. {
  637. TraceFunc( "" );
  638. CResourceEntry * presentry;
  639. HRESULT hr = E_UNEXPECTED;
  640. BSTR bstrName = NULL;
  641. BSTR bstrNotification = NULL;
  642. IClusCfgManagedResourceInfo * pccmri = NULL;
  643. IClusCfgManagedResourceCfg * pccmrc = NULL;
  644. IUnknown * punkServices = NULL;
  645. IPrivatePostCfgResource * ppcr = NULL;
  646. // Validate state
  647. Assert( m_peccmr != NULL );
  648. Assert( m_pccci != NULL );
  649. LogMsg( "PostCfg: Starting pre-create..." );
  650. hr = THR( HrPreInitializeExistingResources() );
  651. if ( FAILED( hr ) )
  652. goto Cleanup;
  653. //
  654. // Make sure the enumer is in the state we think it is.
  655. //
  656. hr = STHR( m_peccmr->Reset() );
  657. if ( FAILED( hr ) )
  658. {
  659. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log, TASKID_Minor_PreCreate_Reset, hr, L"" );
  660. goto Cleanup;
  661. }
  662. hr = THR( CPreCreateServices::S_HrCreateInstance( &punkServices ) );
  663. if ( FAILED( hr ) )
  664. {
  665. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log,
  666. TASKID_Minor_PreCreate_CPreCreateServices,
  667. hr,
  668. L"[PreCreate] Failed to create services object. Aborting."
  669. );
  670. goto Cleanup;
  671. }
  672. hr = THR( punkServices->TypeSafeQI( IPrivatePostCfgResource, &ppcr ) );
  673. if ( FAILED( hr ) )
  674. {
  675. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log,
  676. TASKID_Minor_PreCreate_CPreCreateServices_QI,
  677. hr,
  678. L"[PreCreate] Failed to create services object. Aborting."
  679. );
  680. goto Cleanup;
  681. }
  682. //
  683. // Update the UI layer.
  684. //
  685. hr = THR( HrLoadStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_QUERYING_FOR_RESOURCE_DEPENDENCIES, &bstrNotification ) );
  686. if ( FAILED( hr ) )
  687. {
  688. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log, TASKID_Minor_PreCreate_LoadString_Querying, hr, L"" );
  689. goto Cleanup;
  690. }
  691. hr = THR( SendStatusReport( NULL,
  692. TASKID_Major_Configure_Resources,
  693. TASKID_Minor_Querying_For_Resource_Dependencies,
  694. 0,
  695. 5,
  696. 0,
  697. S_OK,
  698. bstrNotification,
  699. NULL,
  700. NULL
  701. ) );
  702. if ( hr == E_ABORT )
  703. goto Cleanup;
  704. // ignore failure
  705. //
  706. // Loop thru the resources, requesting the resources to PreCreate()
  707. // themselves. This will cause the resources to callback into the
  708. // services object and store class type and resource type information
  709. // as well as any required dependencies the resource might have.
  710. //
  711. for( ;; )
  712. {
  713. //
  714. // Cleanup. We put this here because of error conditions below.
  715. //
  716. TraceSysFreeString( bstrName );
  717. bstrName = NULL;
  718. if ( pccmri != NULL )
  719. {
  720. pccmri->Release();
  721. pccmri = NULL;
  722. }
  723. if ( pccmrc != NULL )
  724. {
  725. pccmrc->Release();
  726. pccmrc = NULL;
  727. }
  728. //
  729. // Ask to get the next resource.
  730. //
  731. hr = STHR( m_peccmr->Next( 1, &pccmri, NULL ) );
  732. if ( FAILED( hr ) )
  733. {
  734. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log,
  735. TASKID_Minor_PreCreate_EnumResources_Next,
  736. hr,
  737. L"[PreCreate] Getting next managed resource failed. Aborting."
  738. );
  739. goto Cleanup;
  740. }
  741. if ( hr == S_FALSE )
  742. {
  743. break; // exit loop
  744. }
  745. //
  746. // Retrieve its name for logging, etc. We will ultimately store this in the
  747. // resource entry to be reused (ownership will be transferred).
  748. //
  749. hr = THR( pccmri->GetName( &bstrName ) );
  750. if ( FAILED( hr ) )
  751. {
  752. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log,
  753. TASKID_Minor_PreCreate_EnumResources_GetName,
  754. hr,
  755. L"[PreCreate] Failed to retrieve a resource's name. Skipping."
  756. );
  757. continue;
  758. }
  759. //
  760. // Check to see if the resource wants to be managed or not.
  761. //
  762. hr = STHR( pccmri->IsManaged() );
  763. if ( FAILED( hr ) )
  764. {
  765. SSR_LOG1( TASKID_Major_Client_And_Server_Log,
  766. TASKID_Minor_PreCreate_EnumResources_IsManaged,
  767. hr,
  768. L"[PreCreate] %1!ws!: Failed determine if it is to be managed. Skipping.",
  769. bstrNotification,
  770. bstrName
  771. );
  772. continue;
  773. }
  774. if ( hr == S_FALSE )
  775. {
  776. SSR_LOG1( TASKID_Major_Client_And_Server_Log,
  777. TASKID_Minor_PreCreate_EnumResources_IsManaged_False,
  778. hr,
  779. L"[PreCreate] %1!ws!: Resource does not want to be managed. Skipping.",
  780. bstrNotification,
  781. bstrName
  782. );
  783. continue;
  784. }
  785. /*
  786. hr = STHR( HrIsLocalQuorum( bstrName ) );
  787. if ( FAILED( hr ) )
  788. {
  789. SSR_LOG1( TASKID_Major_Client_And_Server_Log,
  790. TASKID_Minor_PreCreate_EnumResources_IsLocalQuorum,
  791. hr,
  792. L"Error occured trying to determine if the resource was the local quorum resource.",
  793. bstrNotification,
  794. bstrName
  795. );
  796. continue;
  797. } // if:
  798. //
  799. // Ignore the local quorum resource since it is special and won't need its own group.
  800. //
  801. if ( hr == S_OK )
  802. {
  803. continue;
  804. } // if:
  805. */
  806. //
  807. // Get the config interface for this resource (if any).
  808. //
  809. hr = THR( pccmri->TypeSafeQI( IClusCfgManagedResourceCfg, &pccmrc ) );
  810. if ( FAILED( hr ) )
  811. {
  812. SSR_LOG1( TASKID_Major_Client_And_Server_Log,
  813. TASKID_Minor_PreCreate_EnumResources_QI_pccmrc,
  814. hr,
  815. L"[PreCreate] %1!ws!: Failed QI for IClusCfgManagedResourceCfg. Skipping.",
  816. bstrNotification,
  817. bstrName
  818. );
  819. continue;
  820. }
  821. //
  822. // Grow the resource list if nessecary.
  823. //
  824. if ( m_cResources == m_cAllocedResources )
  825. {
  826. ULONG idxNewCount = m_cAllocedResources + RESOURCE_INCREMENT;
  827. CResourceEntry ** plistNew;
  828. plistNew = (CResourceEntry **) TraceAlloc( 0, sizeof( CResourceEntry *) * idxNewCount );
  829. if ( plistNew == NULL )
  830. goto OutOfMemory;
  831. CopyMemory( plistNew, m_rgpResources, sizeof(CResourceEntry *) * m_cAllocedResources );
  832. TraceFree( m_rgpResources );
  833. m_rgpResources = plistNew;
  834. for ( ; m_cAllocedResources < idxNewCount; m_cAllocedResources ++ )
  835. {
  836. m_rgpResources[ m_cAllocedResources ] = new CResourceEntry();
  837. if ( m_rgpResources[ m_cAllocedResources ] == NULL )
  838. goto OutOfMemory;
  839. }
  840. }
  841. //
  842. // Check to see if this resource is the quorum resource. If it is, point the services
  843. // object to the quorum resource entry (m_idxQuorumResource).
  844. //
  845. hr = STHR( pccmri->IsQuorumDevice() );
  846. if ( hr == S_OK )
  847. {
  848. presentry = m_rgpResources[ m_idxQuorumResource ];
  849. SSR_LOG1( TASKID_Major_Client_And_Server_Log,
  850. TASKID_PreCreate_EnumResources_IsQuorumDevice_S_OK,
  851. hr,
  852. L"[PreCreate] %1!ws!: Setting this resource to be the quorum device.",
  853. bstrNotification,
  854. bstrName
  855. );
  856. //
  857. // We need to release the previous quorum's resource handle.
  858. //
  859. THR( presentry->SetHResource( NULL ) );
  860. // We don't care if this fails... we'll overwrite it later.
  861. // Set the quorum changed flag here.
  862. m_isQuorumChanged = true;
  863. }
  864. else
  865. {
  866. presentry = m_rgpResources[ m_cResources ];
  867. if ( FAILED( hr ) )
  868. {
  869. SSR_LOG_ERR(
  870. TASKID_Major_Client_And_Server_Log
  871. , TASKID_PreCreate_EnumResources_IsQuorumDevice_Failed
  872. , hr
  873. , L""
  874. );
  875. }
  876. }
  877. //
  878. // Setup the new entry.
  879. //
  880. hr = THR( presentry->SetAssociatedResource( pccmrc ) );
  881. if ( FAILED( hr ) )
  882. {
  883. SSR_LOG_ERR(
  884. TASKID_Major_Client_And_Server_Log
  885. , TASKID_PreCreate_EnumResources_SetAssociatedResouce
  886. , hr
  887. , L""
  888. );
  889. continue;
  890. }
  891. hr = THR( presentry->SetName( bstrName ) );
  892. if ( FAILED( hr ) )
  893. {
  894. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log, TASKID_PreCreate_EnumResources_SetName, hr, L"" );
  895. continue;
  896. }
  897. // We gave ownership away when we called SetName() above.
  898. bstrName = NULL;
  899. //
  900. // Point the PreCreate services to the resource entry.
  901. //
  902. hr = THR( ppcr->SetEntry( presentry ) );
  903. if ( FAILED( hr ) )
  904. {
  905. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log, TASKID_PreCreate_EnumResources_SetEntry, hr, L"" );
  906. continue;
  907. }
  908. //
  909. // Ask the resource to configure itself. Every resource that wants to be
  910. // created in the default cluster must implement PreCreate(). Those that
  911. // return E_NOTIMPL will be ignored.
  912. //
  913. // Don't wrap - this can fail with E_NOTIMPL.
  914. hr = pccmrc->PreCreate( punkServices );
  915. if ( FAILED( hr ) )
  916. {
  917. if ( hr == E_NOTIMPL )
  918. {
  919. SSR_LOG1( TASKID_Major_Client_And_Server_Log,
  920. TASKID_Minor_PreCreate_PreCreate_E_NOTIMPL,
  921. hr,
  922. L"[PreCreate] %1!ws!: Failed. Resource returned E_NOTIMPL. This resource will not be created. Skipping.",
  923. bstrNotification,
  924. bstrName
  925. );
  926. }
  927. else
  928. {
  929. HRESULT hrStored = MAKE_HRESULT( 0, HRESULT_FACILITY( hr ), HRESULT_CODE( hr ) );
  930. SSR_LOG1( TASKID_Major_Client_And_Server_Log,
  931. TASKID_Minor_Resource_Failed_PreCreate,
  932. hr,
  933. L"%1!ws! failed PreCreate( ).",
  934. bstrNotification,
  935. bstrName
  936. );
  937. hr = THR( HrLoadStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_RESOURCE_FAILED_PRECREATE, &bstrNotification ) );
  938. if ( FAILED( hr ) )
  939. {
  940. SSR_LOG_ERR(
  941. TASKID_Major_Client_And_Server_Log
  942. , TASKID_Minor_PreCreate_LoadString_Resource_Failed
  943. , hr
  944. , L""
  945. );
  946. goto Cleanup;
  947. }
  948. hr = THR( SendStatusReport( NULL,
  949. TASKID_Major_Configure_Resources,
  950. TASKID_Minor_Resource_Failed_PreCreate,
  951. 0,
  952. 1,
  953. 1,
  954. hrStored,
  955. bstrNotification,
  956. NULL,
  957. NULL
  958. ) );
  959. if ( hr == E_ABORT )
  960. goto Cleanup;
  961. // ignore failure
  962. }
  963. continue;
  964. }
  965. if ( presentry != m_rgpResources[ m_idxQuorumResource ] )
  966. {
  967. m_cResources ++;
  968. }
  969. SSR_LOG1( TASKID_Major_Client_And_Server_Log,
  970. TASKID_Minor_PreCreate_Succeeded,
  971. hr,
  972. L"[PreCreate] %1!ws!: Succeeded.",
  973. bstrNotification,
  974. bstrName
  975. );
  976. } // for: ever
  977. SSR_LOG1( TASKID_Major_Client_And_Server_Log,
  978. TASKID_Minor_PreCreate_Finished,
  979. hr,
  980. L"[PreCreate] Finished.",
  981. bstrNotification,
  982. bstrName
  983. );
  984. #if defined(DEBUG)
  985. // DebugDumpDepencyTree();
  986. #endif
  987. hr = THR( SendStatusReport( NULL,
  988. TASKID_Major_Configure_Resources,
  989. TASKID_Minor_Querying_For_Resource_Dependencies,
  990. 0,
  991. 5,
  992. 5,
  993. S_OK,
  994. NULL, // don't need to update string
  995. NULL,
  996. NULL
  997. ) );
  998. if ( hr == E_ABORT )
  999. goto Cleanup;
  1000. // ignore failure
  1001. hr = S_OK;
  1002. Cleanup:
  1003. TraceSysFreeString( bstrNotification );
  1004. TraceSysFreeString( bstrName );
  1005. if ( pccmri != NULL )
  1006. {
  1007. pccmri->Release();
  1008. }
  1009. if ( pccmrc != NULL )
  1010. {
  1011. pccmrc->Release();
  1012. }
  1013. if ( punkServices != NULL )
  1014. {
  1015. punkServices->Release();
  1016. }
  1017. if ( ppcr != NULL )
  1018. {
  1019. ppcr->Release();
  1020. }
  1021. HRETURN( hr );
  1022. OutOfMemory:
  1023. LogMsg( "PostCfg: Out of memory. Aborting." );
  1024. hr = THR( E_OUTOFMEMORY );
  1025. goto Cleanup;
  1026. } // HrPreCreateResources()
  1027. //////////////////////////////////////////////////////////////////////////////
  1028. //
  1029. // HRESULT
  1030. // CPostCfgManager::HrCreateGroups( void )
  1031. //
  1032. //////////////////////////////////////////////////////////////////////////////
  1033. HRESULT
  1034. CPostCfgManager::HrCreateGroups( void )
  1035. {
  1036. TraceFunc( "" );
  1037. DWORD dwTypeDummy;
  1038. DWORD dwStatus;
  1039. WCHAR szGroupName[ 128 ];
  1040. ULONG cchGroupName;
  1041. ULONG cGroup;
  1042. HGROUP hGroup = NULL;
  1043. CGroupHandle * pgh = NULL;
  1044. ULONG idxResource;
  1045. ULONG idxMatchDepedency;
  1046. ULONG idxMatchResource;
  1047. const CLSID * pclsidType;
  1048. const CLSID * pclsidClassType;
  1049. EDependencyFlags dfFlags;
  1050. CResourceEntry * presentry;
  1051. HRESULT hr = E_UNEXPECTED;
  1052. HCLUSENUM hClusEnum = NULL;
  1053. BSTR bstrGroupName = NULL;
  1054. BSTR bstrNotification = NULL;
  1055. BSTR bstrClusterNameGroup = NULL;
  1056. DWORD sc;
  1057. HRESOURCE hClusterNameResource = NULL;
  1058. CLUSTER_RESOURCE_STATE crs;
  1059. // Validate state
  1060. Assert( m_peccmr != NULL );
  1061. Assert( m_pccci != NULL );
  1062. Assert( m_idxLastStorage == 0 );
  1063. m_idxLastStorage = m_idxQuorumResource;
  1064. //
  1065. // Phase 1: Figure out the dependency tree.
  1066. //
  1067. hr = S_OK;
  1068. SSR_LOG_ERR(
  1069. TASKID_Major_Client_And_Server_Log
  1070. , TASKID_Minor_CreateGroups_Begin
  1071. , hr
  1072. , L"[Grouping] Figuring out dependency tree to determine grouping."
  1073. );
  1074. for ( idxResource = 0; idxResource < m_cResources; idxResource ++ )
  1075. {
  1076. CResourceEntry * presentryResource = m_rgpResources[ idxResource ];
  1077. ULONG cDependencies;
  1078. hr = THR( presentryResource->GetCountOfTypeDependencies( &cDependencies ) );
  1079. if ( FAILED( hr ) )
  1080. {
  1081. SSR_LOG_ERR(
  1082. TASKID_Major_Client_And_Server_Log
  1083. , TASKID_Minor_CreateGroups_GetCountOfTypeDependencies
  1084. , hr
  1085. , L""
  1086. );
  1087. continue;
  1088. }
  1089. for ( idxMatchDepedency = 0; idxMatchDepedency < cDependencies; idxMatchDepedency ++ )
  1090. {
  1091. BOOL fFoundMatch = FALSE;
  1092. const CLSID * pclsidMatchType;
  1093. EDependencyFlags dfMatchFlags;
  1094. hr = THR( presentryResource->GetTypeDependencyPtr( idxMatchDepedency,
  1095. &pclsidMatchType,
  1096. &dfMatchFlags
  1097. ) );
  1098. if ( FAILED( hr ) )
  1099. {
  1100. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log, TASKID_Minor_CreateGroups_GetTypeDependencyPtr, hr, L"" );
  1101. continue;
  1102. }
  1103. //
  1104. // See if it is one of the "well known" types.
  1105. //
  1106. //
  1107. // We special case storage class device because we want to spread as many
  1108. // resources across as many storage devices as possible. This helps prevent
  1109. // the ganging of resources into one large group.
  1110. //
  1111. if ( *pclsidMatchType == RESCLASSTYPE_StorageDevice )
  1112. {
  1113. //
  1114. // The below THR may fire in certain configurations. Please validate
  1115. // the configuration before removing the THR.
  1116. //
  1117. // If it returns E_FAIL, we should fall thru and attempt "normal"
  1118. // resource negociations.
  1119. //
  1120. hr = THR( HrAttemptToAssignStorageToResource( idxResource, dfMatchFlags ) );
  1121. if ( SUCCEEDED( hr ) )
  1122. {
  1123. fFoundMatch = TRUE;
  1124. }
  1125. else if ( FAILED( hr ) )
  1126. {
  1127. if ( hr != E_FAIL )
  1128. {
  1129. goto Cleanup;
  1130. }
  1131. }
  1132. }
  1133. else if ( *pclsidMatchType == RESCLASSTYPE_NetworkName )
  1134. {
  1135. BSTR bstrName = NULL;
  1136. hr = THR( HrFormatStringIntoBSTR( g_hInstance, IDS_NETNAMEFORMAT, &bstrName, m_cNetName ) );
  1137. if ( FAILED( hr ) )
  1138. {
  1139. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log,
  1140. TASKID_Minor_CreateGroups_FormatString_NetName,
  1141. hr,
  1142. L"[Grouping] Failed to create name for net name resource. Aborting."
  1143. );
  1144. goto Cleanup;
  1145. }
  1146. hr = THR( HrAddSpecialResource( bstrName,
  1147. &RESTYPE_NetworkName,
  1148. &RESCLASSTYPE_NetworkName
  1149. ) );
  1150. if ( FAILED( hr ) )
  1151. continue;
  1152. presentry = m_rgpResources[ m_cResources - 1 ];
  1153. // Net name depends on an IP address.
  1154. hr = THR( presentry->AddTypeDependency( &RESCLASSTYPE_IPAddress, dfSHARED ) );
  1155. if ( FAILED( hr ) )
  1156. {
  1157. SSR_LOG_ERR(
  1158. TASKID_Major_Client_And_Server_Log
  1159. , TASKID_Minor_CreateGroups_AddTypeDependency
  1160. , hr
  1161. , L""
  1162. );
  1163. continue;
  1164. }
  1165. fFoundMatch = TRUE;
  1166. }
  1167. else if ( *pclsidMatchType == RESCLASSTYPE_IPAddress )
  1168. {
  1169. BSTR bstrName = NULL;
  1170. hr = THR( HrFormatStringIntoBSTR( g_hInstance,
  1171. IDS_IPADDRESSFORMAT,
  1172. &bstrName,
  1173. FIRST_IPADDRESS( m_cIPAddress ),
  1174. SECOND_IPADDRESS( m_cIPAddress ),
  1175. THIRD_IPADDRESS( m_cIPAddress ),
  1176. FOURTH_IPADDRESS( m_cIPAddress )
  1177. ) );
  1178. if ( FAILED( hr ) )
  1179. {
  1180. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log,
  1181. TASKID_Minor_CreateGroups_FormatString_IPAddress,
  1182. hr,
  1183. L"[Grouping] Failed to create name for IP address resource. Aborting."
  1184. );
  1185. goto Cleanup;
  1186. }
  1187. hr = THR( HrAddSpecialResource( bstrName, &RESTYPE_IPAddress, &RESCLASSTYPE_IPAddress ) );
  1188. if ( FAILED( hr ) )
  1189. continue;
  1190. m_cIPAddress ++;
  1191. fFoundMatch = TRUE;
  1192. }
  1193. else if ( *pclsidMatchType == RESTYPE_ClusterNetName )
  1194. {
  1195. presentry = m_rgpResources[ m_idxClusterName ];
  1196. hr = THR( presentry->AddDependent( idxResource, dfMatchFlags ) );
  1197. if ( FAILED( hr ) )
  1198. {
  1199. SSR_LOG_ERR(
  1200. TASKID_Major_Client_And_Server_Log
  1201. , TASKID_Minor_CreateGroups_NetName_AddDependent
  1202. , hr
  1203. , L""
  1204. );
  1205. continue;
  1206. }
  1207. fFoundMatch = TRUE;
  1208. }
  1209. else if ( *pclsidMatchType == RESTYPE_ClusterIPAddress )
  1210. {
  1211. presentry = m_rgpResources[ m_idxIPAddress ];
  1212. hr = THR( presentry->AddDependent( idxResource, dfMatchFlags ) );
  1213. if ( FAILED( hr ) )
  1214. {
  1215. SSR_LOG_ERR(
  1216. TASKID_Major_Client_And_Server_Log
  1217. , TASKID_Minor_CreateGroups_IPAddress_AddDependent
  1218. , hr
  1219. , L""
  1220. );
  1221. continue;
  1222. }
  1223. fFoundMatch = TRUE;
  1224. }
  1225. else if ( *pclsidMatchType == RESTYPE_ClusterQuorumDisk )
  1226. {
  1227. presentry = m_rgpResources[ m_idxQuorumResource ];
  1228. hr = THR( presentry->AddDependent( idxResource, dfMatchFlags ) );
  1229. if ( FAILED( hr ) )
  1230. {
  1231. SSR_LOG_ERR(
  1232. TASKID_Major_Client_And_Server_Log
  1233. , TASKID_Minor_CreateGroups_QuorumDisk_AddDependent
  1234. , hr
  1235. , L""
  1236. );
  1237. continue;
  1238. }
  1239. fFoundMatch = TRUE;
  1240. }
  1241. //
  1242. // Check out the resources to see if it matches any of them.
  1243. //
  1244. if ( !fFoundMatch )
  1245. {
  1246. //
  1247. // We can always start at the quorum resource because the resource with indexes
  1248. // below that are handled in the special case code above.
  1249. //
  1250. for ( idxMatchResource = m_idxQuorumResource; idxMatchResource < m_cResources; idxMatchResource ++ )
  1251. {
  1252. presentry = m_rgpResources[ idxMatchResource ];
  1253. hr = THR( presentry->GetTypePtr( &pclsidType ) );
  1254. if ( FAILED( hr ) )
  1255. {
  1256. SSR_LOG_ERR(
  1257. TASKID_Major_Client_And_Server_Log
  1258. , TASKID_Minor_CreateGroups_GetTypePtr
  1259. , hr
  1260. , L""
  1261. );
  1262. continue;
  1263. }
  1264. hr = THR( presentry->GetClassTypePtr( &pclsidClassType ) );
  1265. if ( FAILED( hr ) )
  1266. {
  1267. SSR_LOG_ERR(
  1268. TASKID_Major_Client_And_Server_Log
  1269. , TASKID_Minor_CreateGroups_GetClassTypePtr
  1270. , hr
  1271. , L""
  1272. );
  1273. continue;
  1274. }
  1275. hr = THR( presentry->GetFlags( &dfFlags ) );
  1276. if ( FAILED( hr ) )
  1277. {
  1278. SSR_LOG_ERR(
  1279. TASKID_Major_Client_And_Server_Log
  1280. , TASKID_Minor_CreateGroups_GetFlags
  1281. , hr
  1282. , L""
  1283. );
  1284. continue;
  1285. }
  1286. //
  1287. // Try matching it to the resource type.
  1288. //
  1289. if ( *pclsidType == *pclsidMatchType
  1290. || *pclsidClassType == *pclsidMatchType
  1291. )
  1292. {
  1293. if ( ! ( dfFlags & dfEXCLUSIVE )
  1294. || ( ( dfFlags & dfSHARED )
  1295. && ( dfMatchFlags & dfSHARED )
  1296. )
  1297. )
  1298. {
  1299. hr = THR( presentry->SetFlags( dfMatchFlags ) );
  1300. if ( FAILED( hr ) )
  1301. {
  1302. SSR_LOG_ERR(
  1303. TASKID_Major_Client_And_Server_Log
  1304. , TASKID_Minor_CreateGroups_SetFlags
  1305. , hr
  1306. , L""
  1307. );
  1308. continue;
  1309. }
  1310. hr = THR( presentry->AddDependent( idxResource, dfMatchFlags ) );
  1311. if ( FAILED( hr ) )
  1312. {
  1313. SSR_LOG_ERR(
  1314. TASKID_Major_Client_And_Server_Log
  1315. , TASKID_Minor_CreateGroups_Resource_AddDependent
  1316. , hr
  1317. , L""
  1318. );
  1319. continue;
  1320. }
  1321. fFoundMatch = TRUE;
  1322. break; // exit loop
  1323. }
  1324. }
  1325. } // for: idxMatchResource
  1326. } // if: not fFoundMatch
  1327. //
  1328. // If we didn't match the dependency, unmark the resource from being managed.
  1329. //
  1330. if ( !fFoundMatch )
  1331. {
  1332. BSTR bstrName;
  1333. IClusCfgManagedResourceInfo * pccmri;
  1334. IClusCfgManagedResourceCfg * pccmrc;
  1335. //
  1336. // KB: gpease 17-JUN-2000
  1337. // No need to free bstrName because the resource entry controls
  1338. // the lifetime - we're just borrowing it.
  1339. //
  1340. hr = THR( presentryResource->GetName( &bstrName ) );
  1341. if ( FAILED( hr ) )
  1342. {
  1343. SSR_LOG_ERR(
  1344. TASKID_Major_Client_And_Server_Log
  1345. , TASKID_Minor_CreateGroups_GetName
  1346. , hr
  1347. , L""
  1348. );
  1349. continue;
  1350. }
  1351. hr = S_FALSE;
  1352. SSR_LOG1( TASKID_Major_Client_And_Server_Log,
  1353. TASKID_Minor_CreateGroups_MissingDependent,
  1354. hr,
  1355. L"[Grouping] %1!ws!: Missing dependent resource. This resource will not be configured.",
  1356. bstrNotification,
  1357. bstrName
  1358. );
  1359. hr = THR( presentryResource->GetAssociatedResource( &pccmrc ) );
  1360. if ( FAILED( hr ) )
  1361. {
  1362. SSR_LOG_ERR(
  1363. TASKID_Major_Client_And_Server_Log
  1364. , TASKID_Minor_CreateGroups_GetAssociateResource
  1365. , hr
  1366. , L""
  1367. );
  1368. continue;
  1369. }
  1370. hr = THR( pccmrc->TypeSafeQI( IClusCfgManagedResourceInfo, &pccmri ) );
  1371. pccmrc->Release(); // release promptly.
  1372. if ( FAILED( hr ) )
  1373. {
  1374. SSR_LOG1( TASKID_Major_Client_And_Server_Log,
  1375. TASKID_Minor_CreateGroups_QI_pccmri,
  1376. hr,
  1377. L"[Grouping] %1!ws!: Resource failed to QI for IClusCfgManagedResourceInfo.",
  1378. bstrNotification,
  1379. bstrName
  1380. );
  1381. continue;
  1382. }
  1383. hr = THR( pccmri->SetManaged( FALSE ) );
  1384. pccmri->Release(); // release promptly.
  1385. if ( FAILED( hr ) )
  1386. {
  1387. SSR_LOG1( TASKID_Major_Client_And_Server_Log,
  1388. TASKID_Minor_CreateGroups_SetManaged,
  1389. hr,
  1390. L"[Grouping] %1!ws!: Resource failed SetManaged( FALSE ).",
  1391. bstrNotification,
  1392. bstrName
  1393. );
  1394. }
  1395. }
  1396. } // for: idxDepedency
  1397. } // for: idxResource
  1398. #if defined(DEBUG)
  1399. // DebugDumpDepencyTree();
  1400. #endif
  1401. hr = S_OK;
  1402. SSR_LOG_ERR(
  1403. TASKID_Major_Client_And_Server_Log
  1404. , TASKID_Minor_CreateGroups_Creating
  1405. , hr
  1406. , L"[Grouping] Creating groups."
  1407. );
  1408. sc = TW32( ResUtilGetCoreClusterResources( m_hCluster, &hClusterNameResource, NULL, NULL ) );
  1409. if ( sc != ERROR_SUCCESS )
  1410. {
  1411. SSR_LOG_ERR(
  1412. TASKID_Major_Client_And_Server_Log
  1413. , TASKID_Minor_CreateGroups_Get_ClusterNameGroup
  1414. , hr
  1415. , L"[Grouping] Failed to get cluster name group handle. Aborting."
  1416. );
  1417. goto Cleanup;
  1418. }
  1419. hr = THR( HrGetClusterResourceState( hClusterNameResource, NULL, &bstrClusterNameGroup, NULL ) );
  1420. if ( FAILED( hr ) )
  1421. {
  1422. goto Cleanup;
  1423. } // if:
  1424. hGroup = OpenClusterGroup( m_hCluster, bstrClusterNameGroup );
  1425. if ( hGroup == NULL )
  1426. {
  1427. hr = HRESULT_FROM_WIN32( TW32( GetLastError() ) );
  1428. SSR_LOG1( TASKID_Major_Client_And_Server_Log,
  1429. TASKID_Minor_CreateGroups_OpenClusterGroup,
  1430. hr,
  1431. L"[Grouping] Failed OpenClusterGroup('%1!ws!'). Aborting.",
  1432. bstrNotification,
  1433. bstrClusterNameGroup
  1434. );
  1435. SSR_LOG_ERR(
  1436. TASKID_Major_Client_And_Server_Log
  1437. , TASKID_Minor_CreateGroups_Open_ClusterGroup
  1438. , hr
  1439. , L"[Grouping] Failed to open cluster name group. Aborting."
  1440. );
  1441. goto Cleanup;
  1442. }
  1443. //
  1444. // Wrap it up and give ownership away.
  1445. //
  1446. hr = THR( CGroupHandle::S_HrCreateInstance( &pgh, hGroup ) );
  1447. if ( FAILED( hr ) )
  1448. {
  1449. SSR_LOG_ERR(
  1450. TASKID_Major_Client_And_Server_Log
  1451. , TASKID_Minor_CreateGroups_Create_CGroupHandle
  1452. , hr
  1453. , L""
  1454. );
  1455. goto Cleanup;
  1456. }
  1457. hGroup = NULL;
  1458. //
  1459. // Set all the entries in the 'Cluster Name Group' to the group.
  1460. //
  1461. for ( idxResource = 0; idxResource <= m_idxQuorumResource; idxResource ++ )
  1462. {
  1463. hr = THR( HrSetGroupOnResourceAndItsDependents( idxResource, pgh ) );
  1464. if ( FAILED( hr ) )
  1465. continue;
  1466. } // for: idxResource
  1467. //
  1468. // Loop thru the resources looking for groups.
  1469. //
  1470. cGroup = 0;
  1471. for ( idxResource = m_idxQuorumResource + 1; idxResource < m_cResources; idxResource ++ )
  1472. {
  1473. CResourceEntry * presentryResource = m_rgpResources[ idxResource ];
  1474. ULONG cDependencies;
  1475. if ( pgh != NULL )
  1476. {
  1477. pgh->Release();
  1478. pgh = NULL;
  1479. }
  1480. hr = THR( presentryResource->GetCountOfTypeDependencies( &cDependencies ) );
  1481. if ( FAILED( hr ) )
  1482. {
  1483. SSR_LOG_ERR(
  1484. TASKID_Major_Client_And_Server_Log
  1485. , TASKID_Minor_CreateGroups_GetCountOfTypeDependencies2
  1486. , hr
  1487. , L""
  1488. );
  1489. continue;
  1490. }
  1491. //
  1492. // Don't consider resources that have indicated that the depend on
  1493. // somebody else.
  1494. //
  1495. if ( cDependencies != 0 )
  1496. continue;
  1497. //
  1498. // See if any of the dependent resource has already has a group assigned
  1499. // to it. This allows for multiple roots to be combined into a single
  1500. // group due to lower dependencies.
  1501. //
  1502. // Don't create a group for the local quoum resource!
  1503. hr = STHR( HrFindGroupFromResourceOrItsDependents( idxResource, &pgh ) );
  1504. if ( FAILED( hr ) )
  1505. continue;
  1506. if ( hr == S_FALSE )
  1507. {
  1508. //
  1509. // We need to create a new group.
  1510. //
  1511. //
  1512. // Create a name for our group.
  1513. //
  1514. for( ;; )
  1515. {
  1516. hr = THR( HrFormatStringIntoBSTR( g_hInstance, IDS_GROUP_X, &bstrGroupName, cGroup ) );
  1517. if ( FAILED( hr ) )
  1518. {
  1519. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log,
  1520. TASKID_Minor_CreateGroups_FormatString_Group,
  1521. hr,
  1522. L"[Grouping] Failed to create group name. Aborting."
  1523. );
  1524. goto Cleanup;
  1525. }
  1526. //
  1527. // Create the group in the cluster.
  1528. //
  1529. hGroup = CreateClusterGroup( m_hCluster, bstrGroupName );
  1530. if ( hGroup == NULL )
  1531. {
  1532. dwStatus = GetLastError();
  1533. switch ( dwStatus )
  1534. {
  1535. case ERROR_OBJECT_ALREADY_EXISTS:
  1536. cGroup ++;
  1537. break; // keep looping
  1538. default:
  1539. hr = HRESULT_FROM_WIN32( TW32( dwStatus ) );
  1540. SSR_LOG1( TASKID_Major_Client_And_Server_Log,
  1541. TASKID_Minor_CreateGroups_CreateClusterGroup,
  1542. hr,
  1543. L"[Grouping] %1!ws!: Failed to create group. Aborting.",
  1544. bstrNotification,
  1545. bstrGroupName
  1546. );
  1547. goto Cleanup;
  1548. }
  1549. }
  1550. else
  1551. {
  1552. break;
  1553. }
  1554. }
  1555. //
  1556. // Bring the group online to set its persistent state to Online.
  1557. //
  1558. dwStatus = TW32( OnlineClusterGroup( hGroup, NULL ) );
  1559. if ( dwStatus != ERROR_SUCCESS )
  1560. {
  1561. hr = HRESULT_FROM_WIN32( dwStatus );
  1562. SSR_LOG1( TASKID_Major_Client_And_Server_Log,
  1563. TASKID_Minor_CreateGroups_OnlineClusterGroup,
  1564. hr,
  1565. L"[Grouping] %1!ws!: Failed to bring group online. Aborting.",
  1566. bstrNotification,
  1567. bstrGroupName
  1568. );
  1569. goto Cleanup;
  1570. }
  1571. //
  1572. // Wrap the handle for ref counting.
  1573. //
  1574. hr = THR( CGroupHandle::S_HrCreateInstance( &pgh, hGroup ) );
  1575. if ( FAILED( hr ) )
  1576. {
  1577. SSR_LOG_ERR(
  1578. TASKID_Major_Client_And_Server_Log
  1579. , TASKID_Minor_CreateGroups_Create_CGroupHandle2
  1580. , hr
  1581. , L""
  1582. );
  1583. goto Cleanup;
  1584. }
  1585. hGroup = NULL;
  1586. SSR_LOG1( TASKID_Major_Client_And_Server_Log,
  1587. TASKID_Minor_CreateGroups_Created,
  1588. hr,
  1589. L"[Grouping] %1!ws!: Group created.",
  1590. bstrNotification,
  1591. bstrGroupName
  1592. );
  1593. cGroup ++;
  1594. }
  1595. hr = THR( HrSetGroupOnResourceAndItsDependents( idxResource, pgh ) );
  1596. if ( FAILED( hr ) )
  1597. continue;
  1598. } // for: idxResource
  1599. hr = S_OK;
  1600. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log,
  1601. TASKID_Minor_CreateGroups_Finished,
  1602. hr,
  1603. L"[Grouping] Finished."
  1604. );
  1605. #if defined(DEBUG)
  1606. // DebugDumpDepencyTree();
  1607. #endif
  1608. Cleanup:
  1609. if ( hClusterNameResource != NULL )
  1610. {
  1611. CloseClusterResource( hClusterNameResource );
  1612. } // if:
  1613. TraceSysFreeString( bstrNotification );
  1614. TraceSysFreeString( bstrGroupName );
  1615. TraceSysFreeString( bstrClusterNameGroup );
  1616. if ( hClusEnum != NULL )
  1617. {
  1618. TW32( ClusterCloseEnum( hClusEnum ) );
  1619. }
  1620. if ( hGroup != NULL )
  1621. {
  1622. BOOL fRet = CloseClusterGroup( hGroup );
  1623. Assert( fRet );
  1624. }
  1625. if ( pgh != NULL )
  1626. {
  1627. pgh->Release();
  1628. }
  1629. HRETURN( hr );
  1630. } // HrCreateGroups()
  1631. //////////////////////////////////////////////////////////////////////////////
  1632. //
  1633. // HRESULT
  1634. // CPostCfgManager::HrCreateResources( void )
  1635. //
  1636. //////////////////////////////////////////////////////////////////////////////
  1637. HRESULT
  1638. CPostCfgManager::HrCreateResources( void )
  1639. {
  1640. TraceFunc( "" );
  1641. BSTR bstrName; // don't free!
  1642. ULONG idxResource;
  1643. HRESULT hr;
  1644. BSTR bstrNotification = NULL;
  1645. // Validate state
  1646. Assert( m_peccmr != NULL );
  1647. Assert( m_pccci != NULL );
  1648. //
  1649. // Make a message using the name.
  1650. //
  1651. hr = THR( HrLoadStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_CREATING_RESOURCE, &bstrNotification ) );
  1652. if ( FAILED( hr ) )
  1653. {
  1654. SSR_LOG_ERR(
  1655. TASKID_Major_Client_And_Server_Log
  1656. , TASKID_Minor_CreateResources_LoadString_Creating
  1657. , hr
  1658. , L""
  1659. );
  1660. goto Cleanup;
  1661. }
  1662. //
  1663. // Tell the UI what we are doing.
  1664. //
  1665. hr = THR( SendStatusReport( NULL,
  1666. TASKID_Major_Configure_Resources,
  1667. TASKID_Minor_Creating_Resource,
  1668. 0,
  1669. m_cResources, // KB: this was multiplied by 4; should it be?
  1670. 0,
  1671. S_OK,
  1672. bstrNotification,
  1673. NULL,
  1674. NULL
  1675. ) );
  1676. if ( hr == E_ABORT )
  1677. goto Cleanup;
  1678. // ignore failure
  1679. //
  1680. // TODO: gpease 24-AUG-2000
  1681. // What to do if we have a failure?? For now I think we should keep going!
  1682. //
  1683. hr = S_OK;
  1684. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log,
  1685. TASKID_Minor_CreateResources_Starting,
  1686. hr,
  1687. L"[Create] Starting..."
  1688. );
  1689. for ( idxResource = m_idxQuorumResource; idxResource < m_cResources; idxResource ++ )
  1690. {
  1691. hr = THR( HrCreateResourceAndDependents( idxResource ) );
  1692. if ( FAILED( hr ) )
  1693. continue;
  1694. } // for: idxResource
  1695. hr = S_OK;
  1696. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log,
  1697. TASKID_Minor_CreateResources_Finished,
  1698. hr,
  1699. L"[Create] Finished."
  1700. );
  1701. //
  1702. // Tell the UI what we are doing.
  1703. //
  1704. hr = THR( SendStatusReport( NULL,
  1705. TASKID_Major_Configure_Resources,
  1706. TASKID_Minor_Creating_Resource,
  1707. 0,
  1708. m_cResources, // KB: once these were multiplied by 4. Should they be?
  1709. m_cResources,
  1710. S_OK,
  1711. NULL,
  1712. NULL,
  1713. NULL
  1714. ) );
  1715. //
  1716. // TODO: gpease 24-AUG-2000
  1717. // What to do if we have a failure?? For now I think we should keep going!
  1718. //
  1719. Cleanup:
  1720. TraceSysFreeString( bstrNotification );
  1721. HRETURN( hr );
  1722. } // HrCreateResources()
  1723. //////////////////////////////////////////////////////////////////////////////
  1724. //
  1725. // HRESULT
  1726. // CPostCfgManager::HrPostCreateResources( void )
  1727. //
  1728. //////////////////////////////////////////////////////////////////////////////
  1729. HRESULT
  1730. CPostCfgManager::HrPostCreateResources( void )
  1731. {
  1732. TraceFunc( "" );
  1733. HRESULT hr;
  1734. ULONG idxResource;
  1735. BSTR bstrNotification = NULL;
  1736. // Validate state
  1737. Assert( m_peccmr != NULL );
  1738. Assert( m_pccci != NULL );
  1739. //
  1740. // Tell the UI what's going on.
  1741. //
  1742. hr = THR( HrLoadStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_STARTING_RESOURCES, &bstrNotification ) );
  1743. if ( FAILED( hr ) )
  1744. {
  1745. SSR_LOG_ERR(
  1746. TASKID_Major_Client_And_Server_Log
  1747. , TASKID_Minor_PostCreateResources_LoadString_Starting
  1748. , hr
  1749. , L""
  1750. );
  1751. goto Cleanup;
  1752. }
  1753. hr = THR( SendStatusReport( NULL,
  1754. TASKID_Major_Configure_Resources,
  1755. TASKID_Minor_Starting_Resources,
  1756. 0,
  1757. m_cResources,
  1758. 0,
  1759. S_OK,
  1760. bstrNotification,
  1761. NULL,
  1762. NULL
  1763. ) );
  1764. if ( hr == E_ABORT )
  1765. goto Cleanup;
  1766. // ignore failure
  1767. //
  1768. // TODO: gpease 24-AUG-2000
  1769. // What to do if we have a failure?? For now I think we should keep going!
  1770. //
  1771. hr = S_OK;
  1772. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log,
  1773. TASKID_Minor_PostCreateResources_Starting,
  1774. hr,
  1775. L"[PostCreate] Starting..."
  1776. );
  1777. //
  1778. // Reset the configure flag on every resource.
  1779. //
  1780. for( idxResource = 0; idxResource < m_cResources ; idxResource ++ )
  1781. {
  1782. hr = THR( m_rgpResources[ idxResource ]->SetConfigured( FALSE ) );
  1783. if ( FAILED( hr ) )
  1784. continue;
  1785. } // for: idxResource
  1786. //
  1787. // Loop thru the resource calling PostCreate().
  1788. //
  1789. for( idxResource = 0; idxResource < m_cResources ; idxResource ++ )
  1790. {
  1791. hr = THR( HrPostCreateResourceAndDependents( idxResource ) );
  1792. if ( FAILED( hr ) )
  1793. continue;
  1794. } // for: ever
  1795. hr = S_OK;
  1796. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log,
  1797. TASKID_Minor_PostCreateResources_Finished,
  1798. hr,
  1799. L"[PostCreate] Finished."
  1800. );
  1801. hr = THR( SendStatusReport( NULL,
  1802. TASKID_Major_Configure_Resources,
  1803. TASKID_Minor_Starting_Resources,
  1804. 0,
  1805. m_cResources, // KB: once these were multiplied by 4; should they be?
  1806. m_cResources,
  1807. S_OK,
  1808. NULL, // don't need to change text
  1809. NULL,
  1810. NULL
  1811. ) );
  1812. if ( hr == E_ABORT )
  1813. goto Cleanup;
  1814. // ignore failure
  1815. Cleanup:
  1816. TraceSysFreeString( bstrNotification );
  1817. HRETURN( hr );
  1818. } // HrPostCreateResources()
  1819. //////////////////////////////////////////////////////////////////////////////
  1820. //
  1821. // HRESULT
  1822. // CPostCfgManager::HrFindNextSharedStorage(
  1823. // ULONG idxSeedIn,
  1824. // ULONG * pidxOut
  1825. // )
  1826. //
  1827. //////////////////////////////////////////////////////////////////////////////
  1828. HRESULT
  1829. CPostCfgManager::HrFindNextSharedStorage(
  1830. ULONG * pidxInout
  1831. )
  1832. {
  1833. TraceFunc( "" );
  1834. HRESULT hr;
  1835. ULONG idxNextDiskResource;
  1836. const CLSID * pclsidClassType;
  1837. CResourceEntry * presentry;
  1838. EDependencyFlags dfFlags;
  1839. BOOL fFirstPass = TRUE;
  1840. Assert( pidxInout != NULL );
  1841. for( idxNextDiskResource = *pidxInout + 1
  1842. ; fFirstPass && idxNextDiskResource != *pidxInout
  1843. ; idxNextDiskResource ++
  1844. )
  1845. {
  1846. if ( idxNextDiskResource >= m_cResources )
  1847. {
  1848. fFirstPass = FALSE;
  1849. idxNextDiskResource = m_idxQuorumResource;
  1850. }
  1851. presentry = m_rgpResources[ idxNextDiskResource ];
  1852. hr = THR( presentry->GetClassTypePtr( &pclsidClassType ) );
  1853. if ( FAILED( hr ) )
  1854. {
  1855. SSR_LOG_ERR(
  1856. TASKID_Major_Client_And_Server_Log
  1857. , TASKID_Minor_FindNextSharedStorage_GetClassTypePtr
  1858. , hr
  1859. , L""
  1860. );
  1861. continue;
  1862. }
  1863. // Skip non-storage class devices
  1864. if ( *pclsidClassType != RESCLASSTYPE_StorageDevice )
  1865. continue;
  1866. hr = THR( presentry->GetFlags( &dfFlags ) );
  1867. if ( FAILED( hr ) )
  1868. {
  1869. SSR_LOG_ERR(
  1870. TASKID_Major_Client_And_Server_Log
  1871. , TASKID_Minor_FindNextSharedStorage_GetFlags
  1872. , hr
  1873. , L""
  1874. );
  1875. continue;
  1876. }
  1877. if ( ! ( dfFlags & dfEXCLUSIVE ) )
  1878. {
  1879. *pidxInout = idxNextDiskResource;
  1880. hr = S_OK;
  1881. goto Cleanup;
  1882. }
  1883. } // for: fFirstPass && idxNextDiskResource
  1884. hr = THR( E_FAIL );
  1885. Cleanup:
  1886. HRETURN( hr );
  1887. } // HrFindNextSharedStorage()
  1888. //////////////////////////////////////////////////////////////////////////////
  1889. //
  1890. // HRESULT
  1891. // CPostCfgManager::HrAttemptToAssignStorageToResource(
  1892. // ULONG idxResource
  1893. // )
  1894. //
  1895. //////////////////////////////////////////////////////////////////////////////
  1896. HRESULT
  1897. CPostCfgManager::HrAttemptToAssignStorageToResource(
  1898. ULONG idxResourceIn,
  1899. EDependencyFlags dfResourceFlagsIn
  1900. )
  1901. {
  1902. TraceFunc1( "idxResource = %u", idxResourceIn );
  1903. HRESULT hr;
  1904. ULONG idxStorage;
  1905. CResourceEntry * presentry;
  1906. //
  1907. // Find the next available shared storage resource.
  1908. //
  1909. idxStorage = m_idxLastStorage;
  1910. hr = THR( HrFindNextSharedStorage( &idxStorage ) );
  1911. if ( FAILED( hr ) )
  1912. goto Cleanup;
  1913. //
  1914. // If the resource wants exclusive rights the the disk, then the quorum
  1915. // resource can not be used. The quorum device must always have SHARED
  1916. // access to it.
  1917. //
  1918. if ( ( dfResourceFlagsIn & dfEXCLUSIVE )
  1919. && ( idxStorage == m_idxQuorumResource )
  1920. )
  1921. {
  1922. hr = THR( HrFindNextSharedStorage( &idxStorage ) );
  1923. if ( idxStorage == m_idxQuorumResource )
  1924. {
  1925. //
  1926. // There must not be anymore storage devices available for exclusive
  1927. // access. Return failure.
  1928. //
  1929. hr = THR( E_FAIL );
  1930. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log,
  1931. TASKID_Minor_HrAttemptToAssignStorageToResource_NoMoreStorage,
  1932. hr,
  1933. L"There must not be anymore storage devices available for exclusive access."
  1934. );
  1935. goto Cleanup;
  1936. }
  1937. }
  1938. presentry = m_rgpResources[ idxStorage ];
  1939. //
  1940. // Set the dependency flags.
  1941. //
  1942. hr = THR( presentry->SetFlags( dfResourceFlagsIn ) );
  1943. if ( FAILED( hr ) )
  1944. {
  1945. SSR_LOG_ERR(
  1946. TASKID_Major_Client_And_Server_Log
  1947. , TASKID_Minor_HrAttemptToAssignStorageToResource_SetFlags
  1948. , hr
  1949. , L""
  1950. );
  1951. goto Cleanup;
  1952. }
  1953. //
  1954. // If the resource wants exclusive access to the storage resource, move
  1955. // any existing SHARED dependents to another resource. There will always
  1956. // be at least one SHARED resource because the quorum disk can't not be
  1957. // assigned to EXCLUSIVE access.
  1958. //
  1959. if ( dfResourceFlagsIn & dfEXCLUSIVE )
  1960. {
  1961. ULONG idxNewStorage = idxStorage;
  1962. hr = THR( HrFindNextSharedStorage( &idxNewStorage ) );
  1963. if ( FAILED( hr ) )
  1964. goto Cleanup;
  1965. hr = THR( HrMovedDependentsToAnotherResource( idxStorage, idxNewStorage ) );
  1966. if ( FAILED( hr ) )
  1967. goto Cleanup;
  1968. }
  1969. //
  1970. // Add the resource as a dependent of this storage resource.
  1971. //
  1972. hr = THR( presentry->AddDependent( idxResourceIn, dfResourceFlagsIn ) );
  1973. if ( FAILED( hr ) )
  1974. {
  1975. SSR_LOG_ERR(
  1976. TASKID_Major_Client_And_Server_Log
  1977. , TASKID_Minor_HrAttemptToAssignStorageToResource_AddDependent
  1978. , hr
  1979. , L""
  1980. );
  1981. goto Cleanup;
  1982. }
  1983. m_idxLastStorage = idxStorage;
  1984. hr = S_OK;
  1985. Cleanup:
  1986. HRETURN( hr );
  1987. } // HrAttemptToAssignStorageToResource()
  1988. //////////////////////////////////////////////////////////////////////////////
  1989. //
  1990. // HRESULT
  1991. // CPostCfgManager::HrMovedDependentsToAnotherResource(
  1992. // ULONG idxSourceIn,
  1993. // ULONG idxDestIn
  1994. // )
  1995. //
  1996. //////////////////////////////////////////////////////////////////////////////
  1997. HRESULT
  1998. CPostCfgManager::HrMovedDependentsToAnotherResource(
  1999. ULONG idxSourceIn,
  2000. ULONG idxDestIn
  2001. )
  2002. {
  2003. TraceFunc( "" );
  2004. HRESULT hr;
  2005. ULONG cDependents;
  2006. ULONG idxDependent;
  2007. EDependencyFlags dfFlags;
  2008. CResourceEntry * presentrySrc;
  2009. CResourceEntry * presentryDst;
  2010. //
  2011. // Move the shared resources to another shared disk.
  2012. //
  2013. presentrySrc = m_rgpResources[ idxSourceIn ];
  2014. presentryDst = m_rgpResources[ idxDestIn ];
  2015. hr = THR( presentrySrc->GetCountOfDependents( &cDependents ) );
  2016. if ( FAILED( hr ) )
  2017. {
  2018. SSR_LOG_ERR(
  2019. TASKID_Major_Client_And_Server_Log
  2020. , TASKID_Minor_HrMovedDependentsToAnotherResource_GetCountOfDependents
  2021. , hr
  2022. , L""
  2023. );
  2024. goto Cleanup;
  2025. }
  2026. for ( ; cDependents != 0 ; )
  2027. {
  2028. cDependents --;
  2029. hr = THR( presentrySrc->GetDependent( cDependents, &idxDependent, &dfFlags ) );
  2030. if ( FAILED( hr ) )
  2031. {
  2032. SSR_LOG_ERR(
  2033. TASKID_Major_Client_And_Server_Log
  2034. , TASKID_Minor_HrMovedDependentsToAnotherResource_GetDependent
  2035. , hr
  2036. , L""
  2037. );
  2038. goto Cleanup;
  2039. }
  2040. hr = THR( presentryDst->AddDependent( idxDependent, dfFlags ) );
  2041. if ( FAILED( hr ) )
  2042. {
  2043. SSR_LOG_ERR(
  2044. TASKID_Major_Client_And_Server_Log
  2045. , TASKID_Minor_HrMovedDependentsToAnotherResource_AddDependent
  2046. , hr
  2047. , L""
  2048. );
  2049. goto Cleanup;
  2050. }
  2051. } // for: cDependents
  2052. hr = THR( presentrySrc->ClearDependents() );
  2053. if ( FAILED( hr ) )
  2054. {
  2055. SSR_LOG_ERR(
  2056. TASKID_Major_Client_And_Server_Log
  2057. , TASKID_Minor_HrMovedDependentsToAnotherResource_ClearDependents
  2058. , hr
  2059. , L""
  2060. );
  2061. goto Cleanup;
  2062. }
  2063. Cleanup:
  2064. HRETURN( hr );
  2065. } // HrMovedDependentsToAnotherResource()
  2066. //////////////////////////////////////////////////////////////////////////////
  2067. //
  2068. // HRESULT
  2069. // CPostCfgManager::HrSetGroupOnResourceAndItsDependents(
  2070. // ULONG idxResourceIn,
  2071. // CGroupHandle * pghIn
  2072. // )
  2073. //
  2074. //////////////////////////////////////////////////////////////////////////////
  2075. HRESULT
  2076. CPostCfgManager::HrSetGroupOnResourceAndItsDependents(
  2077. ULONG idxResourceIn,
  2078. CGroupHandle * pghIn
  2079. )
  2080. {
  2081. TraceFunc1( "idxResourceIn = %u", idxResourceIn );
  2082. HRESULT hr;
  2083. ULONG cDependents;
  2084. ULONG idxDependent;
  2085. EDependencyFlags dfDependent;
  2086. CResourceEntry * presentry;
  2087. presentry = m_rgpResources[ idxResourceIn ];
  2088. hr = THR( presentry->SetGroupHandle( pghIn ) );
  2089. if ( FAILED( hr ) )
  2090. {
  2091. SSR_LOG_ERR(
  2092. TASKID_Major_Client_And_Server_Log
  2093. , TASKID_Minor_HrSetGroupOnResourceAndItsDependents_SetGroupHandle
  2094. , hr
  2095. , L""
  2096. );
  2097. goto Cleanup;
  2098. }
  2099. //
  2100. // Follow the depents list.
  2101. //
  2102. hr = THR( presentry->GetCountOfDependents( &cDependents ) );
  2103. if ( FAILED( hr ) )
  2104. {
  2105. SSR_LOG_ERR(
  2106. TASKID_Major_Client_And_Server_Log
  2107. , TASKID_Minor_HrSetGroupOnResourceAndItsDependents_GetCountOfDependents
  2108. , hr
  2109. , L""
  2110. );
  2111. goto Cleanup;
  2112. }
  2113. for ( ; cDependents != 0 ; )
  2114. {
  2115. cDependents --;
  2116. hr = THR( presentry->GetDependent( cDependents, &idxDependent, &dfDependent ) );
  2117. if ( FAILED( hr ) )
  2118. {
  2119. SSR_LOG_ERR(
  2120. TASKID_Major_Client_And_Server_Log
  2121. , TASKID_Minor_HrSetGroupOnResourceAndItsDependents_GetDependent
  2122. , hr
  2123. , L""
  2124. );
  2125. continue;
  2126. }
  2127. hr = THR( HrSetGroupOnResourceAndItsDependents( idxDependent, pghIn ) );
  2128. if ( FAILED( hr ) )
  2129. continue;
  2130. } // for: cDependents
  2131. hr = S_OK;
  2132. Cleanup:
  2133. HRETURN( hr );
  2134. } // HrSetGroupOnResourceAndItsDependents()
  2135. //////////////////////////////////////////////////////////////////////////////
  2136. //
  2137. // HRESULT
  2138. // CPostCfgManager::HrFindGroupFromResourceOrItsDependents(
  2139. // ULONG idxResourceIn,
  2140. // CGroupHandle ** ppghOut
  2141. // )
  2142. //
  2143. //////////////////////////////////////////////////////////////////////////////
  2144. HRESULT
  2145. CPostCfgManager::HrFindGroupFromResourceOrItsDependents(
  2146. ULONG idxResourceIn,
  2147. CGroupHandle ** ppghOut
  2148. )
  2149. {
  2150. TraceFunc1( "idxResourceIn = %u", idxResourceIn );
  2151. HRESULT hr;
  2152. ULONG cDependents;
  2153. ULONG idxDependent;
  2154. BSTR bstrName; // don't free
  2155. BSTR bstrGroup = NULL;
  2156. HRESOURCE hResource;
  2157. HRESOURCE hResourceToClose = NULL;
  2158. HGROUP hGroup = NULL;
  2159. EDependencyFlags dfDependent;
  2160. CResourceEntry * presentry;
  2161. BSTR bstrNotification = NULL;
  2162. Assert( ppghOut != NULL );
  2163. presentry = m_rgpResources[ idxResourceIn ];
  2164. //
  2165. // See if we already have a cached version of the group handle.
  2166. //
  2167. hr = THR( presentry->GetGroupHandle( ppghOut) );
  2168. if ( FAILED( hr ) )
  2169. {
  2170. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log,
  2171. TASKID_Minor_HrFindGroupFromResourceOrItsDependents_GetGroupHandle,
  2172. hr,
  2173. L"GetGroupHandle failed."
  2174. );
  2175. goto Cleanup;
  2176. }
  2177. if ( hr == S_OK && *ppghOut != NULL )
  2178. goto Cleanup;
  2179. //
  2180. // Else, see if we can located an existing resource and group.
  2181. //
  2182. // don't wrap - this can fail with H_R_W32( ERROR_INVALID_DATA )
  2183. hr = presentry->GetHResource( &hResource );
  2184. if ( FAILED( hr ) )
  2185. {
  2186. Assert( hr == HRESULT_FROM_WIN32( ERROR_INVALID_DATA ) );
  2187. Assert( hResource == NULL );
  2188. // Just borrowing it's name.... don't free
  2189. hr = THR( presentry->GetName( &bstrName ) );
  2190. if ( hr == S_OK )
  2191. {
  2192. hResourceToClose = OpenClusterResource( m_hCluster, bstrName );
  2193. hResource = hResourceToClose;
  2194. }
  2195. }
  2196. if ( hResource != NULL )
  2197. {
  2198. CLUSTER_RESOURCE_STATE crs;
  2199. DWORD cbGroup = 200;
  2200. ReAllocGroupName:
  2201. bstrGroup = TraceSysAllocStringLen( NULL, cbGroup );
  2202. if ( bstrGroup == NULL )
  2203. goto OutOfMemory;
  2204. crs = GetClusterResourceState( hResource, NULL, NULL, bstrGroup, &cbGroup );
  2205. if ( crs != ClusterResourceStateUnknown )
  2206. {
  2207. hGroup = OpenClusterGroup( m_hCluster, bstrGroup );
  2208. if ( hGroup != NULL )
  2209. {
  2210. hr = THR( CGroupHandle::S_HrCreateInstance( ppghOut, hGroup ) );
  2211. if ( FAILED( hr ) )
  2212. {
  2213. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log,
  2214. TASKID_Minor_HrFindGroupFromResourceOrItsDependents_Create_CGroupHandle,
  2215. hr,
  2216. L""
  2217. );
  2218. goto Cleanup;
  2219. }
  2220. hGroup = NULL; // gave ownership away above
  2221. goto Cleanup;
  2222. }
  2223. else
  2224. {
  2225. hr = HRESULT_FROM_WIN32( TW32( GetLastError() ) );
  2226. SSR_LOG1( TASKID_Major_Client_And_Server_Log,
  2227. TASKID_Minor_HrFindGroupFromResourceOrItsDependents_OpenClusterGroup,
  2228. hr,
  2229. L"[Grouping] %1!ws!: OpenClusterGroup() failed. Aborting.",
  2230. bstrNotification,
  2231. bstrGroup
  2232. );
  2233. goto Cleanup;
  2234. }
  2235. }
  2236. else
  2237. {
  2238. DWORD dwErr = GetLastError();
  2239. switch ( dwErr )
  2240. {
  2241. case ERROR_MORE_DATA:
  2242. cbGroup += sizeof(WCHAR); // add terminating NULL
  2243. TraceSysFreeString( bstrGroup );
  2244. goto ReAllocGroupName;
  2245. default:
  2246. hr = HRESULT_FROM_WIN32( TW32( GetLastError() ) );
  2247. SSR_LOG1( TASKID_Major_Client_And_Server_Log,
  2248. TASKID_Minor_HrFindGroupFromResourceOrItsDependents_GetClusterResourceState,
  2249. hr,
  2250. L"[Grouping] %1!ws!: GetClusterResourceState( ) failed. Aborting.",
  2251. bstrNotification,
  2252. bstrName
  2253. );
  2254. goto Cleanup;
  2255. }
  2256. }
  2257. }
  2258. // else the resource might not exist... continue....
  2259. //
  2260. // Follow the depents list.
  2261. //
  2262. hr = THR( presentry->GetCountOfDependents( &cDependents ) );
  2263. if ( FAILED( hr ) )
  2264. {
  2265. SSR_LOG_ERR(
  2266. TASKID_Major_Client_And_Server_Log
  2267. , TASKID_Minor_HrFindGroupFromResourceOrItsDependents_GetCountOfDependents
  2268. , hr
  2269. , L""
  2270. );
  2271. goto Cleanup;
  2272. }
  2273. for ( ; cDependents != 0 ; )
  2274. {
  2275. cDependents --;
  2276. hr = THR( presentry->GetDependent( cDependents, &idxDependent, &dfDependent ) );
  2277. if ( FAILED( hr ) )
  2278. {
  2279. SSR_LOG_ERR(
  2280. TASKID_Major_Client_And_Server_Log
  2281. , TASKID_Minor_HrFindGroupFromResourceOrItsDependents_GetDependent
  2282. , hr
  2283. , L""
  2284. );
  2285. goto Cleanup;
  2286. }
  2287. hr = STHR( HrFindGroupFromResourceOrItsDependents( idxDependent, ppghOut) );
  2288. if ( FAILED( hr ) )
  2289. goto Cleanup;
  2290. if ( hr == S_OK && *ppghOut != NULL )
  2291. goto Cleanup;
  2292. } // for: cDependents
  2293. //
  2294. // Failed to find an existing group.
  2295. //
  2296. hr = S_FALSE;
  2297. *ppghOut = NULL;
  2298. Cleanup:
  2299. if ( hResourceToClose != NULL )
  2300. {
  2301. CloseClusterResource( hResourceToClose );
  2302. }
  2303. if ( hGroup != NULL )
  2304. {
  2305. CloseClusterGroup( hGroup );
  2306. }
  2307. TraceSysFreeString( bstrGroup );
  2308. TraceSysFreeString( bstrNotification );
  2309. HRETURN( hr );
  2310. OutOfMemory:
  2311. hr = E_OUTOFMEMORY;
  2312. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log,
  2313. TASKID_Minor_HrFindGroupFromResourceOrItsDependents_OutOfMemory,
  2314. hr,
  2315. L"Out of Memory."
  2316. );
  2317. goto Cleanup;
  2318. } // HrFindGroupFromResourceOrItsDependents()
  2319. //////////////////////////////////////////////////////////////////////////////
  2320. //
  2321. // HRESULT
  2322. // CPostCfgManager::HrCreateResourceAndDependents(
  2323. // ULONG idxResourceIn
  2324. // )
  2325. //
  2326. //////////////////////////////////////////////////////////////////////////////
  2327. HRESULT
  2328. CPostCfgManager::HrCreateResourceAndDependents(
  2329. ULONG idxResourceIn
  2330. )
  2331. {
  2332. TraceFunc1( "idxResourceIn = %u", idxResourceIn );
  2333. HRESULT hr;
  2334. BSTR bstrName; // don't free!
  2335. ULONG cDependents;
  2336. ULONG idxDependent;
  2337. HGROUP hGroup; // don't close!
  2338. HRESOURCE hResource;
  2339. const CLSID * pclsidResType;
  2340. CGroupHandle * pgh;
  2341. EDependencyFlags dfDependent;
  2342. BSTR bstrNotification = NULL;
  2343. IClusCfgManagedResourceCfg * pccmrc = NULL;
  2344. CResourceEntry * presentry = m_rgpResources[ idxResourceIn ];
  2345. IUnknown * punkServices = NULL;
  2346. IPrivatePostCfgResource * ppcr = NULL;
  2347. IClusCfgResourceCreate * pccrc = NULL;
  2348. // Validate state
  2349. Assert( m_peccmr != NULL );
  2350. Assert( m_pccci != NULL );
  2351. //
  2352. // Create a service object for this resource.
  2353. //
  2354. hr = THR( CCreateServices::S_HrCreateInstance( &punkServices ) );
  2355. if ( FAILED( hr ) )
  2356. {
  2357. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log,
  2358. TASKID_Minor_HrCreateResourceAndDependents_Create_CCreateServices,
  2359. hr,
  2360. L"[Create] Failed to create services object. Aborting."
  2361. );
  2362. goto Cleanup;
  2363. }
  2364. hr = THR( punkServices->TypeSafeQI( IPrivatePostCfgResource, &ppcr ) );
  2365. if ( FAILED( hr ) )
  2366. {
  2367. SSR_LOG_ERR(
  2368. TASKID_Major_Client_And_Server_Log
  2369. , TASKID_Minor_HrCreateResourceAndDependents_Create_CCreateServices_QI
  2370. , hr
  2371. , L""
  2372. );
  2373. goto Cleanup;
  2374. }
  2375. hr = THR( ppcr->SetEntry( presentry ) );
  2376. if ( FAILED( hr ) )
  2377. {
  2378. SSR_LOG_ERR(
  2379. TASKID_Major_Client_And_Server_Log
  2380. , TASKID_Minor_HrCreateResourceAndDependents_SetEntry
  2381. , hr
  2382. , L""
  2383. );
  2384. goto Cleanup;
  2385. }
  2386. //
  2387. // See if it was configured in a previous pass.
  2388. //
  2389. hr = STHR( presentry->IsConfigured() );
  2390. if ( FAILED( hr ) )
  2391. {
  2392. SSR_LOG_ERR(
  2393. TASKID_Major_Client_And_Server_Log
  2394. , TASKID_Minor_HrCreateResourceAndDependents_IsConfigured
  2395. , hr
  2396. , L""
  2397. );
  2398. goto Cleanup;
  2399. }
  2400. if ( hr == S_FALSE )
  2401. {
  2402. //
  2403. // Make sure that Create() is not called again because of recursion.
  2404. //
  2405. hr = THR( presentry->SetConfigured( TRUE ) );
  2406. if ( FAILED( hr ) )
  2407. {
  2408. SSR_LOG_ERR(
  2409. TASKID_Major_Client_And_Server_Log
  2410. , TASKID_Minor_HrCreateResourceAndDependents_SetConfigured
  2411. , hr
  2412. , L""
  2413. );
  2414. goto Cleanup;
  2415. }
  2416. //
  2417. // Grab some useful information: name, group handle, ...
  2418. //
  2419. hr = THR( presentry->GetName( &bstrName ) );
  2420. if ( FAILED( hr ) )
  2421. {
  2422. SSR_LOG_ERR(
  2423. TASKID_Major_Client_And_Server_Log
  2424. , TASKID_Minor_HrCreateResourceAndDependents_GetName
  2425. , hr
  2426. , L""
  2427. );
  2428. goto Cleanup;
  2429. }
  2430. hr = THR( presentry->GetGroupHandle( &pgh) );
  2431. if ( FAILED( hr ) )
  2432. {
  2433. SSR_LOG_ERR(
  2434. TASKID_Major_Client_And_Server_Log
  2435. , TASKID_Minor_HrCreateResourceAndDependents_GetGroupHandle
  2436. , hr
  2437. , L""
  2438. );
  2439. goto Cleanup;
  2440. }
  2441. hr = THR( pgh->GetHandle( &hGroup ) );
  2442. pgh->Release(); // release promptly
  2443. if ( FAILED( hr ) )
  2444. {
  2445. SSR_LOG_ERR(
  2446. TASKID_Major_Client_And_Server_Log
  2447. , TASKID_Minor_HrCreateResourceAndDependents_GetHandle
  2448. , hr
  2449. , L""
  2450. );
  2451. goto Cleanup;
  2452. }
  2453. //
  2454. // Some resource that we pre-create don't have an associated managed resource.
  2455. // Skip "creating" them but do create their dependents. Note that "special"
  2456. // resources are create below in the else statement.
  2457. //
  2458. // Don't wrap - this can fail with Win32 ERROR_INVALID_DATA if the pointer is invalid.
  2459. hr = presentry->GetAssociatedResource( &pccmrc );
  2460. if ( FAILED( hr ) && hr != HRESULT_FROM_WIN32( ERROR_INVALID_DATA ) )
  2461. {
  2462. THR( hr );
  2463. SSR_LOG_ERR(
  2464. TASKID_Major_Client_And_Server_Log
  2465. , TASKID_Minor_HrCreateResourceAndDependents_GetAssociatedResource
  2466. , hr
  2467. , L""
  2468. );
  2469. goto Cleanup;
  2470. }
  2471. if ( SUCCEEDED( hr ) )
  2472. {
  2473. // Don't wrap - this can fail with E_NOTIMPL.
  2474. hr = pccmrc->Create( punkServices );
  2475. if ( FAILED( hr ) )
  2476. {
  2477. if ( hr == E_NOTIMPL )
  2478. {
  2479. hr = S_OK; // ignore the error.
  2480. } // if: E_NOTIMPL
  2481. else
  2482. {
  2483. HRESULT hr2;
  2484. SSR_LOG1( TASKID_Major_Client_And_Server_Log,
  2485. TASKID_Minor_HrCreateResourceAndDependents_Create_Failed,
  2486. hr,
  2487. L"[Create] %1!ws!: Create() failed. Its dependents may not be created. Skipping.",
  2488. bstrNotification,
  2489. bstrName
  2490. );
  2491. hr2 = THR( HrLoadStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_RESOURCE_FAILED_CREATE, &bstrNotification ) );
  2492. if ( FAILED( hr2 ) )
  2493. {
  2494. SSR_LOG_ERR(
  2495. TASKID_Major_Client_And_Server_Log
  2496. , TASKID_Minor_HrCreateResourceAndDependents_LoadString_CreateFailed
  2497. , hr
  2498. , L""
  2499. );
  2500. hr = hr2;
  2501. goto Cleanup;
  2502. }
  2503. hr = THR( SendStatusReport( NULL,
  2504. TASKID_Major_Configure_Resources,
  2505. TASKID_Minor_Resource_Failed_Create,
  2506. 0,
  2507. 1,
  2508. 1,
  2509. MAKE_HRESULT( 0, HRESULT_FACILITY( hr ), HRESULT_CODE( hr ) ),
  2510. bstrNotification,
  2511. NULL,
  2512. NULL
  2513. ) );
  2514. if ( hr == E_ABORT )
  2515. goto Cleanup;
  2516. // ignore failure
  2517. } // else: other failure
  2518. } // if: failure
  2519. if ( SUCCEEDED( hr ) )
  2520. {
  2521. LPCWSTR pcszResType; // don't free.
  2522. hr = THR( presentry->GetTypePtr( &pclsidResType ) );
  2523. if ( FAILED( hr ) )
  2524. {
  2525. SSR_LOG_ERR(
  2526. TASKID_Major_Client_And_Server_Log
  2527. , TASKID_Minor_HrCreateResourceAndDependents_GetTypePtr
  2528. , hr
  2529. , L""
  2530. );
  2531. goto Cleanup;
  2532. }
  2533. pcszResType = PcszLookupTypeNameByGUID( *pclsidResType );
  2534. if ( pcszResType == NULL )
  2535. {
  2536. SSR_LOG1( TASKID_Major_Client_And_Server_Log,
  2537. TASKID_Minor_HrCreateResourceAndDependents_PcszLookupTypeNameByGUID,
  2538. hr,
  2539. L"[Create] %1!ws!: Resource cannot be created because the resource type is not registered. Its dependents may not be created. Skipping.",
  2540. bstrNotification,
  2541. bstrName
  2542. );
  2543. }
  2544. else
  2545. {
  2546. hr = THR( HrCreateResourceInstance( idxResourceIn, hGroup, pcszResType, &hResource ) );
  2547. if ( FAILED( hr ) )
  2548. goto Cleanup;
  2549. }
  2550. } // if: success
  2551. } // if: interface
  2552. else
  2553. {
  2554. //
  2555. // See if it is one of the "special" types that we can generate on the fly.
  2556. //
  2557. const CLSID * pclsidType;
  2558. hr = THR( presentry->GetTypePtr( &pclsidType ) );
  2559. if ( FAILED( hr ) )
  2560. {
  2561. SSR_LOG_ERR(
  2562. TASKID_Major_Client_And_Server_Log
  2563. , TASKID_Minor_HrCreateResourceAndDependents_InvalidData_GetTypePtr
  2564. , hr
  2565. , L""
  2566. );
  2567. goto Cleanup;
  2568. }
  2569. if ( *pclsidType == RESTYPE_NetworkName )
  2570. {
  2571. //
  2572. // Create a new network name resource.
  2573. //
  2574. hr = THR( punkServices->TypeSafeQI( IClusCfgResourceCreate, &pccrc ) );
  2575. if ( FAILED( hr ) )
  2576. {
  2577. SSR_LOG_ERR(
  2578. TASKID_Major_Client_And_Server_Log
  2579. , TASKID_Minor_HrCreateResourceAndDependents_NetworkName_QI_pccrc
  2580. , hr
  2581. , L""
  2582. );
  2583. goto Cleanup;
  2584. }
  2585. hr = THR( pccrc->SetPropertyString( L"Name", bstrName ) );
  2586. if ( FAILED( hr ) )
  2587. {
  2588. SSR_LOG_ERR(
  2589. TASKID_Major_Client_And_Server_Log
  2590. , TASKID_Minor_HrCreateResourceAndDependents_NetworkName_SetPropertyString
  2591. , hr
  2592. , L""
  2593. );
  2594. goto Cleanup;
  2595. }
  2596. hr = THR( HrCreateResourceInstance( idxResourceIn, hGroup, L"Network Name", &hResource ) );
  2597. if ( FAILED( hr ) )
  2598. goto Cleanup;
  2599. }
  2600. else if ( *pclsidType == RESTYPE_IPAddress )
  2601. {
  2602. //
  2603. // Create a new IP address resource.
  2604. //
  2605. hr = THR( punkServices->TypeSafeQI( IClusCfgResourceCreate, &pccrc ) );
  2606. if ( FAILED( hr ) )
  2607. {
  2608. SSR_LOG_ERR(
  2609. TASKID_Major_Client_And_Server_Log
  2610. , TASKID_Minor_HrCreateResourceAndDependents_IPAddress_QI_pccrc
  2611. , hr
  2612. , L""
  2613. );
  2614. goto Cleanup;
  2615. }
  2616. //
  2617. // TODO: gpease 21-JUN-2000
  2618. // Since we do not have a way to generate an appropriate IP address,
  2619. // we don't set any properties. This will cause it to fail to come
  2620. // online.
  2621. //
  2622. hr = THR( HrCreateResourceInstance( idxResourceIn, hGroup, L"IP Address", &hResource ) );
  2623. if ( FAILED( hr ) )
  2624. goto Cleanup;
  2625. }
  2626. else
  2627. {
  2628. //
  2629. // else... the resource is one of the pre-created resources that BaseCluster
  2630. // created. Log and continue creating its dependents.
  2631. //
  2632. hr = S_OK;
  2633. SSR_LOG1( TASKID_Major_Client_And_Server_Log,
  2634. TASKID_Minor_HrCreateResourceAndDependents_NothingNew,
  2635. hr,
  2636. L"[Create] %1!ws!: Nothing new to create. Configuring dependents.",
  2637. bstrNotification,
  2638. bstrName
  2639. );
  2640. }
  2641. } // else: no interface
  2642. } // if: not created
  2643. //
  2644. // Now that we created the resource instance, we need to create its dependents.
  2645. //
  2646. hr = THR( presentry->GetCountOfDependents( &cDependents ) );
  2647. if ( FAILED( hr ) )
  2648. {
  2649. SSR_LOG_ERR(
  2650. TASKID_Major_Client_And_Server_Log
  2651. , TASKID_Minor_HrCreateResourceAndDependents_Dependents_GetCountOfDependents
  2652. , hr
  2653. , L""
  2654. );
  2655. goto Cleanup;
  2656. }
  2657. for( ; cDependents != 0; )
  2658. {
  2659. DWORD dw;
  2660. BSTR bstrDependent;
  2661. HRESOURCE hResourceDependent;
  2662. CResourceEntry * presentryDependent;
  2663. cDependents --;
  2664. hr = THR( presentry->GetDependent( cDependents, &idxDependent, &dfDependent ) );
  2665. if ( FAILED( hr ) )
  2666. {
  2667. SSR_LOG_ERR(
  2668. TASKID_Major_Client_And_Server_Log
  2669. , TASKID_Minor_HrCreateResourceAndDependents_Dependents_GetDependent
  2670. , hr
  2671. , L""
  2672. );
  2673. continue;
  2674. }
  2675. hr = THR( HrCreateResourceAndDependents( idxDependent ) );
  2676. if ( FAILED( hr ) )
  2677. continue;
  2678. //
  2679. // Add the dependencies on the resource.
  2680. //
  2681. presentryDependent = m_rgpResources[ idxDependent ];
  2682. hr = THR( presentryDependent->GetName( &bstrDependent ) );
  2683. if ( FAILED( hr ) )
  2684. {
  2685. SSR_LOG_ERR(
  2686. TASKID_Major_Client_And_Server_Log
  2687. , TASKID_Minor_HrCreateResourceAndDependents_Dependents_GetName
  2688. , hr
  2689. , L""
  2690. );
  2691. continue;
  2692. }
  2693. hr = THR( presentryDependent->GetHResource( &hResourceDependent ) );
  2694. if ( FAILED( hr ) )
  2695. {
  2696. SSR_LOG_ERR(
  2697. TASKID_Major_Client_And_Server_Log
  2698. , TASKID_Minor_HrCreateResourceAndDependents_Dependents_GetHResource
  2699. , hr
  2700. , L""
  2701. );
  2702. continue;
  2703. }
  2704. dw = TW32( AddClusterResourceDependency( hResourceDependent, hResource ) );
  2705. if ( dw != ERROR_SUCCESS )
  2706. {
  2707. hr = HRESULT_FROM_WIN32( dw );
  2708. SSR_LOG2( TASKID_Major_Client_And_Server_Log,
  2709. TASKID_Minor_HrCreateResourceAndDependents_Dependents_AddClusterResourceDependency,
  2710. hr,
  2711. L"[Create] %1!ws!: Could not set dependency on %2!ws!.",
  2712. bstrNotification,
  2713. bstrDependent,
  2714. bstrName
  2715. );
  2716. }
  2717. else
  2718. {
  2719. hr = S_OK;
  2720. SSR_LOG2( TASKID_Major_Client_And_Server_Log,
  2721. TASKID_Minor_HrCreateResourceAndDependents_Dependents_Succeeded,
  2722. hr,
  2723. L"[Create] %1!ws!: Successfully set dependency set on %2!ws!.",
  2724. bstrNotification,
  2725. bstrDependent,
  2726. bstrName
  2727. );
  2728. }
  2729. } // for: cDependents
  2730. hr = S_OK;
  2731. Cleanup:
  2732. TraceSysFreeString( bstrNotification );
  2733. if ( pccmrc != NULL )
  2734. {
  2735. pccmrc->Release();
  2736. }
  2737. if ( punkServices != NULL )
  2738. {
  2739. punkServices->Release();
  2740. }
  2741. if ( ppcr != NULL )
  2742. {
  2743. ppcr->Release();
  2744. }
  2745. if ( pccrc != NULL )
  2746. {
  2747. pccrc->Release();
  2748. }
  2749. HRETURN( hr );
  2750. } // HrCreateResourceAndDependents()
  2751. //////////////////////////////////////////////////////////////////////////////
  2752. //
  2753. // HRESULT
  2754. // CPostCfgManager::HrPostCreateResourceAndDependents(
  2755. // ULONG idxResourceIn
  2756. // )
  2757. //
  2758. //////////////////////////////////////////////////////////////////////////////
  2759. HRESULT
  2760. CPostCfgManager::HrPostCreateResourceAndDependents(
  2761. ULONG idxResourceIn
  2762. )
  2763. {
  2764. TraceFunc1( "idxResourceIn = %u", idxResourceIn );
  2765. Assert( m_ecmCommitChangesMode != cmUNKNOWN );
  2766. HRESULT hr;
  2767. BSTR bstrName; // don't free
  2768. ULONG cDependents;
  2769. ULONG idxDependent;
  2770. HRESOURCE hResource;
  2771. EDependencyFlags dfDependent;
  2772. BSTR bstrNotification = NULL;
  2773. BSTR bstrLocalQuorumNotification = NULL;
  2774. IClusCfgManagedResourceCfg * pccmrc = NULL;
  2775. CResourceEntry * presentry = m_rgpResources[ idxResourceIn ];
  2776. IUnknown * punkServices = NULL;
  2777. IPrivatePostCfgResource * ppcr = NULL;
  2778. // Validate state
  2779. Assert( m_peccmr != NULL );
  2780. Assert( m_pccci != NULL );
  2781. hr = STHR( presentry->IsConfigured() );
  2782. if ( FAILED( hr ) )
  2783. {
  2784. SSR_LOG_ERR(
  2785. TASKID_Major_Client_And_Server_Log
  2786. , TASKID_Minor_HrPostCreateResourceAndDependents_IsConfigured
  2787. , hr
  2788. , L""
  2789. );
  2790. goto Cleanup;
  2791. }
  2792. if ( hr == S_FALSE )
  2793. {
  2794. //
  2795. // Make sure that PostCreate() is not called again because of recursion.
  2796. //
  2797. hr = THR( presentry->SetConfigured( TRUE ) );
  2798. if ( FAILED( hr ) )
  2799. {
  2800. SSR_LOG_ERR(
  2801. TASKID_Major_Client_And_Server_Log
  2802. , TASKID_Minor_HrPostCreateResourceAndDependents_SetConfigured
  2803. , hr
  2804. , L""
  2805. );
  2806. goto Cleanup;
  2807. }
  2808. //
  2809. // Grab the name of the resource for logging.
  2810. //
  2811. hr = THR( presentry->GetName( &bstrName ) );
  2812. if ( FAILED( hr ) )
  2813. {
  2814. SSR_LOG_ERR(
  2815. TASKID_Major_Client_And_Server_Log
  2816. , TASKID_Minor_HrPostCreateResourceAndDependents_GetName
  2817. , hr
  2818. , L""
  2819. );
  2820. goto Cleanup;
  2821. }
  2822. //
  2823. // Bring the resource online.
  2824. //
  2825. hr = presentry->GetHResource( &hResource );
  2826. if ( SUCCEEDED( hr ) )
  2827. {
  2828. DWORD dwErr;
  2829. // Don't wrap - can return ERROR_IO_PENDING.
  2830. dwErr = OnlineClusterResource( hResource );
  2831. switch ( dwErr )
  2832. {
  2833. case ERROR_SUCCESS:
  2834. SSR_LOG1( TASKID_Major_Client_And_Server_Log,
  2835. TASKID_Minor_HrPostCreateResourceAndDependents_OpenClusterResource,
  2836. hr,
  2837. L"[PostCreate] %1!ws!: Resource brought online successfully.",
  2838. bstrNotification,
  2839. bstrName
  2840. );
  2841. hr = S_OK;
  2842. break;
  2843. case ERROR_IO_PENDING:
  2844. {
  2845. CLUSTER_RESOURCE_STATE crs = ClusterResourceOnlinePending;
  2846. hr = HRESULT_FROM_WIN32( dwErr );
  2847. SSR_LOG1( TASKID_Major_Client_And_Server_Log,
  2848. TASKID_Minor_HrPostCreateResourceAndDependents_OpenClusterResourcePending,
  2849. hr,
  2850. L"[PostCreate] %1!ws!: Online pending...",
  2851. bstrNotification,
  2852. bstrName
  2853. );
  2854. for( ; crs == ClusterResourceOnlinePending ; )
  2855. {
  2856. crs = GetClusterResourceState( hResource,
  2857. NULL,
  2858. NULL,
  2859. NULL,
  2860. NULL
  2861. );
  2862. switch ( crs )
  2863. {
  2864. case ClusterResourceOnline:
  2865. // no-op
  2866. hr = S_OK;
  2867. break;
  2868. case ClusterResourceInitializing:
  2869. crs = ClusterResourceOnlinePending;
  2870. // fall thru
  2871. case ClusterResourceOnlinePending:
  2872. Sleep( 500 ); // sleep a 1/2 second
  2873. break;
  2874. case ClusterResourceStateUnknown:
  2875. dwErr = GetLastError();
  2876. hr = HRESULT_FROM_WIN32( TW32( dwErr ) );
  2877. SSR_LOG1( TASKID_Major_Client_And_Server_Log,
  2878. TASKID_Minor_HrPostCreateResourceAndDependents_ClusterResourceStateUnknown,
  2879. hr,
  2880. L"[PostCreate] %1!ws!: Resource failed to come online. Dependent resources might fail too.",
  2881. bstrNotification,
  2882. bstrName
  2883. );
  2884. break;
  2885. case ClusterResourceOfflinePending:
  2886. case ClusterResourceOffline:
  2887. hr = THR( E_FAIL );
  2888. SSR_LOG1( TASKID_Major_Client_And_Server_Log,
  2889. TASKID_Minor_HrPostCreateResourceAndDependents_ClusterResourceOffline,
  2890. hr,
  2891. L"[PostCreate] %1!ws!: Resource went offline. Dependent resources might fail too.",
  2892. bstrNotification,
  2893. bstrName
  2894. );
  2895. break;
  2896. case ClusterResourceFailed:
  2897. hr = E_FAIL;
  2898. SSR_LOG1( TASKID_Major_Client_And_Server_Log,
  2899. TASKID_Minor_HrPostCreateResourceAndDependents_ClusterResourceFailed,
  2900. hr,
  2901. L"[PostCreate] %1!ws!: Resource failed. Check Event Log. Dependent resources might fail too.",
  2902. bstrNotification,
  2903. bstrName
  2904. );
  2905. break;
  2906. } // switch: crs
  2907. } // for: crs
  2908. }
  2909. break;
  2910. default:
  2911. hr = HRESULT_FROM_WIN32( TW32( dwErr ) );
  2912. SSR_LOG1( TASKID_Major_Client_And_Server_Log,
  2913. TASKID_Minor_HrPostCreateResourceAndDependents_OnlineClusterResource_Failed,
  2914. hr,
  2915. L"[PostCreate] %1!ws!: Resource failed to come online. Dependent resources might fail too.",
  2916. bstrNotification,
  2917. bstrName
  2918. );
  2919. break;
  2920. } // switch: dwErr
  2921. } // if: hResource
  2922. //
  2923. // Set it to the quorum resource if marked so.
  2924. //
  2925. if ( SUCCEEDED( hr )
  2926. && idxResourceIn == m_idxQuorumResource
  2927. )
  2928. {
  2929. DWORD dwErr;
  2930. dwErr = TW32( SetClusterQuorumResource( hResource, NULL, CLUSTER_QUORUM_DEFAULT_MAX_LOG_SIZE ) );
  2931. if ( dwErr != ERROR_SUCCESS )
  2932. {
  2933. hr = HRESULT_FROM_WIN32( dwErr );
  2934. SSR_LOG1( TASKID_Major_Client_And_Server_Log,
  2935. TASKID_Minor_HrPostCreateResourceAndDependents_SetClusterQuorumResource,
  2936. hr,
  2937. L"[PostCreate] %1!ws!: Failure setting resource to be the quorum resource.",
  2938. bstrNotification,
  2939. bstrName
  2940. );
  2941. }
  2942. else
  2943. {
  2944. SSR_LOG1( TASKID_Major_Client_And_Server_Log,
  2945. TASKID_Minor_HrPostCreateResourceAndDependents_SetClusterQuorumResource_Succeeded,
  2946. hr,
  2947. L"[PostCreate] %1!ws!: Successfully set as quorum resource.",
  2948. bstrNotification,
  2949. bstrName
  2950. );
  2951. }
  2952. //
  2953. // Create a notification about setting the quorum resource.
  2954. //
  2955. hr = THR( HrFormatMessageIntoBSTR( g_hInstance,
  2956. IDS_TASKID_MINOR_SET_QUORUM_DEVICE,
  2957. &bstrNotification,
  2958. bstrName
  2959. ) );
  2960. if ( FAILED( hr ) )
  2961. {
  2962. SSR_LOG_ERR(
  2963. TASKID_Major_Client_And_Server_Log
  2964. , TASKID_Minor_HrPostCreateResourceAndDependents_FormatMessage_SetQuorum
  2965. , hr
  2966. , L""
  2967. );
  2968. // ignore the failure.
  2969. }
  2970. //
  2971. // Send a status that we found the quorum device.
  2972. //
  2973. hr = THR( SendStatusReport( NULL,
  2974. TASKID_Major_Configure_Resources,
  2975. TASKID_Minor_Set_Quorum_Device,
  2976. 0,
  2977. 5,
  2978. 5,
  2979. HRESULT_FROM_WIN32( dwErr ),
  2980. bstrNotification,
  2981. NULL,
  2982. NULL
  2983. ) );
  2984. if ( hr == E_ABORT )
  2985. goto Cleanup;
  2986. // ignore failure
  2987. // Do this only if the quorum has changed.
  2988. if ( ( dwErr == ERROR_SUCCESS ) && ( m_ecmCommitChangesMode == cmCREATE_CLUSTER ) && m_isQuorumChanged)
  2989. {
  2990. TraceFlow( "We are forming a cluster and the quorum resouce has changed - trying to delete the local quorum resource." );
  2991. m_dwLocalQuorumStatusMax = 0;
  2992. //
  2993. // If we are here, we are forming and we have successfully set a new quorum resource.
  2994. // So, delete the local quorum resource.
  2995. //
  2996. // Create a notification about deleting the local quorum resource.
  2997. hr = THR( HrFormatMessageIntoBSTR( g_hInstance, IDS_DELETING_LOCAL_QUORUM_RESOURCE, &bstrLocalQuorumNotification ) );
  2998. // ignore the failure.
  2999. // Send a status that we are deleting the quorum device.
  3000. hr = THR( SendStatusReport( NULL,
  3001. TASKID_Major_Configure_Resources,
  3002. TASKID_Minor_Delete_LocalQuorum,
  3003. 0,
  3004. m_dwLocalQuorumStatusMax,
  3005. m_dwLocalQuorumStatusMax,
  3006. HRESULT_FROM_WIN32( dwErr ),
  3007. bstrLocalQuorumNotification,
  3008. NULL,
  3009. NULL
  3010. ) );
  3011. dwErr = TW32(
  3012. ResUtilEnumResourcesEx(
  3013. m_hCluster
  3014. , NULL
  3015. , CLUS_RESTYPE_NAME_LKQUORUM
  3016. , S_DwDeleteLocalQuorumResource
  3017. , this
  3018. )
  3019. );
  3020. if ( dwErr != ERROR_SUCCESS )
  3021. {
  3022. LogMsg( "PostCfg: An error occurred trying to enumerate localquorum resources (dwErr=%#08x).", dwErr );
  3023. } // if: an error occurred trying to enumerate all local quorum resources
  3024. else
  3025. {
  3026. LogMsg( "PostCfg: Successfully deleted the local quorum resource." );
  3027. } // if: we successfully deleted the localquorum resource
  3028. // Complete the status that we are deleting the quorum device.
  3029. ++m_dwLocalQuorumStatusMax;
  3030. hr = THR( SendStatusReport( NULL,
  3031. TASKID_Major_Configure_Resources,
  3032. TASKID_Minor_Delete_LocalQuorum,
  3033. 0,
  3034. m_dwLocalQuorumStatusMax,
  3035. m_dwLocalQuorumStatusMax,
  3036. HRESULT_FROM_WIN32( dwErr ),
  3037. NULL, // don't update text
  3038. NULL,
  3039. NULL
  3040. ) );
  3041. } // if: we are forming a cluster and there have been no errors setting the quorum resource
  3042. hr = THR( SendStatusReport( NULL,
  3043. TASKID_Major_Configure_Resources,
  3044. TASKID_Minor_Locate_Existing_Quorum_Device,
  3045. 0,
  3046. 10,
  3047. 10,
  3048. hr,
  3049. NULL, // don't update text
  3050. NULL,
  3051. NULL
  3052. ) );
  3053. if ( hr == E_ABORT )
  3054. goto Cleanup;
  3055. // ignore failure
  3056. }
  3057. //
  3058. // Some resource that we pre-create don't have an associated
  3059. // managed resource. Skip "creating" them but do create their
  3060. // dependents.
  3061. //
  3062. // Don't wrap - this can fail with Win32 ERROR_INVALID_DATA if the pointer is invalid.
  3063. hr = presentry->GetAssociatedResource( &pccmrc );
  3064. if ( FAILED( hr ) && hr != HRESULT_FROM_WIN32( ERROR_INVALID_DATA ) )
  3065. {
  3066. THR( hr );
  3067. SSR_LOG_ERR(
  3068. TASKID_Major_Client_And_Server_Log
  3069. , TASKID_Minor_HrPostCreateResourceAndDependents_GetAssociatedResource
  3070. , hr
  3071. , L""
  3072. );
  3073. goto Error;
  3074. }
  3075. if ( SUCCEEDED( hr ) )
  3076. {
  3077. //
  3078. // Create a service object for this resource.
  3079. //
  3080. hr = THR( CPostCreateServices::S_HrCreateInstance( &punkServices ) );
  3081. if ( FAILED( hr ) )
  3082. {
  3083. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log,
  3084. TASKID_Minor_HrPostCreateResourceAndDependents_Create_CPostCreateServices,
  3085. hr,
  3086. L"[PostCreate] Failed to create services object. Aborting."
  3087. );
  3088. goto Error;
  3089. }
  3090. hr = THR( punkServices->TypeSafeQI( IPrivatePostCfgResource, &ppcr ) );
  3091. if ( FAILED( hr ) )
  3092. {
  3093. SSR_LOG_ERR(
  3094. TASKID_Major_Client_And_Server_Log
  3095. , TASKID_Minor_HrPostCreateResourceAndDependents_Create_CPostCreateServices_QI_ppcr
  3096. , hr
  3097. , L""
  3098. );
  3099. goto Error;
  3100. }
  3101. hr = THR( ppcr->SetEntry( presentry ) );
  3102. if ( FAILED( hr ) )
  3103. {
  3104. SSR_LOG_ERR(
  3105. TASKID_Major_Client_And_Server_Log
  3106. , TASKID_Minor_HrPostCreateResourceAndDependents_SetEntry
  3107. , hr
  3108. , L""
  3109. );
  3110. goto Error;
  3111. }
  3112. // Don't wrap - this can fail with E_NOTIMPL.
  3113. hr = pccmrc->PostCreate( punkServices );
  3114. if ( FAILED( hr ) )
  3115. {
  3116. if ( hr == E_NOTIMPL )
  3117. {
  3118. SSR_LOG1( TASKID_Major_Client_And_Server_Log,
  3119. TASKID_Minor_HrPostCreateResourceAndDependents_PostCreate_E_NOTIMPL,
  3120. hr,
  3121. L"[PostCreate] %1!ws!: PostCreate() returned E_NOTIMPL. Ignoring.",
  3122. bstrNotification,
  3123. bstrName
  3124. );
  3125. } // if: E_NOTIMPL
  3126. else
  3127. {
  3128. HRESULT hr2;
  3129. SSR_LOG1( TASKID_Major_Client_And_Server_Log,
  3130. TASKID_Minor_HrPostCreateResourceAndDependents_PostCreate_Failed,
  3131. hr,
  3132. L"[PostCreate] %1!ws!: PostCreate() failed. Ignoring.",
  3133. bstrNotification,
  3134. bstrName
  3135. );
  3136. hr2 = THR( HrFormatMessageIntoBSTR( g_hInstance,
  3137. IDS_TASKID_MINOR_RESOURCE_FAILED_POSTCREATE_LOG,
  3138. &bstrNotification,
  3139. bstrName,
  3140. hr
  3141. ) );
  3142. if ( FAILED( hr2 ) )
  3143. {
  3144. hr = hr2;
  3145. SSR_LOG_ERR(
  3146. TASKID_Major_Client_And_Server_Log
  3147. , TASKID_Minor_HrPostCreateResourceAndDependents_FormatMessage_PostCreate_Failed
  3148. , hr
  3149. , L""
  3150. );
  3151. goto Cleanup;
  3152. }
  3153. hr2 = THR( SendStatusReport( NULL,
  3154. TASKID_Major_Client_And_Server_Log,
  3155. TASKID_Minor_Resource_Failed_PostCreate,
  3156. 0,
  3157. 1,
  3158. 1,
  3159. hr,
  3160. bstrNotification,
  3161. NULL,
  3162. NULL
  3163. ) );
  3164. if ( FAILED( hr2 ) )
  3165. {
  3166. hr = hr2;
  3167. goto Cleanup;
  3168. }
  3169. hr2 = THR( HrLoadStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_RESOURCE_FAILED_POSTCREATE, &bstrNotification ) );
  3170. if ( FAILED( hr2 ) )
  3171. {
  3172. hr = hr2;
  3173. SSR_LOG_ERR(
  3174. TASKID_Major_Client_And_Server_Log
  3175. , TASKID_Minor_HrPostCreateResourceAndDependents_FormatMessage_ResourcePostCreate_Failed
  3176. , hr
  3177. , L""
  3178. );
  3179. goto Cleanup;
  3180. }
  3181. hr = THR( SendStatusReport( NULL,
  3182. TASKID_Major_Configure_Resources,
  3183. TASKID_Minor_Resource_Failed_PostCreate,
  3184. 0,
  3185. 1,
  3186. 1,
  3187. MAKE_HRESULT( 0, HRESULT_FACILITY( hr ), HRESULT_CODE( hr ) ),
  3188. bstrNotification,
  3189. NULL,
  3190. NULL
  3191. ) );
  3192. if ( hr == E_ABORT )
  3193. goto Cleanup;
  3194. // ignore failure
  3195. } // else: other failure
  3196. } // if: failure
  3197. else
  3198. {
  3199. SSR_LOG1( TASKID_Major_Client_And_Server_Log,
  3200. TASKID_Minor_HrPostCreateResourceAndDependents_PostCreate_Succeeded,
  3201. hr,
  3202. L"[PostCreate] %1!ws!: PostCreate() succeeded.",
  3203. bstrNotification,
  3204. bstrName
  3205. );
  3206. } // else: success
  3207. } // if: inteface
  3208. else
  3209. {
  3210. SSR_LOG1( TASKID_Major_Client_And_Server_Log,
  3211. TASKID_Minor_HrPostCreateResourceAndDependents_PostCreate_NotNeeded,
  3212. hr,
  3213. L"[PostCreate] %1!ws!: No PostCreate() needed. Configuring dependents.",
  3214. bstrNotification,
  3215. bstrName
  3216. );
  3217. } // else: no interface
  3218. } // if: not created
  3219. //
  3220. // Now that we created the resource instance, we need to create its dependents.
  3221. //
  3222. hr = THR( presentry->GetCountOfDependents( &cDependents ) );
  3223. if ( FAILED( hr ) )
  3224. {
  3225. SSR_LOG_ERR(
  3226. TASKID_Major_Client_And_Server_Log
  3227. , TASKID_Minor_HrPostCreateResourceAndDependents_GetCountOfDependents
  3228. , hr
  3229. , L""
  3230. );
  3231. goto Error;
  3232. }
  3233. for( ; cDependents != 0; )
  3234. {
  3235. cDependents --;
  3236. hr = THR( presentry->GetDependent( cDependents, &idxDependent, &dfDependent ) );
  3237. if ( FAILED( hr ) )
  3238. {
  3239. SSR_LOG_ERR(
  3240. TASKID_Major_Client_And_Server_Log
  3241. , TASKID_Minor_HrPostCreateResourceAndDependents_GetDependent
  3242. , hr
  3243. , L""
  3244. );
  3245. continue;
  3246. }
  3247. hr = THR( HrPostCreateResourceAndDependents( idxDependent ) );
  3248. if ( FAILED( hr ) )
  3249. continue;
  3250. } // for: cDependents
  3251. //
  3252. // Update the UI layer.
  3253. //
  3254. hr = THR( SendStatusReport( NULL,
  3255. TASKID_Major_Configure_Resources,
  3256. TASKID_Minor_Starting_Resources,
  3257. 0,
  3258. m_cResources, // KB: once these were multiplied by 4; should they be?
  3259. idxResourceIn,
  3260. S_OK,
  3261. NULL, // don't need to change text
  3262. NULL,
  3263. NULL
  3264. ) );
  3265. if ( hr == E_ABORT )
  3266. goto Cleanup;
  3267. // ignore failure
  3268. hr = S_OK;
  3269. Cleanup:
  3270. if ( pccmrc != NULL )
  3271. {
  3272. pccmrc->Release();
  3273. }
  3274. if ( punkServices != NULL )
  3275. {
  3276. punkServices->Release();
  3277. }
  3278. if ( ppcr != NULL )
  3279. {
  3280. ppcr->Release();
  3281. }
  3282. TraceSysFreeString( bstrNotification );
  3283. TraceSysFreeString( bstrLocalQuorumNotification );
  3284. HRETURN( hr );
  3285. Error:
  3286. THR( SendStatusReport( NULL,
  3287. TASKID_Major_Configure_Resources,
  3288. TASKID_Minor_Starting_Resources,
  3289. 0,
  3290. m_cResources, // KB: once these were multiplied by 4; should they be?
  3291. idxResourceIn,
  3292. hr,
  3293. NULL, // don't need to change text
  3294. NULL,
  3295. NULL
  3296. ) );
  3297. goto Cleanup;
  3298. } // HrPostCreateResourceAndDependents()
  3299. //////////////////////////////////////////////////////////////////////////////
  3300. //++
  3301. //
  3302. // HRESULT
  3303. // CPostCfgManager::HrNotifyMemberSetChangeListeners
  3304. //
  3305. // Description:
  3306. // Notify all components on the local computer registered to get
  3307. // notification of cluster member set change (form, join or evict).
  3308. //
  3309. // Arguments:
  3310. // None.
  3311. //
  3312. // Return Values:
  3313. // S_OK
  3314. // Success.
  3315. //
  3316. // other HRESULTs
  3317. // Something went wrong during the notifications.
  3318. //
  3319. //--
  3320. //////////////////////////////////////////////////////////////////////////////
  3321. HRESULT
  3322. CPostCfgManager::HrNotifyMemberSetChangeListeners( void )
  3323. {
  3324. TraceFunc( "" );
  3325. const UINT uiCHUNK_SIZE = 16;
  3326. HRESULT hr = S_OK;
  3327. ICatInformation * pciCatInfo = NULL;
  3328. IEnumCLSID * plceListenerClsidEnum = NULL;
  3329. // Validate state
  3330. Assert( m_pccci != NULL );
  3331. do
  3332. {
  3333. ULONG cReturned = 0;
  3334. CATID rgCatIdsImplemented[ 1 ];
  3335. rgCatIdsImplemented[ 0 ] = CATID_ClusCfgMemberSetChangeListeners;
  3336. //
  3337. // Enumerate all the enumerators registered in the
  3338. // CATID_ClusCfgMemberSetChangeListeners category
  3339. //
  3340. hr = THR(
  3341. CoCreateInstance(
  3342. CLSID_StdComponentCategoriesMgr
  3343. , NULL
  3344. , CLSCTX_SERVER
  3345. , IID_ICatInformation
  3346. , reinterpret_cast< void ** >( &pciCatInfo )
  3347. )
  3348. );
  3349. if ( FAILED( hr ) )
  3350. {
  3351. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log,
  3352. TASKID_Minor_HrNotifyMemberSetChangeListeners_CoCreate_StdComponentCategoriesMgr,
  3353. hr,
  3354. L"Error occurred trying to get a pointer to the enumerator of the CATID_ClusCfgMemberSetChangeListeners category."
  3355. );
  3356. break;
  3357. } // if: we could not get a pointer to the ICatInformation interface
  3358. // Get a pointer to the enumerator of the CLSIDs that belong to
  3359. // the CATID_ClusCfgMemberSetChangeListeners category.
  3360. hr = THR(
  3361. pciCatInfo->EnumClassesOfCategories(
  3362. 1
  3363. , rgCatIdsImplemented
  3364. , 0
  3365. , NULL
  3366. , &plceListenerClsidEnum
  3367. )
  3368. );
  3369. if ( FAILED( hr ) )
  3370. {
  3371. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log,
  3372. TASKID_Minor_HrNotifyMemberSetChangeListeners_EnumClassesOfCategories,
  3373. hr,
  3374. L"Error occurred trying to get a pointer to the enumerator of the CATID_ClusCfgMemberSetChangeListeners category."
  3375. );
  3376. break;
  3377. } // if: we could not get a pointer to the IEnumCLSID interface
  3378. // Enumerate the CLSIDs of the registered enumerators
  3379. do
  3380. {
  3381. CLSID rgListenerClsidArray[ uiCHUNK_SIZE ];
  3382. ULONG idxCLSID;
  3383. hr = STHR(
  3384. plceListenerClsidEnum->Next(
  3385. uiCHUNK_SIZE
  3386. , rgListenerClsidArray
  3387. , &cReturned
  3388. )
  3389. );
  3390. if ( FAILED( hr ) )
  3391. {
  3392. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log,
  3393. TASKID_Minor_HrNotifyMemberSetChangeListeners_Next,
  3394. hr,
  3395. L"Error occurred trying enumerate member set listener enumerators."
  3396. );
  3397. break;
  3398. } // if: we could not get a pointer to the IEnumCLSID interface
  3399. // hr may be S_FALSE here, so reset it.
  3400. hr = S_OK;
  3401. for ( idxCLSID = 0; idxCLSID < cReturned; ++idxCLSID )
  3402. {
  3403. hr = THR( HrProcessMemberSetChangeListener( rgListenerClsidArray[ idxCLSID ] ) );
  3404. if ( FAILED( hr ) )
  3405. {
  3406. // The processing of one of the listeners failed.
  3407. // Log the error, but continue processing other listeners.
  3408. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log,
  3409. TASKID_Minor_HrNotifyMemberSetChangeListeners_HrProcessMemberSetChangeListener,
  3410. hr,
  3411. L"Error occurred trying to process a member set change listener. Ignoring. Other listeners will be processed."
  3412. );
  3413. hr = S_OK;
  3414. } // if: this listener failed
  3415. } // for: iterate through the returned CLSIDs
  3416. }
  3417. while( cReturned > 0 ); // while: there are still CLSIDs to be enumerated
  3418. if ( FAILED( hr ) )
  3419. {
  3420. break;
  3421. } // if: something went wrong in the loop above
  3422. }
  3423. while( false ); // dummy do-while loop to avoid gotos.
  3424. //
  3425. // Cleanup code
  3426. //
  3427. if ( pciCatInfo != NULL )
  3428. {
  3429. pciCatInfo->Release();
  3430. } // if: we had obtained a pointer to the ICatInformation interface
  3431. if ( plceListenerClsidEnum != NULL )
  3432. {
  3433. plceListenerClsidEnum->Release();
  3434. } // if: we had obtained a pointer to the enumerator of listener CLSIDs
  3435. HRETURN( hr );
  3436. } //*** CPostCfgManager::HrNotifyMemberSetChangeListeners()
  3437. //////////////////////////////////////////////////////////////////////////////
  3438. //++
  3439. //
  3440. // HRESULT
  3441. // CPostCfgManager::HrProcessMemberSetChangeListener
  3442. //
  3443. // Description:
  3444. // This function notifies a listener of cluster member set changes.
  3445. //
  3446. // Arguments:
  3447. // rclsidListenerClsidIn
  3448. // CLSID of the listener component.
  3449. //
  3450. // Return Values:
  3451. // S_OK
  3452. // Success.
  3453. //
  3454. // other HRESULTs
  3455. // Something went wrong during the notification.
  3456. //
  3457. //--
  3458. //////////////////////////////////////////////////////////////////////////////
  3459. HRESULT
  3460. CPostCfgManager::HrProcessMemberSetChangeListener(
  3461. const CLSID & rclsidListenerClsidIn
  3462. )
  3463. {
  3464. TraceFunc( "" );
  3465. HRESULT hr = S_OK;
  3466. IClusCfgMemberSetChangeListener * pccmclListener = NULL;
  3467. TraceMsgGUID( mtfFUNC, "The CLSID of this listener is ", rclsidListenerClsidIn );
  3468. do
  3469. {
  3470. //
  3471. // Create the listener represented by the CLSID passed in
  3472. //
  3473. hr = THR(
  3474. CoCreateInstance(
  3475. rclsidListenerClsidIn
  3476. , NULL
  3477. , CLSCTX_INPROC_SERVER
  3478. , __uuidof( pccmclListener )
  3479. , reinterpret_cast< void ** >( &pccmclListener )
  3480. )
  3481. );
  3482. if ( FAILED( hr ) )
  3483. {
  3484. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log,
  3485. TASKID_Minor_HrProcessMemberSetChangeListener_CoCreate_Listener,
  3486. hr,
  3487. L"Error occurred trying to get a pointer to the the member set change listener."
  3488. );
  3489. break;
  3490. } // if: we could not get a pointer to the IClusCfgMemberSetChangeListener interface
  3491. hr = THR( pccmclListener->Notify( m_pccci ) );
  3492. if ( FAILED( hr ) )
  3493. {
  3494. // The processing of this listeners failed.
  3495. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log,
  3496. TASKID_Minor_HrProcessMemberSetChangeListener_Notify,
  3497. hr,
  3498. L"Error occurred trying to notify a listener."
  3499. );
  3500. break;
  3501. } // if: this listeners failed
  3502. }
  3503. while( false ); // dummy do-while loop to avoid gotos.
  3504. //
  3505. // Cleanup code
  3506. //
  3507. if ( pccmclListener != NULL )
  3508. {
  3509. pccmclListener->Release();
  3510. } // if: we had obtained a pointer to the listener interface
  3511. HRETURN( hr );
  3512. } //*** CPostCfgManager::HrProcessMemberSetChangeListener()
  3513. //////////////////////////////////////////////////////////////////////////////
  3514. //++
  3515. //
  3516. // HRESULT
  3517. // CPostCfgManager::HrConfigureResTypes
  3518. //
  3519. // Description:
  3520. // Enumerate all components on the local computer registered for resource
  3521. // type configuration.
  3522. //
  3523. // Arguments:
  3524. // IUnknown * punkResTypeServicesIn
  3525. // A pointer to the IUnknown interface on a component that provides
  3526. // services that help configure resource types.
  3527. //
  3528. // Return Values:
  3529. // S_OK
  3530. // Success.
  3531. //
  3532. // other HRESULTs
  3533. // Something went wrong during the enumeration.
  3534. //
  3535. //--
  3536. //////////////////////////////////////////////////////////////////////////////
  3537. HRESULT
  3538. CPostCfgManager::HrConfigureResTypes( IUnknown * punkResTypeServicesIn )
  3539. {
  3540. TraceFunc( "" );
  3541. const UINT uiCHUNK_SIZE = 16;
  3542. HRESULT hr = S_OK;
  3543. ICatInformation * pciCatInfo = NULL;
  3544. IEnumCLSID * prceResTypeClsidEnum = NULL;
  3545. // Validate state
  3546. Assert( m_pccci != NULL );
  3547. do
  3548. {
  3549. ULONG cReturned = 0;
  3550. CATID rgCatIdsImplemented[ 1 ];
  3551. rgCatIdsImplemented[ 0 ] = CATID_ClusCfgResourceTypes;
  3552. //
  3553. // Enumerate all the enumerators registered in the
  3554. // CATID_ClusCfgResourceTypes category
  3555. //
  3556. hr = THR(
  3557. CoCreateInstance(
  3558. CLSID_StdComponentCategoriesMgr
  3559. , NULL
  3560. , CLSCTX_SERVER
  3561. , IID_ICatInformation
  3562. , reinterpret_cast< void ** >( &pciCatInfo )
  3563. )
  3564. );
  3565. if ( FAILED( hr ) )
  3566. {
  3567. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log,
  3568. TASKID_Minor_HrConfigureResTypes_CoCreate_CategoriesMgr,
  3569. hr,
  3570. L"Error occurred trying to get a pointer to the enumerator of the CATID_ClusCfgResourceTypes category."
  3571. );
  3572. break;
  3573. } // if: we could not get a pointer to the ICatInformation interface
  3574. // Get a pointer to the enumerator of the CLSIDs that belong to the CATID_ClusCfgResourceTypes category.
  3575. hr = THR(
  3576. pciCatInfo->EnumClassesOfCategories(
  3577. 1
  3578. , rgCatIdsImplemented
  3579. , 0
  3580. , NULL
  3581. , &prceResTypeClsidEnum
  3582. )
  3583. );
  3584. if ( FAILED( hr ) )
  3585. {
  3586. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log,
  3587. TASKID_Minor_HrConfigureResTypes_Enum,
  3588. hr,
  3589. L"Error occurred trying to get a pointer to the enumerator of the CATID_ClusCfgResourceTypes category."
  3590. );
  3591. break;
  3592. } // if: we could not get a pointer to the IEnumCLSID interface
  3593. // Enumerate the CLSIDs of the registered resource types
  3594. do
  3595. {
  3596. CLSID rgResTypeCLSIDArray[ uiCHUNK_SIZE ];
  3597. ULONG idxCLSID;
  3598. cReturned = 0;
  3599. hr = STHR(
  3600. prceResTypeClsidEnum->Next(
  3601. uiCHUNK_SIZE
  3602. , rgResTypeCLSIDArray
  3603. , &cReturned
  3604. )
  3605. );
  3606. if ( FAILED( hr ) )
  3607. {
  3608. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log,
  3609. TASKID_Minor_HrConfigureResTypes_Next,
  3610. hr,
  3611. L"Error occurred trying enumerate resource type configuration components."
  3612. );
  3613. break;
  3614. } // if: we could not get the next set of CLSIDs
  3615. // hr may be S_FALSE here, so reset it.
  3616. hr = S_OK;
  3617. for ( idxCLSID = 0; idxCLSID < cReturned; ++idxCLSID )
  3618. {
  3619. hr = THR( HrProcessResType( rgResTypeCLSIDArray[ idxCLSID ], punkResTypeServicesIn ) );
  3620. if ( FAILED( hr ) )
  3621. {
  3622. BSTR bstrCLSID = NULL;
  3623. BSTR bstrNotification = NULL;
  3624. THR( StringFromCLSID( rgResTypeCLSIDArray[ idxCLSID ], &bstrCLSID ) );
  3625. // The processing of one of the resource types failed.
  3626. // Log the error, but continue processing other resource types.
  3627. SSR_LOG1( TASKID_Major_Client_And_Server_Log,
  3628. TASKID_Minor_HrConfigureResTypes_HrProcessResType,
  3629. hr,
  3630. L"[ResType] Error occurred trying to process a resource type. Ignoring. Other resource types will be processed. The CLSID of the failed resource type is %1!ws!.",
  3631. bstrNotification,
  3632. bstrCLSID
  3633. );
  3634. TraceSysFreeString( bstrNotification );
  3635. SysFreeString( bstrCLSID );
  3636. hr = S_OK;
  3637. } // if: this enumerator failed
  3638. } // for: iterate through the returned CLSIDs
  3639. }
  3640. while( cReturned > 0 ); // while: there are still CLSIDs to be enumerated
  3641. if ( FAILED( hr ) )
  3642. {
  3643. break;
  3644. } // if: something went wrong in the loop above
  3645. }
  3646. while( false ); // dummy do-while loop to avoid gotos.
  3647. //
  3648. // Cleanup code
  3649. //
  3650. if ( pciCatInfo != NULL )
  3651. {
  3652. pciCatInfo->Release();
  3653. } // if: we had obtained a pointer to the ICatInformation interface
  3654. if ( prceResTypeClsidEnum != NULL )
  3655. {
  3656. prceResTypeClsidEnum->Release();
  3657. } // if: we had obtained a pointer to the enumerator of resource type CLSIDs
  3658. HRETURN( hr );
  3659. } //*** CPostCfgManager::HrConfigureResTypes()
  3660. //////////////////////////////////////////////////////////////////////////////
  3661. //++
  3662. //
  3663. // HRESULT
  3664. // CPostCfgManager::HrProcessResType
  3665. //
  3666. // Description:
  3667. // This function instantiates a resource type configuration component
  3668. // and calls the appropriate methods.
  3669. //
  3670. // Arguments:
  3671. // rclsidResTypeCLSIDIn
  3672. // CLSID of the resource type configuration component
  3673. //
  3674. // punkResTypeServicesIn
  3675. // Pointer to the IUnknown interface on the resource type services
  3676. // component. This interface provides methods that help configure
  3677. // resource types.
  3678. //
  3679. // Return Values:
  3680. // S_OK
  3681. // Success.
  3682. //
  3683. // other HRESULTs
  3684. // Something went wrong during the processing of the resource type.
  3685. //
  3686. //--
  3687. //////////////////////////////////////////////////////////////////////////////
  3688. HRESULT
  3689. CPostCfgManager::HrProcessResType(
  3690. const CLSID & rclsidResTypeCLSIDIn
  3691. , IUnknown * punkResTypeServicesIn
  3692. )
  3693. {
  3694. TraceFunc( "" );
  3695. HRESULT hr = S_OK;
  3696. IClusCfgResourceTypeInfo * pcrtiResTypeInfo = NULL;
  3697. BSTR bstrResTypeName = NULL;
  3698. GUID guidResTypeGUID;
  3699. BSTR bstrNotification = NULL;
  3700. TraceMsgGUID( mtfFUNC, "The CLSID of this resource type is ", rclsidResTypeCLSIDIn );
  3701. do
  3702. {
  3703. //
  3704. // Create the component represented by the CLSID passed in
  3705. //
  3706. hr = THR(
  3707. CoCreateInstance(
  3708. rclsidResTypeCLSIDIn
  3709. , NULL
  3710. , CLSCTX_INPROC_SERVER
  3711. , __uuidof( pcrtiResTypeInfo )
  3712. , reinterpret_cast< void ** >( &pcrtiResTypeInfo )
  3713. )
  3714. );
  3715. if ( FAILED( hr ) )
  3716. {
  3717. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log,
  3718. TASKID_Minor_HrProcessResType_CoCreate_ResTypeClsid,
  3719. hr,
  3720. L"[ResType] Error occurred trying to create the resource type configuration component."
  3721. );
  3722. break;
  3723. } // if: we could not create the resource type configuration component
  3724. //
  3725. // Initialize the newly created component
  3726. //
  3727. {
  3728. IClusCfgInitialize * pcci = NULL;
  3729. HRESULT hrTemp;
  3730. // Check if this component supports the callback interface.
  3731. hrTemp = THR( pcrtiResTypeInfo->QueryInterface< IClusCfgInitialize >( &pcci ) );
  3732. if ( FAILED( hrTemp ) )
  3733. {
  3734. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log,
  3735. TASKID_Minor_HrProcessResType_QI_pcci,
  3736. hrTemp,
  3737. L"Error occurred trying to get a pointer to the IClusCfgInitialize interface. This resource type does not support initialization."
  3738. );
  3739. } // if: the callback interface is not supported
  3740. else
  3741. {
  3742. // Initialize this component.
  3743. hr = THR(
  3744. pcci->Initialize(
  3745. TraceInterface( __THISCLASS__, IClusCfgCallback, this, 0 )
  3746. , m_lcid
  3747. )
  3748. );
  3749. // This interface is no longer needed.
  3750. pcci->Release();
  3751. // Did initialization succeed?
  3752. if ( FAILED( hr ) )
  3753. {
  3754. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log,
  3755. TASKID_Minor_HrProcessResType_Initialize,
  3756. hr,
  3757. L"Error occurred trying initialize a resource type configuration component."
  3758. );
  3759. break;
  3760. } // if: the initialization failed
  3761. } // else: the callback interface is supported
  3762. }
  3763. // Get the name of the current resource type.
  3764. hr = THR( pcrtiResTypeInfo->GetTypeName( &bstrResTypeName ) );
  3765. if ( FAILED( hr ) )
  3766. {
  3767. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log,
  3768. TASKID_Minor_HrProcessResType_GetTypeName,
  3769. hr,
  3770. L"Error occurred trying to get the name of a resource type."
  3771. );
  3772. break;
  3773. } // if: we could not get the resource type name
  3774. SSR_LOG1( TASKID_Major_Client_And_Server_Log,
  3775. TASKID_Minor_HrProcessResType_AboutToConfigureType,
  3776. hr,
  3777. L"[ResType] %1!ws!: About to configure resource type...",
  3778. bstrNotification,
  3779. bstrResTypeName
  3780. );
  3781. // Configure this resource type.
  3782. hr = THR( pcrtiResTypeInfo->CommitChanges( m_pccci, punkResTypeServicesIn ) );
  3783. if ( FAILED( hr ) )
  3784. {
  3785. SSR_LOG1( TASKID_Major_Client_And_Server_Log,
  3786. TASKID_Minor_HrProcessResType_CommitChanges,
  3787. hr,
  3788. L"[ResType] %1!ws!: Error occurred trying to configure the resource type.",
  3789. bstrNotification,
  3790. bstrResTypeName
  3791. );
  3792. break;
  3793. } // if: this resource type configuration failed
  3794. // Get and store the resource type GUID
  3795. hr = STHR( pcrtiResTypeInfo->GetTypeGUID( &guidResTypeGUID ) );
  3796. if ( FAILED( hr ) )
  3797. {
  3798. SSR_LOG1( TASKID_Major_Client_And_Server_Log,
  3799. TASKID_Minor_HrProcessResType_GetTypeGUID,
  3800. hr,
  3801. L"[ResType] %1!ws!: Error occurred trying to get the resource type GUID.",
  3802. bstrNotification,
  3803. bstrResTypeName
  3804. );
  3805. break;
  3806. } // if: this resource type configuration failed
  3807. if ( hr == S_OK )
  3808. {
  3809. TraceMsgGUID( mtfFUNC, "The GUID of this resource type is", guidResTypeGUID );
  3810. hr = THR( HrMapResTypeGUIDToName( guidResTypeGUID, bstrResTypeName ) );
  3811. if ( FAILED( hr ) )
  3812. {
  3813. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log,
  3814. TASKID_Minor_HrProcessResType_HrMapResTypeGUIDToName,
  3815. hr,
  3816. L"Error occurred trying to create a mapping between a GUID and a name"
  3817. );
  3818. // Something went wrong with our code - we cannot continue.
  3819. break;
  3820. } // if: we could not add the mapping
  3821. } // if: this resource type has a GUID
  3822. else
  3823. {
  3824. // Reset hr
  3825. hr = S_OK;
  3826. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log,
  3827. TASKID_Minor_HrProcessResType_NoGuid,
  3828. hr,
  3829. L"This resource type does not have a GUID associated with it."
  3830. );
  3831. } // else: this resource type does not have a GUID
  3832. }
  3833. while( false ); // dummy do-while loop to avoid gotos.
  3834. //
  3835. // Cleanup code
  3836. //
  3837. if ( pcrtiResTypeInfo != NULL )
  3838. {
  3839. pcrtiResTypeInfo->Release();
  3840. } // if: we had obtained a pointer to the resource type info interface
  3841. if ( bstrResTypeName != NULL )
  3842. {
  3843. SysFreeString( bstrResTypeName );
  3844. } // if: a bstr was allocated for this resource type
  3845. TraceSysFreeString( bstrNotification );
  3846. HRETURN( hr );
  3847. } //*** CPostCfgManager::HrProcessResType()
  3848. //////////////////////////////////////////////////////////////////////////////
  3849. //++
  3850. //
  3851. // HRESULT
  3852. // CPostCfgManager::HrMapResTypeGUIDToName
  3853. //
  3854. // Description:
  3855. // Create a mapping between a resource type GUID and a resource type name.
  3856. //
  3857. // Arguments:
  3858. // rcguidTypeGuidIn
  3859. // Resource type GUID which is to be mapped to a resource type name.
  3860. //
  3861. // pcszTypeNameIn
  3862. // The resource type name to map the above GUID to.
  3863. //
  3864. // Return Values:
  3865. // S_OK
  3866. // Success.
  3867. //
  3868. // other HRESULTs
  3869. // If something went wrong
  3870. //
  3871. //--
  3872. //////////////////////////////////////////////////////////////////////////////
  3873. HRESULT
  3874. CPostCfgManager::HrMapResTypeGUIDToName(
  3875. const GUID & rcguidTypeGuidIn
  3876. , const WCHAR * pcszTypeNameIn
  3877. )
  3878. {
  3879. TraceFunc( "" );
  3880. HRESULT hr = S_OK;
  3881. do
  3882. {
  3883. ULONG cchTypeNameSize;
  3884. WCHAR * pszTypeName;
  3885. //
  3886. // Validate the parameters
  3887. //
  3888. // Validate the parameters
  3889. if ( ( pcszTypeNameIn == NULL ) || ( *pcszTypeNameIn == L'\0' ) )
  3890. {
  3891. hr = THR( E_INVALIDARG );
  3892. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log,
  3893. TASKID_HrMapResTypeGUIDToName_InvalidArg,
  3894. hr,
  3895. L"An empty resource type name cannot be added to the map."
  3896. );
  3897. break;
  3898. } // if: the resource type name is empty
  3899. // Check if the existing map buffer is big enough to hold another entry.
  3900. if ( m_idxNextMapEntry >= m_cMapSize )
  3901. {
  3902. // Double the size of the map buffer
  3903. ULONG cNewMapSize = m_cMapSize * 2;
  3904. ULONG idxMapEntry;
  3905. SResTypeGUIDAndName * pgnNewMap = new SResTypeGUIDAndName[ cNewMapSize ];
  3906. if ( pgnNewMap == NULL )
  3907. {
  3908. hr = THR( E_OUTOFMEMORY );
  3909. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log,
  3910. TASKID_HrMapResTypeGUIDToName_OutOfMemory_NewMap,
  3911. hr,
  3912. L"Memory allocation failed trying to add a new resource type GUID to name map entry."
  3913. );
  3914. break;
  3915. } // if: memory allocation failed
  3916. // Copy the contents of the old buffer to the new one.
  3917. for ( idxMapEntry = 0; idxMapEntry < m_idxNextMapEntry; ++idxMapEntry )
  3918. {
  3919. pgnNewMap[ idxMapEntry ] = m_pgnResTypeGUIDNameMap[ idxMapEntry ];
  3920. } // for: iterate through the existing map
  3921. // Update the member variables
  3922. delete [] m_pgnResTypeGUIDNameMap;
  3923. m_pgnResTypeGUIDNameMap = pgnNewMap;
  3924. m_cMapSize = cNewMapSize;
  3925. } // if: the map buffer is not big enough for another entry
  3926. //
  3927. // Add the new entry to the map
  3928. //
  3929. cchTypeNameSize = wcslen( pcszTypeNameIn ) + 1;
  3930. pszTypeName = new WCHAR[ cchTypeNameSize ];
  3931. if ( pszTypeName == NULL )
  3932. {
  3933. hr = THR( E_OUTOFMEMORY );
  3934. SSR_LOG_ERR( TASKID_Major_Client_And_Server_Log,
  3935. TASKID_HrMapResTypeGUIDToName_OutOfMemory_TypeName,
  3936. hr,
  3937. L"Memory allocation failed trying to add a new resource type GUID to name map entry."
  3938. );
  3939. break;
  3940. } // if: memory allocation failed
  3941. wcsncpy( pszTypeName, pcszTypeNameIn, cchTypeNameSize );
  3942. m_pgnResTypeGUIDNameMap[ m_idxNextMapEntry ].m_guidTypeGUID = rcguidTypeGuidIn;
  3943. m_pgnResTypeGUIDNameMap[ m_idxNextMapEntry ].m_pszTypeName = pszTypeName;
  3944. ++m_idxNextMapEntry;
  3945. }
  3946. while( false ); // dummy do-while loop to avoid gotos
  3947. HRETURN( hr );
  3948. } //*** CPostCfgManager::HrMapResTypeGUIDToName()
  3949. //////////////////////////////////////////////////////////////////////////////
  3950. //++
  3951. //
  3952. // LPCWSTR
  3953. // CPostCfgManager::PcszLookupTypeNameByGUID
  3954. //
  3955. // Description:
  3956. // Given a resource type GUID this function finds the resource type name
  3957. // if any.
  3958. //
  3959. // Arguments:
  3960. // rcguidTypeGuidIn
  3961. // Resource type GUID which is to be mapped to a resource type name.
  3962. //
  3963. // Return Values:
  3964. // Pointer to the name of the resource type
  3965. // If the type GUID maps to name
  3966. //
  3967. // NULL
  3968. // If there is no type name associated with the input GUID
  3969. //--
  3970. //////////////////////////////////////////////////////////////////////////////
  3971. const WCHAR *
  3972. CPostCfgManager::PcszLookupTypeNameByGUID(
  3973. const GUID & rcguidTypeGuidIn
  3974. )
  3975. {
  3976. TraceFunc( "" );
  3977. ULONG idxCurrentMapEntry;
  3978. const WCHAR * pcszTypeName = NULL;
  3979. TraceMsgGUID( mtfFUNC, "Trying to look up the the type name of resource type ", rcguidTypeGuidIn );
  3980. for ( idxCurrentMapEntry = 0; idxCurrentMapEntry < m_idxNextMapEntry; ++idxCurrentMapEntry )
  3981. {
  3982. if ( IsEqualGUID( rcguidTypeGuidIn, m_pgnResTypeGUIDNameMap[ idxCurrentMapEntry ].m_guidTypeGUID ) != FALSE )
  3983. {
  3984. // A mapping has been found.
  3985. pcszTypeName = m_pgnResTypeGUIDNameMap[ idxCurrentMapEntry ].m_pszTypeName;
  3986. TraceMsg( mtfFUNC, "The name of the type is '%s'", pcszTypeName );
  3987. break;
  3988. } // if: this GUID has been found in the map
  3989. } // for: iterate through the existing entries in the map
  3990. if ( pcszTypeName == NULL )
  3991. {
  3992. TraceMsg( mtfFUNC, "The input GUID does not map to any resource type name." );
  3993. } // if: this GUID does not exist in the map
  3994. RETURN( pcszTypeName );
  3995. } //*** CPostCfgManager::PcszLookupTypeNameByGUID()
  3996. //////////////////////////////////////////////////////////////////////////////
  3997. //
  3998. // HRESULT
  3999. // CPostCfgManager::HrPreInitializeExistingResources( void )
  4000. //
  4001. //////////////////////////////////////////////////////////////////////////////
  4002. HRESULT
  4003. CPostCfgManager::HrPreInitializeExistingResources( void )
  4004. {
  4005. TraceFunc( "" );
  4006. HRESULT hr;
  4007. BSTR bstrName; // don't free
  4008. HRESOURCE hResource;
  4009. CResourceEntry * presentry;
  4010. DWORD dwMaxLogSize;
  4011. DWORD dw;
  4012. BSTR bstrNotification = NULL;
  4013. BSTR bstrClusterNameResourceName = NULL;
  4014. BSTR bstrClusterIPAddressResourceName = NULL;
  4015. BSTR bstrClusterQuorumResourceName = NULL;
  4016. HRESOURCE hClusterNameResource = NULL;
  4017. HRESOURCE hClusterIPAddressResource = NULL;
  4018. HRESOURCE hClusterQuorumResource = NULL;
  4019. Assert( m_rgpResources == NULL );
  4020. Assert( m_cAllocedResources == 0 );
  4021. Assert( m_cResources == 0 );
  4022. hr = THR( HrLoadStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_LOCATE_EXISTING_QUORUM_DEVICE, &bstrNotification ) );
  4023. if ( FAILED( hr ) )
  4024. {
  4025. SSR_LOG_ERR(
  4026. TASKID_Major_Client_And_Server_Log
  4027. , TASKID_Minor_HrPreInitializeExistingResources_LoadString_LocateExistingQuorum
  4028. , hr
  4029. , L""
  4030. );
  4031. goto Cleanup;
  4032. }
  4033. m_rgpResources = (CResourceEntry **) TraceAlloc( 0, sizeof(CResourceEntry *) * RESOURCE_INCREMENT );
  4034. if ( m_rgpResources == NULL )
  4035. {
  4036. goto OutOfMemory;
  4037. } // if:
  4038. for ( ; m_cAllocedResources < RESOURCE_INCREMENT; m_cAllocedResources ++ )
  4039. {
  4040. m_rgpResources[ m_cAllocedResources] = new CResourceEntry();
  4041. if ( m_rgpResources[ m_cAllocedResources ] == NULL )
  4042. {
  4043. goto OutOfMemory;
  4044. } // if:
  4045. } // for:
  4046. Assert( m_cAllocedResources == RESOURCE_INCREMENT );
  4047. //
  4048. // Create default resources such as Cluster IP, Cluster Name resource, and Quorum Device
  4049. //
  4050. Assert( m_cResources == 0 );
  4051. //
  4052. // Get the core resources and their names.
  4053. //
  4054. hr = THR( HrGetCoreClusterResourceNames(
  4055. &bstrClusterNameResourceName
  4056. , &hClusterNameResource
  4057. , &bstrClusterIPAddressResourceName
  4058. , &hClusterIPAddressResource
  4059. , &bstrClusterQuorumResourceName
  4060. , &hClusterQuorumResource
  4061. ) );
  4062. if ( FAILED( hr ) )
  4063. {
  4064. goto Cleanup;
  4065. } // if:
  4066. //
  4067. // Add Cluster IP Address resource
  4068. //
  4069. m_idxIPAddress = m_cResources;
  4070. presentry = m_rgpResources[ m_cResources ];
  4071. // This give ownership of bstrClusterIPAddressResourceName away
  4072. hr = THR( presentry->SetName( bstrClusterIPAddressResourceName ) );
  4073. if ( FAILED( hr ) )
  4074. {
  4075. SSR_LOG_ERR(
  4076. TASKID_Major_Client_And_Server_Log
  4077. , TASKID_Minor_HrPreInitializeExistingResources_IP_SetName
  4078. , hr
  4079. , L""
  4080. );
  4081. goto Cleanup;
  4082. }
  4083. bstrClusterIPAddressResourceName = NULL;
  4084. hr = THR( presentry->SetType( &RESTYPE_ClusterIPAddress ) );
  4085. if ( FAILED( hr ) )
  4086. {
  4087. SSR_LOG_ERR(
  4088. TASKID_Major_Client_And_Server_Log
  4089. , TASKID_Minor_HrPreInitializeExistingResources_IP_SetType
  4090. , hr
  4091. , L""
  4092. );
  4093. goto Cleanup;
  4094. }
  4095. hr = THR( presentry->SetClassType( &RESCLASSTYPE_IPAddress ) );
  4096. if ( FAILED( hr ) )
  4097. {
  4098. SSR_LOG_ERR(
  4099. TASKID_Major_Client_And_Server_Log
  4100. , TASKID_Minor_HrPreInitializeExistingResources_IP_SetClassType
  4101. , hr
  4102. , L""
  4103. );
  4104. goto Cleanup;
  4105. }
  4106. hr = THR( presentry->SetFlags( dfSHARED ) );
  4107. if ( FAILED( hr ) )
  4108. {
  4109. SSR_LOG_ERR(
  4110. TASKID_Major_Client_And_Server_Log
  4111. , TASKID_Minor_HrPreInitializeExistingResources_IP_SetFlags
  4112. , hr
  4113. , L""
  4114. );
  4115. goto Cleanup;
  4116. }
  4117. hr = THR( presentry->SetHResource( hClusterIPAddressResource ) );
  4118. if ( FAILED( hr ) )
  4119. {
  4120. SSR_LOG_ERR(
  4121. TASKID_Major_Client_And_Server_Log
  4122. , TASKID_Minor_HrPreInitializeExistingResources_IP_SetHResource
  4123. , hr
  4124. , L""
  4125. );
  4126. goto Cleanup;
  4127. }
  4128. hClusterIPAddressResource = NULL;
  4129. m_cResources ++;
  4130. //
  4131. // Add Cluster Name resource
  4132. //
  4133. m_idxClusterName = m_cResources;
  4134. presentry = m_rgpResources[ m_cResources ];
  4135. // This give ownership of bstrClusterNameResourceName away
  4136. hr = THR( presentry->SetName( bstrClusterNameResourceName ) );
  4137. if ( FAILED( hr ) )
  4138. {
  4139. SSR_LOG_ERR(
  4140. TASKID_Major_Client_And_Server_Log
  4141. , TASKID_Minor_HrPreInitializeExistingResources_Name_SetName
  4142. , hr
  4143. , L""
  4144. );
  4145. goto Cleanup;
  4146. }
  4147. bstrClusterNameResourceName = NULL;
  4148. hr = THR( presentry->SetType( &RESTYPE_ClusterNetName ) );
  4149. if ( FAILED( hr ) )
  4150. {
  4151. SSR_LOG_ERR(
  4152. TASKID_Major_Client_And_Server_Log
  4153. , TASKID_Minor_HrPreInitializeExistingResources_Name_SetType
  4154. , hr
  4155. , L""
  4156. );
  4157. goto Cleanup;
  4158. }
  4159. hr = THR( presentry->SetClassType( &RESCLASSTYPE_NetworkName ) );
  4160. if ( FAILED( hr ) )
  4161. {
  4162. SSR_LOG_ERR(
  4163. TASKID_Major_Client_And_Server_Log
  4164. , TASKID_Minor_HrPreInitializeExistingResources_Name_SetClassType
  4165. , hr
  4166. , L""
  4167. );
  4168. goto Cleanup;
  4169. }
  4170. hr = THR( presentry->SetFlags( dfSHARED ) );
  4171. if ( FAILED( hr ) )
  4172. {
  4173. SSR_LOG_ERR(
  4174. TASKID_Major_Client_And_Server_Log
  4175. , TASKID_Minor_HrPreInitializeExistingResources_Name_SetFlags
  4176. , hr
  4177. , L""
  4178. );
  4179. goto Cleanup;
  4180. }
  4181. // Add the dependency on the IP address.
  4182. hr = THR( presentry->AddTypeDependency( &RESTYPE_ClusterIPAddress, dfSHARED ) );
  4183. if ( FAILED( hr ) )
  4184. {
  4185. SSR_LOG_ERR(
  4186. TASKID_Major_Client_And_Server_Log
  4187. , TASKID_Minor_HrPreInitializeExistingResources_Name_AddTypeDependency
  4188. , hr
  4189. , L""
  4190. );
  4191. goto Cleanup;
  4192. }
  4193. hr = THR( presentry->SetHResource( hClusterNameResource ) );
  4194. if ( FAILED( hr ) )
  4195. {
  4196. SSR_LOG_ERR(
  4197. TASKID_Major_Client_And_Server_Log
  4198. , TASKID_Minor_HrPreInitializeExistingResources_Name_SetHResource
  4199. , hr
  4200. , L""
  4201. );
  4202. goto Cleanup;
  4203. }
  4204. hClusterNameResource = NULL;
  4205. m_cResources ++;
  4206. //
  4207. // Add Quorum resource
  4208. //
  4209. //
  4210. // KB: gpease 19-JUN-2000
  4211. // Anything before the quorum device will be considered to be
  4212. // in the Cluster Group.
  4213. //
  4214. m_idxQuorumResource = m_cResources;
  4215. presentry = m_rgpResources[ m_cResources ];
  4216. // This give ownership of bstrClusterQuorumResourceName away
  4217. hr = THR( presentry->SetName( bstrClusterQuorumResourceName ) );
  4218. if ( FAILED( hr ) )
  4219. {
  4220. SSR_LOG_ERR(
  4221. TASKID_Major_Client_And_Server_Log
  4222. , TASKID_Minor_HrPreInitializeExistingResources_Quorum_SetName
  4223. , hr
  4224. , L""
  4225. );
  4226. goto Cleanup;
  4227. }
  4228. bstrClusterQuorumResourceName = NULL;
  4229. hr = THR( presentry->SetType( &RESTYPE_ClusterQuorumDisk ) );
  4230. if ( FAILED( hr ) )
  4231. {
  4232. SSR_LOG_ERR(
  4233. TASKID_Major_Client_And_Server_Log
  4234. , TASKID_Minor_HrPreInitializeExistingResources_Quorum_SetType
  4235. , hr
  4236. , L""
  4237. );
  4238. goto Cleanup;
  4239. }
  4240. hr = THR( presentry->SetClassType( &RESCLASSTYPE_StorageDevice ) );
  4241. if ( FAILED( hr ) )
  4242. {
  4243. SSR_LOG_ERR(
  4244. TASKID_Major_Client_And_Server_Log
  4245. , TASKID_Minor_HrPreInitializeExistingResources_Quorum_SetClassType
  4246. , hr
  4247. , L""
  4248. );
  4249. goto Cleanup;
  4250. }
  4251. hr = THR( presentry->SetFlags( dfSHARED ) );
  4252. if ( FAILED( hr ) )
  4253. {
  4254. SSR_LOG_ERR(
  4255. TASKID_Major_Client_And_Server_Log
  4256. , TASKID_Minor_HrPreInitializeExistingResources_Quorum_SetFlags
  4257. , hr
  4258. , L""
  4259. );
  4260. goto Cleanup;
  4261. }
  4262. hr = THR( presentry->SetHResource( hClusterQuorumResource ) );
  4263. if ( FAILED( hr ) )
  4264. {
  4265. SSR_LOG_ERR(
  4266. TASKID_Major_Client_And_Server_Log
  4267. , TASKID_Minor_HrPreInitializeExistingResources_Quorum_SetHResource
  4268. , hr
  4269. , L""
  4270. );
  4271. goto Cleanup;
  4272. }
  4273. hClusterQuorumResource = NULL;
  4274. m_cResources ++;
  4275. //
  4276. // Make sure that the default resource allocation can hold all the
  4277. // default resources.
  4278. //
  4279. AssertMsg( m_cResources <= m_cAllocedResources, "Default resource allocation needs to be bigger!" );
  4280. goto Cleanup;
  4281. OutOfMemory:
  4282. hr = E_OUTOFMEMORY;
  4283. SSR_LOG_ERR(
  4284. TASKID_Major_Client_And_Server_Log
  4285. , TASKID_Minor_HrPreInitializeExistingResources_OutOfMemory
  4286. , hr
  4287. , L"Out of memory"
  4288. );
  4289. Cleanup:
  4290. //
  4291. // Send a status that we found the quorum device.
  4292. //
  4293. hr = THR( SendStatusReport( NULL,
  4294. TASKID_Major_Configure_Resources,
  4295. TASKID_Minor_Locate_Existing_Quorum_Device,
  4296. 0,
  4297. 10,
  4298. 10,
  4299. hr,
  4300. bstrNotification,
  4301. NULL,
  4302. NULL
  4303. ) );
  4304. if ( hr == E_ABORT )
  4305. goto Cleanup;
  4306. // ignore failure
  4307. TraceSysFreeString( bstrNotification );
  4308. TraceSysFreeString( bstrClusterNameResourceName );
  4309. TraceSysFreeString( bstrClusterIPAddressResourceName );
  4310. TraceSysFreeString( bstrClusterQuorumResourceName );
  4311. if ( hClusterNameResource != NULL )
  4312. {
  4313. CloseClusterResource( hClusterNameResource );
  4314. } // if:
  4315. if ( hClusterIPAddressResource != NULL )
  4316. {
  4317. CloseClusterResource( hClusterIPAddressResource );
  4318. } // if:
  4319. if ( hClusterQuorumResource != NULL )
  4320. {
  4321. CloseClusterResource( hClusterQuorumResource );
  4322. } // if:
  4323. HRETURN( hr );
  4324. } // HrPreInitializeExistingResources( void )
  4325. //////////////////////////////////////////////////////////////////////////////
  4326. //
  4327. // HRESULT
  4328. // CPostCfgManager::HrAddSpecialResource(
  4329. // BSTR bstrNameIn,
  4330. // const CLSID * pclsidTypeIn,
  4331. // const CLSID * pclsidClassTypeIn
  4332. // )
  4333. //
  4334. //////////////////////////////////////////////////////////////////////////////
  4335. HRESULT
  4336. CPostCfgManager::HrAddSpecialResource(
  4337. BSTR bstrNameIn,
  4338. const CLSID * pclsidTypeIn,
  4339. const CLSID * pclsidClassTypeIn
  4340. )
  4341. {
  4342. TraceFunc( "" );
  4343. HRESULT hr;
  4344. CResourceEntry * presentry;
  4345. //
  4346. // Grow the resource list if nessecary.
  4347. //
  4348. if ( m_cResources == m_cAllocedResources )
  4349. {
  4350. ULONG idxNewCount = m_cAllocedResources + RESOURCE_INCREMENT;
  4351. CResourceEntry ** pnewList;
  4352. pnewList = (CResourceEntry **) TraceAlloc( 0, sizeof( CResourceEntry * ) * idxNewCount );
  4353. if ( pnewList == NULL )
  4354. goto OutOfMemory;
  4355. CopyMemory( pnewList, m_rgpResources, sizeof(CResourceEntry *) * m_cAllocedResources );
  4356. TraceFree( m_rgpResources );
  4357. m_rgpResources = pnewList;
  4358. for ( ; m_cAllocedResources < idxNewCount ; m_cAllocedResources ++ )
  4359. {
  4360. m_rgpResources[ m_cAllocedResources ] = new CResourceEntry();
  4361. if ( m_rgpResources[ m_cAllocedResources ] == NULL )
  4362. goto OutOfMemory;
  4363. }
  4364. }
  4365. presentry = m_rgpResources[ m_cResources ];
  4366. //
  4367. // Setup the new entry.
  4368. //
  4369. hr = THR( presentry->SetName( bstrNameIn ) );
  4370. if ( FAILED( hr ) )
  4371. {
  4372. SSR_LOG_ERR(
  4373. TASKID_Major_Client_And_Server_Log
  4374. , TASKID_Minor_HrAddSpecialResource_SetName
  4375. , hr
  4376. , L""
  4377. );
  4378. goto Cleanup;
  4379. }
  4380. hr = THR( presentry->SetType( pclsidTypeIn ) );
  4381. if ( FAILED( hr ) )
  4382. {
  4383. SSR_LOG_ERR(
  4384. TASKID_Major_Client_And_Server_Log
  4385. , TASKID_Minor_HrAddSpecialResource_SetType
  4386. , hr
  4387. , L""
  4388. );
  4389. goto Cleanup;
  4390. }
  4391. hr = THR( presentry->SetClassType( pclsidClassTypeIn ) );
  4392. if ( FAILED( hr ) )
  4393. {
  4394. SSR_LOG_ERR(
  4395. TASKID_Major_Client_And_Server_Log
  4396. , TASKID_Minor_HrAddSpecialResource_SetClassType
  4397. , hr
  4398. , L""
  4399. );
  4400. goto Cleanup;
  4401. }
  4402. m_cResources ++;
  4403. Cleanup:
  4404. HRETURN( hr );
  4405. OutOfMemory:
  4406. {
  4407. hr = E_OUTOFMEMORY;
  4408. SSR_LOG_ERR(
  4409. TASKID_Major_Client_And_Server_Log
  4410. , TASKID_Minor_HrAddSpecialResource_OutOfMemory
  4411. , hr
  4412. , L"Out of memory"
  4413. );
  4414. }
  4415. goto Cleanup;
  4416. } // HrAddSpecialResource()
  4417. //////////////////////////////////////////////////////////////////////////////
  4418. //
  4419. // HRESULT
  4420. // CPostCfgManager::HrCreateResourceInstance(
  4421. // ULONG idxResourceIn,
  4422. // HGROUP hGroupIn,
  4423. // LPCWSTR pszResTypeIn,
  4424. // HRESOURCE * phResourceOut
  4425. // )
  4426. //
  4427. //////////////////////////////////////////////////////////////////////////////
  4428. HRESULT
  4429. CPostCfgManager::HrCreateResourceInstance(
  4430. ULONG idxResourceIn,
  4431. HGROUP hGroupIn,
  4432. LPCWSTR pszResTypeIn,
  4433. HRESOURCE * phResourceOut
  4434. )
  4435. {
  4436. TraceFunc3( "idxResourceIn = %u, hGroupIn = %p, pszResTypeIn = '%ws'",
  4437. idxResourceIn, hGroupIn, pszResTypeIn );
  4438. HRESULT hr;
  4439. DWORD dw;
  4440. BSTR bstrName; // don't free
  4441. CResourceEntry * presentry;
  4442. BSTR bstrNotification = NULL;
  4443. Assert( phResourceOut != NULL );
  4444. Assert( idxResourceIn < m_cResources );
  4445. Assert( hGroupIn != NULL );
  4446. presentry = m_rgpResources[ idxResourceIn ];
  4447. hr = THR( presentry->GetName( &bstrName ) );
  4448. if ( FAILED( hr ) )
  4449. {
  4450. SSR_LOG_ERR(
  4451. TASKID_Major_Client_And_Server_Log
  4452. , TASKID_Minor_HrCreateResourceInstance_GetName
  4453. , hr
  4454. , L""
  4455. );
  4456. goto Cleanup;
  4457. }
  4458. //
  4459. // Tell the UI what we are doing.
  4460. //
  4461. hr = THR( SendStatusReport( NULL,
  4462. TASKID_Major_Configure_Resources,
  4463. TASKID_Minor_Creating_Resource,
  4464. 0,
  4465. m_cResources, // KB: once these were multiplied by 4. Should they be?
  4466. idxResourceIn,
  4467. S_OK,
  4468. NULL,
  4469. NULL,
  4470. NULL
  4471. ) );
  4472. if ( hr == E_ABORT )
  4473. goto Cleanup;
  4474. // ignore failure
  4475. //
  4476. // TODO: gpease 24-AUG-2000
  4477. // What to do if we have a failure?? For now I think we should keep going!
  4478. //
  4479. //
  4480. // See if the resource already exists. We need to do this because the user
  4481. // might have clicked "Retry" in the UI. We don't want to create another
  4482. // instance of existing resources.
  4483. //
  4484. *phResourceOut = OpenClusterResource( m_hCluster, bstrName );
  4485. if ( *phResourceOut == NULL )
  4486. {
  4487. //
  4488. // Create a new resource instance.
  4489. //
  4490. *phResourceOut = CreateClusterResource( hGroupIn, bstrName, pszResTypeIn, 0 );
  4491. if ( *phResourceOut == NULL )
  4492. {
  4493. hr = HRESULT_FROM_WIN32( TW32( GetLastError() ) );
  4494. SSR_LOG1( TASKID_Major_Client_And_Server_Log,
  4495. TASKID_Minor_HrCreateResourceInstance_CreateClusterResource,
  4496. hr,
  4497. L"[Create] %1!ws!: CreateClusterResource failed. Its dependents may not be created. Skipping.",
  4498. bstrNotification,
  4499. bstrName
  4500. );
  4501. goto Cleanup;
  4502. } // if: failure
  4503. SSR_LOG1( TASKID_Major_Client_And_Server_Log,
  4504. TASKID_Minor_HrCreateResourceInstance_CreateClusterResource_Successful,
  4505. hr,
  4506. L"[Create] %1!ws!: Resource created successfully.",
  4507. bstrNotification,
  4508. bstrName
  4509. );
  4510. }
  4511. else
  4512. {
  4513. SSR_LOG1( TASKID_Major_Client_And_Server_Log,
  4514. TASKID_Minor_HrCreateResourceInstance_FoundExistingResource,
  4515. hr,
  4516. L"[Create] %1!ws!: Found existing resource.",
  4517. bstrNotification,
  4518. bstrName
  4519. );
  4520. //
  4521. // Make sure the resource is in the group we think it is.
  4522. //
  4523. // don't wrap - this can fail with ERROR_ALREADY_EXISTS.
  4524. dw = ChangeClusterResourceGroup( *phResourceOut, hGroupIn );
  4525. if ( dw == ERROR_ALREADY_EXISTS )
  4526. {
  4527. // no-op. It's the way we want it.
  4528. }
  4529. else if ( dw != ERROR_SUCCESS )
  4530. {
  4531. hr = HRESULT_FROM_WIN32( dw );
  4532. SSR_LOG1( TASKID_Major_Client_And_Server_Log,
  4533. TASKID_Minor_HrCreateResourceInstance_ChangeClusterResourceGroup,
  4534. hr,
  4535. L"[Create] %1!ws!: Can move existing resource to proper group. Configuration may not work.",
  4536. bstrNotification,
  4537. bstrName
  4538. );
  4539. }
  4540. }
  4541. //
  4542. // Store off the resource handle.
  4543. //
  4544. hr = THR( presentry->SetHResource( *phResourceOut ) );
  4545. if ( FAILED( hr ) )
  4546. {
  4547. SSR_LOG_ERR(
  4548. TASKID_Major_Client_And_Server_Log
  4549. , TASKID_Minor_HrCreateResourceInstance_SetHResource
  4550. , hr
  4551. , L""
  4552. );
  4553. goto Cleanup;
  4554. }
  4555. //
  4556. // Configure resource.
  4557. //
  4558. hr = THR( presentry->Configure() );
  4559. if ( FAILED( hr ) )
  4560. {
  4561. SSR_LOG_ERR(
  4562. TASKID_Major_Client_And_Server_Log
  4563. , TASKID_Minor_HrCreateResourceInstance_Configure
  4564. , hr
  4565. , L""
  4566. );
  4567. // ignore the error and continue.
  4568. }
  4569. //
  4570. // Make a message using the name.
  4571. //
  4572. hr = THR( HrFormatMessageIntoBSTR( g_hInstance,
  4573. IDS_TASKID_MINOR_CREATING_RESOURCE,
  4574. &bstrNotification,
  4575. bstrName
  4576. ) );
  4577. if ( FAILED( hr ) )
  4578. {
  4579. SSR_LOG_ERR(
  4580. TASKID_Major_Client_And_Server_Log
  4581. , TASKID_Minor_HrCreateResourceInstance_LoadString_CreatingResource
  4582. , hr
  4583. , L""
  4584. );
  4585. goto Cleanup;
  4586. }
  4587. //
  4588. // Tell the UI what we are doing.
  4589. //
  4590. hr = THR( SendStatusReport( NULL,
  4591. TASKID_Major_Client_And_Server_Log, // informative only
  4592. TASKID_Minor_Creating_Resource,
  4593. 0,
  4594. 2,
  4595. 2,
  4596. hr, // log the error on the client side
  4597. bstrNotification,
  4598. NULL,
  4599. NULL
  4600. ) );
  4601. if ( hr == E_ABORT )
  4602. goto Cleanup;
  4603. // ignore failure
  4604. //
  4605. // TODO: gpease 24-AUG-2000
  4606. // What to do if we have a failure?? For now I think we should keep going!
  4607. //
  4608. hr = S_OK;
  4609. Cleanup:
  4610. TraceSysFreeString( bstrNotification );
  4611. HRETURN( hr );
  4612. } // HrCreateResourceInstance()
  4613. //////////////////////////////////////////////////////////////////////////////
  4614. //
  4615. // DWORD
  4616. // CPostCfgManager::S_DwDeleteLocalQuorumResource(
  4617. // )
  4618. //
  4619. //////////////////////////////////////////////////////////////////////////////
  4620. DWORD
  4621. CPostCfgManager::S_DwDeleteLocalQuorumResource(
  4622. HCLUSTER hClusterIn
  4623. , HRESOURCE hSelfIn
  4624. , HRESOURCE hLQuorumIn
  4625. , PVOID pvParamIn
  4626. )
  4627. {
  4628. TraceFunc( "" );
  4629. DWORD sc = ERROR_SUCCESS;
  4630. signed long slOfflineTimeOut = 60; // seconds
  4631. CLUSTER_RESOURCE_STATE crs;
  4632. HCHANGE hc = reinterpret_cast< HCHANGE >( INVALID_HANDLE_VALUE );
  4633. CPostCfgManager * pcpcmThis = reinterpret_cast< CPostCfgManager * >( pvParamIn );
  4634. DWORD dwStatusCurrent;
  4635. //
  4636. // Check if the this pointer is valid.
  4637. //
  4638. if ( pvParamIn == NULL )
  4639. {
  4640. // If the pointer is invalid, set it to a valid address and continue.
  4641. TW32( ERROR_INVALID_PARAMETER );
  4642. TraceFlow( "Error: The pointer to the CPostCfgManager object cannot be NULL." );
  4643. LogMsg( "PostCfg: Error: An invalid parameter was received while trying to delete the local quorum resource." );
  4644. goto Cleanup;
  4645. }
  4646. // Get the state of the resource.
  4647. crs = GetClusterResourceState( hLQuorumIn, NULL, NULL, NULL, NULL );
  4648. // Check if it is offline - if it is, then we can proceed to deleting it.
  4649. if ( crs == ClusterResourceOffline )
  4650. {
  4651. TraceFlow( "The localquorum resource is already offline." );
  4652. goto Cleanup;
  4653. }
  4654. TraceFlow( "Trying to take the localquorum resource offline." );
  4655. // If we are here, the resource is not yet offline. Instruct it to go offline.
  4656. sc = OfflineClusterResource( hLQuorumIn );
  4657. if ( ( sc != ERROR_SUCCESS ) && ( sc != ERROR_IO_PENDING ) )
  4658. {
  4659. TW32( sc );
  4660. TraceFlow1( "Error %#08x occurred trying to take the local quorum resource offline.", sc );
  4661. LogMsg( "PostCfg: Error %#08x occurred trying to take the local quorum resource offline.", sc );
  4662. goto Cleanup;
  4663. } // if: an error occurred trying to take the resource offline
  4664. if ( sc == ERROR_IO_PENDING )
  4665. {
  4666. TraceFlow1( "Waiting %d seconds for the localquorum resource to go offline.", slOfflineTimeOut );
  4667. // Create a notification port for resource state changes
  4668. hc = CreateClusterNotifyPort(
  4669. reinterpret_cast< HCHANGE >( INVALID_HANDLE_VALUE )
  4670. , hClusterIn
  4671. , CLUSTER_CHANGE_RESOURCE_STATE
  4672. , NULL
  4673. );
  4674. if ( hc == NULL )
  4675. {
  4676. sc = TW32( GetLastError() );
  4677. TraceFlow1( "Error %#08x occurred trying to create a cluster notification port.", sc );
  4678. LogMsg( "PostCfg: Error %#08x occurred trying to create a cluster notification port.", sc );
  4679. goto Cleanup;
  4680. } // if: we could not create a notification port
  4681. sc = TW32( RegisterClusterNotify( hc, CLUSTER_CHANGE_RESOURCE_STATE, hLQuorumIn, NULL ) );
  4682. if ( sc != ERROR_SUCCESS )
  4683. {
  4684. TraceFlow1( "Error %#08x occurred trying to register for cluster notifications.", sc );
  4685. LogMsg( "PostCfg: Error %#08x occurred trying to register for cluster notifications.", sc );
  4686. goto Cleanup;
  4687. } // if:
  4688. // Change the status report range.
  4689. dwStatusCurrent = pcpcmThis->m_dwLocalQuorumStatusMax;
  4690. pcpcmThis->m_dwLocalQuorumStatusMax += slOfflineTimeOut;
  4691. // Wait for slOfflineTimeOut seconds for the resource to go offline.
  4692. for ( ; slOfflineTimeOut > 0; --slOfflineTimeOut )
  4693. {
  4694. DWORD dwFilterType;
  4695. crs = GetClusterResourceState( hLQuorumIn, NULL, NULL, NULL, NULL );
  4696. if ( crs == ClusterResourceOffline )
  4697. {
  4698. TraceFlow1( "The local quorum resource has gone offline with %d seconds to spare.", slOfflineTimeOut );
  4699. break;
  4700. } // if: the resource is now offline
  4701. sc = GetClusterNotify( hc, NULL, &dwFilterType, NULL, NULL, 1000 ); // wait for one second
  4702. if ( ( sc != ERROR_SUCCESS ) && ( sc != WAIT_TIMEOUT ) )
  4703. {
  4704. TW32( sc );
  4705. TraceFlow1( "Error %#08x occurred trying wait for a resource state change notification.", sc );
  4706. LogMsg( "PostCfg: Error %#08x occurred trying wait for a resource state change notification.", sc );
  4707. goto Cleanup;
  4708. } // if: something went wrong
  4709. // Reset sc, since it could be WAIT_TIMEOUT here
  4710. sc = ERROR_SUCCESS;
  4711. Assert( dwFilterType == CLUSTER_CHANGE_RESOURCE_STATE );
  4712. // Send a status report that we are deleting the quorum device.
  4713. ++dwStatusCurrent;
  4714. THR(
  4715. pcpcmThis->SendStatusReport(
  4716. NULL
  4717. , TASKID_Major_Configure_Resources
  4718. , TASKID_Minor_Delete_LocalQuorum
  4719. , 0
  4720. , pcpcmThis->m_dwLocalQuorumStatusMax
  4721. , dwStatusCurrent
  4722. , HRESULT_FROM_WIN32( sc )
  4723. , NULL // don't update text
  4724. , NULL
  4725. , NULL
  4726. )
  4727. );
  4728. } // for: loop while the timeout has not expired
  4729. } // if:
  4730. else
  4731. {
  4732. crs = ClusterResourceOffline; // the resource went offline immediately.
  4733. } // else:
  4734. //
  4735. // If we are here, then one of two things could have happened:
  4736. // 1. The resource has gone offline
  4737. // 2. The timeout has expired
  4738. // Check to see which of the above is true.
  4739. //
  4740. if ( crs != ClusterResourceOffline )
  4741. {
  4742. // We cannot be here if the timeout has not expired.
  4743. Assert( slOfflineTimeOut <= 0 );
  4744. TraceFlow( "The local quorum resource could not be taken offline." );
  4745. LogMsg( "PostCfg: Error: The local quorum resource could not be taken offline." );
  4746. sc = TW32( WAIT_TIMEOUT );
  4747. goto Cleanup;
  4748. } // if: the timeout has expired
  4749. // If we are here, the resource is offline.
  4750. TraceFlow( "The local quorum resource is offline." );
  4751. if ( pcpcmThis != NULL )
  4752. {
  4753. // Send a status report that we are deleting the quorum device.
  4754. ++pcpcmThis->m_dwLocalQuorumStatusMax;
  4755. THR(
  4756. pcpcmThis->SendStatusReport(
  4757. NULL
  4758. , TASKID_Major_Configure_Resources
  4759. , TASKID_Minor_Delete_LocalQuorum
  4760. , 0
  4761. , pcpcmThis->m_dwLocalQuorumStatusMax
  4762. , pcpcmThis->m_dwLocalQuorumStatusMax
  4763. , HRESULT_FROM_WIN32( sc )
  4764. , NULL // don't update text
  4765. , NULL
  4766. , NULL
  4767. )
  4768. );
  4769. } // if: the this pointer is valid
  4770. // If we are here, the resource is offline - now delete it.
  4771. sc = TW32( DeleteClusterResource( hLQuorumIn ) );
  4772. if ( sc != ERROR_SUCCESS )
  4773. {
  4774. TraceFlow1( "Error %#08x occurred trying to delete the localquorum resource.", sc );
  4775. LogMsg( "PostCfg: Error %#08x occurred trying to delete the localquorum resource.", sc );
  4776. } // if: we could not delete the resource
  4777. else
  4778. {
  4779. TraceFlow( "The localquorum resource has been deleted." );
  4780. LogMsg( "The localquorum resource has been deleted." );
  4781. } // else: the resource has been deleted
  4782. // Send a status report that we are deleting the quorum device.
  4783. ++pcpcmThis->m_dwLocalQuorumStatusMax;
  4784. THR(
  4785. pcpcmThis->SendStatusReport(
  4786. NULL
  4787. , TASKID_Major_Configure_Resources
  4788. , TASKID_Minor_Delete_LocalQuorum
  4789. , 0
  4790. , pcpcmThis->m_dwLocalQuorumStatusMax
  4791. , pcpcmThis->m_dwLocalQuorumStatusMax
  4792. , HRESULT_FROM_WIN32( sc )
  4793. , NULL // don't update text
  4794. , NULL
  4795. , NULL
  4796. )
  4797. );
  4798. Cleanup:
  4799. //
  4800. // Cleanup
  4801. //
  4802. if ( hc != INVALID_HANDLE_VALUE )
  4803. {
  4804. CloseClusterNotifyPort( hc );
  4805. } // if: we had created a cluster notification port
  4806. RETURN( sc );
  4807. } // S_DwDeleteLocalQuorumResource()
  4808. //////////////////////////////////////////////////////////////////////////////
  4809. //
  4810. // HRESULT
  4811. // CPostCfgManager::HrGetCoreClusterResourceNames(
  4812. // BSTR * pbstrClusterNameResourceOut
  4813. // , BSTR * pbstrClusterIPAddressNameOut
  4814. // , BSTR * pbstrClusterQuorumResourceNameOut
  4815. // )
  4816. //
  4817. //////////////////////////////////////////////////////////////////////////////
  4818. HRESULT
  4819. CPostCfgManager::HrGetCoreClusterResourceNames(
  4820. BSTR * pbstrClusterNameResourceNameOut
  4821. , HRESOURCE * phClusterNameResourceOut
  4822. , BSTR * pbstrClusterIPAddressNameOut
  4823. , HRESOURCE * phClusterIPAddressResourceOut
  4824. , BSTR * pbstrClusterQuorumResourceNameOut
  4825. , HRESOURCE * phClusterQuorumResourceOut
  4826. )
  4827. {
  4828. TraceFunc( "" );
  4829. Assert( pbstrClusterNameResourceNameOut != NULL );
  4830. Assert( phClusterNameResourceOut != NULL );
  4831. Assert( pbstrClusterIPAddressNameOut != NULL );
  4832. Assert( phClusterIPAddressResourceOut != NULL );
  4833. Assert( pbstrClusterQuorumResourceNameOut != NULL );
  4834. Assert( phClusterQuorumResourceOut != NULL );
  4835. HRESULT hr = S_OK;
  4836. WCHAR * pszName = NULL;
  4837. DWORD cchName = 33;
  4838. HRESOURCE hClusterIPAddressResource = NULL;
  4839. HRESOURCE hClusterNameResource = NULL;
  4840. HRESOURCE hClusterQuorumResource = NULL;
  4841. DWORD sc;
  4842. BSTR * pbstr = NULL;
  4843. HRESOURCE hResource = NULL;
  4844. int idx;
  4845. sc = TW32( ResUtilGetCoreClusterResources( m_hCluster, &hClusterNameResource, &hClusterIPAddressResource, &hClusterQuorumResource ) );
  4846. if ( sc != ERROR_SUCCESS )
  4847. {
  4848. hr = HRESULT_FROM_WIN32( sc );
  4849. goto Cleanup;
  4850. } // if:
  4851. pszName = new WCHAR[ cchName ];
  4852. if ( pszName == NULL )
  4853. {
  4854. goto OutOfMemory;
  4855. } // if:
  4856. for ( idx = 0; idx < 3; )
  4857. {
  4858. switch ( idx )
  4859. {
  4860. case 0:
  4861. {
  4862. hResource = hClusterNameResource;
  4863. pbstr = pbstrClusterNameResourceNameOut;
  4864. break;
  4865. } // case:
  4866. case 1:
  4867. {
  4868. hResource = hClusterIPAddressResource;
  4869. pbstr = pbstrClusterIPAddressNameOut;
  4870. break;
  4871. } // case:
  4872. case 2:
  4873. {
  4874. hResource = hClusterQuorumResource;
  4875. pbstr = pbstrClusterQuorumResourceNameOut;
  4876. break;
  4877. } // case:
  4878. } // switch:
  4879. sc = ResUtilGetResourceName( hResource, pszName, &cchName );
  4880. if ( sc == ERROR_MORE_DATA )
  4881. {
  4882. delete [] pszName;
  4883. pszName = NULL;
  4884. cchName++;
  4885. pszName = new WCHAR[ cchName ];
  4886. if ( pszName == NULL )
  4887. {
  4888. goto OutOfMemory;
  4889. } // if:
  4890. continue;
  4891. } // if:
  4892. if ( sc == ERROR_SUCCESS )
  4893. {
  4894. *pbstr = TraceSysAllocString( pszName );
  4895. if ( *pbstr == NULL )
  4896. {
  4897. goto OutOfMemory;
  4898. } // if:
  4899. pbstr = NULL;
  4900. idx++;
  4901. continue;
  4902. } // if:
  4903. if ( sc != ERROR_SUCCESS )
  4904. {
  4905. TW32( sc );
  4906. hr = HRESULT_FROM_WIN32( sc );
  4907. SSR_LOG_ERR(
  4908. TASKID_Major_Client_And_Server_Log
  4909. , TASKID_Minor_HrGetCoreClusterResourceNames_GetResourceName
  4910. , hr
  4911. , L""
  4912. );
  4913. goto Cleanup;
  4914. } // if:
  4915. } // for:
  4916. //
  4917. // Give ownership to the caller
  4918. //
  4919. *phClusterNameResourceOut = hClusterNameResource;
  4920. hClusterNameResource = NULL;
  4921. *phClusterIPAddressResourceOut = hClusterIPAddressResource;
  4922. hClusterIPAddressResource = NULL;
  4923. *phClusterQuorumResourceOut = hClusterQuorumResource;
  4924. hClusterQuorumResource = NULL;
  4925. goto Cleanup;
  4926. OutOfMemory:
  4927. hr = THR( E_OUTOFMEMORY );
  4928. Cleanup:
  4929. if ( hClusterNameResource != NULL )
  4930. {
  4931. CloseClusterResource( hClusterNameResource );
  4932. } // if:
  4933. if ( hClusterIPAddressResource != NULL )
  4934. {
  4935. CloseClusterResource( hClusterIPAddressResource );
  4936. } // if:
  4937. if ( hClusterQuorumResource != NULL )
  4938. {
  4939. CloseClusterResource( hClusterQuorumResource );
  4940. } // if:
  4941. if ( pbstr != NULL )
  4942. {
  4943. TraceSysFreeString( *pbstr );
  4944. } // if:
  4945. delete [] pszName;
  4946. HRETURN( hr );
  4947. } //***CPostCfgManager::HrGetCoreClusterResourceNames
  4948. /*
  4949. //////////////////////////////////////////////////////////////////////////////
  4950. //
  4951. // HRESULT
  4952. // CPostCfgManager::HrIsLocalQuorum( BSTR bstrNameIn )
  4953. //
  4954. //////////////////////////////////////////////////////////////////////////////
  4955. HRESULT
  4956. CPostCfgManager::HrIsLocalQuorum( BSTR bstrNameIn )
  4957. {
  4958. TraceFunc( "" );
  4959. Assert( bstrNameIn != NULL );
  4960. HRESULT hr = S_FALSE;
  4961. BSTR bstrLocalQuorum = NULL;
  4962. hr = THR( HrLoadStringIntoBSTR( g_hInstance, IDS_LOCAL_QUORUM_DISPLAY_NAME, &bstrLocalQuorum ) );
  4963. if ( FAILED( hr ) )
  4964. {
  4965. goto Cleanup;
  4966. } // if:
  4967. if ( _wcsicmp( bstrNameIn, bstrLocalQuorum ) == 0 )
  4968. {
  4969. hr = S_OK;
  4970. } // if:
  4971. else
  4972. {
  4973. hr = S_FALSE;
  4974. } // else:
  4975. Cleanup:
  4976. TraceSysFreeString( bstrLocalQuorum );
  4977. HRETURN( hr );
  4978. } //***CPostCfgManager::HrIsLocalQuorum
  4979. */
  4980. #if defined(DEBUG)
  4981. //////////////////////////////////////////////////////////////////////////////
  4982. //
  4983. // void
  4984. // CPostCfgManager::DebugDumpDepencyTree( void )
  4985. //
  4986. //////////////////////////////////////////////////////////////////////////////
  4987. void
  4988. CPostCfgManager::DebugDumpDepencyTree( void )
  4989. {
  4990. TraceFunc( "" );
  4991. ULONG idxResource;
  4992. ULONG cDependents;
  4993. ULONG idxDependent;
  4994. BSTR bstrName; // don't free
  4995. CResourceEntry * presentry;
  4996. EDependencyFlags dfDependent;
  4997. for ( idxResource = 0; idxResource < m_cResources ; idxResource ++ )
  4998. {
  4999. presentry = m_rgpResources[ idxResource ];
  5000. THR( presentry->GetName( &bstrName ) );
  5001. DebugMsgNoNewline( "%ws(#%u) -> ", bstrName, idxResource );
  5002. THR( presentry->GetCountOfDependents( &cDependents ) );
  5003. for ( ; cDependents != 0 ; )
  5004. {
  5005. cDependents --;
  5006. THR( presentry->GetDependent( cDependents, &idxDependent, &dfDependent ) );
  5007. THR( m_rgpResources[ idxDependent ]->GetName( &bstrName ) );
  5008. DebugMsgNoNewline( "%ws(#%u) ", bstrName, idxDependent );
  5009. } // for: cDependents
  5010. DebugMsg( L"" );
  5011. } // for: idxResource
  5012. TraceFuncExit();
  5013. } // DebugDumpDepencyTree()
  5014. #endif // #if defined(DEBUG)