Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1463 lines
45 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2000-2002 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // TaskAnalyzeCluster.cpp
  7. //
  8. // Description:
  9. // CTaskAnalyzeCluster implementation.
  10. //
  11. // Maintained By:
  12. // Galen Barbee (GalenB) 03-FEB-2000
  13. //
  14. //////////////////////////////////////////////////////////////////////////////
  15. //////////////////////////////////////////////////////////////////////////////
  16. // Include Files
  17. //////////////////////////////////////////////////////////////////////////////
  18. #include "Pch.h"
  19. #include "TaskAnalyzeCluster.h"
  20. //////////////////////////////////////////////////////////////////////////////
  21. // Constant Definitions
  22. //////////////////////////////////////////////////////////////////////////////
  23. DEFINE_THISCLASS( "CTaskAnalyzeCluster" )
  24. //*************************************************************************//
  25. /////////////////////////////////////////////////////////////////////////////
  26. // CTaskAnalyzeCluster class
  27. /////////////////////////////////////////////////////////////////////////////
  28. //////////////////////////////////////////////////////////////////////////////
  29. //++
  30. //
  31. // CTaskAnalyzeCluster::S_HrCreateInstance
  32. //
  33. // Description:
  34. // Create a CTaskAnalyzeCluster instance.
  35. //
  36. // Arguments:
  37. // ppunkOut
  38. //
  39. // Return Values:
  40. // S_OK
  41. // Success.
  42. //
  43. // Other HRESULT as failure.
  44. //
  45. //--
  46. //////////////////////////////////////////////////////////////////////////////
  47. HRESULT
  48. CTaskAnalyzeCluster::S_HrCreateInstance(
  49. IUnknown ** ppunkOut
  50. )
  51. {
  52. TraceFunc( "" );
  53. Assert( ppunkOut != NULL );
  54. HRESULT hr = S_OK;
  55. CTaskAnalyzeCluster * ptac = NULL;
  56. if ( ppunkOut == NULL )
  57. {
  58. hr = THR( E_POINTER );
  59. goto Cleanup;
  60. } // if:
  61. ptac = new CTaskAnalyzeCluster;
  62. if ( ptac == NULL )
  63. {
  64. hr = THR( E_OUTOFMEMORY );
  65. goto Cleanup;
  66. } // if:
  67. hr = THR( ptac->HrInit() );
  68. if ( FAILED( hr ) )
  69. {
  70. goto Cleanup;
  71. } // if:
  72. hr = THR( ptac->TypeSafeQI( IUnknown, ppunkOut ) );
  73. if ( FAILED( hr ) )
  74. {
  75. goto Cleanup;
  76. } // if:
  77. Cleanup:
  78. if ( ptac != NULL )
  79. {
  80. ptac->Release();
  81. } // if:
  82. HRETURN( hr );
  83. } //*** CTaskAnalyzeCluster::S_HrCreateInstance
  84. //////////////////////////////////////////////////////////////////////////////
  85. //++
  86. //
  87. // CTaskAnalyzeCluster::CTaskAnalyzeCluster
  88. //
  89. // Description:
  90. // Constructor
  91. //
  92. // Arguments:
  93. // None.
  94. //
  95. // Return Values:
  96. // None.
  97. //
  98. //--
  99. //////////////////////////////////////////////////////////////////////////////
  100. CTaskAnalyzeCluster::CTaskAnalyzeCluster( void )
  101. {
  102. TraceFunc( "" );
  103. TraceFuncExit();
  104. } //*** CTaskAnalyzeCluster::CTaskAnalyzeCluster
  105. //////////////////////////////////////////////////////////////////////////////
  106. //++
  107. //
  108. // CTaskAnalyzeCluster::~CTaskAnalyzeCluster
  109. //
  110. // Description:
  111. // Destructor
  112. //
  113. // Arguments:
  114. // None.
  115. //
  116. // Return Values:
  117. // None.
  118. //
  119. //--
  120. //////////////////////////////////////////////////////////////////////////////
  121. CTaskAnalyzeCluster::~CTaskAnalyzeCluster( void )
  122. {
  123. TraceFunc( "" );
  124. TraceFuncExit();
  125. } //*** CTaskAnalyzeCluster::~CTaskAnalyzeCluster
  126. //*************************************************************************//
  127. /////////////////////////////////////////////////////////////////////////////
  128. // CTaskAnalyzeCluster - IUknkown interface.
  129. /////////////////////////////////////////////////////////////////////////////
  130. //////////////////////////////////////////////////////////////////////////////
  131. //++
  132. //
  133. // CTaskAnalyzeCluster::QueryInterface
  134. //
  135. // Description:
  136. // Query this object for the passed in interface.
  137. //
  138. // Arguments:
  139. // riidIn
  140. // Id of interface requested.
  141. //
  142. // ppvOut
  143. // Pointer to the requested interface.
  144. //
  145. // Return Value:
  146. // S_OK
  147. // If the interface is available on this object.
  148. //
  149. // E_NOINTERFACE
  150. // If the interface is not available.
  151. //
  152. // E_POINTER
  153. // ppvOut was NULL.
  154. //
  155. //--
  156. //////////////////////////////////////////////////////////////////////////////
  157. STDMETHODIMP
  158. CTaskAnalyzeCluster::QueryInterface(
  159. REFIID riidIn
  160. , LPVOID * ppvOut
  161. )
  162. {
  163. TraceQIFunc( riidIn, ppvOut );
  164. HRESULT hr = S_OK;
  165. //
  166. // Validate arguments.
  167. //
  168. Assert( ppvOut != NULL );
  169. if ( ppvOut == NULL )
  170. {
  171. hr = THR( E_POINTER );
  172. goto Cleanup;
  173. } // if:
  174. //
  175. // Handle known interfaces.
  176. //
  177. if ( IsEqualIID( riidIn, IID_IUnknown ) )
  178. {
  179. *ppvOut = static_cast< ITaskAnalyzeCluster * >( this );
  180. } // if: IUnknown
  181. else if ( IsEqualIID( riidIn, IID_ITaskAnalyzeCluster ) )
  182. {
  183. *ppvOut = TraceInterface( __THISCLASS__, ITaskAnalyzeCluster, this, 0 );
  184. } // else if: ITaskAnalyzeCluster
  185. else if ( IsEqualIID( riidIn, IID_IDoTask ) )
  186. {
  187. *ppvOut = TraceInterface( __THISCLASS__, IDoTask, this, 0 );
  188. } // else if: IDoTask
  189. else if ( IsEqualIID( riidIn, IID_IClusCfgCallback ) )
  190. {
  191. *ppvOut = TraceInterface( __THISCLASS__, IClusCfgCallback, this, 0 );
  192. } // else if: IClusCfgCallback
  193. else if ( IsEqualIID( riidIn, IID_INotifyUI ) )
  194. {
  195. *ppvOut = TraceInterface( __THISCLASS__, INotifyUI, this, 0 );
  196. } // else if: INotifyUI
  197. else
  198. {
  199. *ppvOut = NULL;
  200. hr = E_NOINTERFACE;
  201. } // else:
  202. //
  203. // Add a reference to the interface if successful.
  204. //
  205. if ( SUCCEEDED( hr ) )
  206. {
  207. ((IUnknown *) *ppvOut)->AddRef();
  208. } // if: success
  209. Cleanup:
  210. QIRETURN_IGNORESTDMARSHALLING( hr, riidIn );
  211. } //*** CTaskAnalyzeCluster::QueryInterface
  212. //////////////////////////////////////////////////////////////////////////////
  213. //++
  214. //
  215. // CTaskAnalyzeCluster::AddRef
  216. //
  217. // Description:
  218. // Increment the reference count of this object by one.
  219. //
  220. // Arguments:
  221. // None.
  222. //
  223. // Return Value:
  224. // The new reference count.
  225. //
  226. //--
  227. //////////////////////////////////////////////////////////////////////////////
  228. STDMETHODIMP_( ULONG )
  229. CTaskAnalyzeCluster::AddRef( void )
  230. {
  231. TraceFunc( "[IUnknown]" );
  232. ULONG c = UlAddRef();
  233. CRETURN( c );
  234. } //*** CTaskAnalyzeCluster::AddRef
  235. //////////////////////////////////////////////////////////////////////////////
  236. //++
  237. //
  238. // CTaskAnalyzeCluster::Release
  239. //
  240. // Description:
  241. // Decrement the reference count of this object by one.
  242. //
  243. // Arguments:
  244. // None.
  245. //
  246. // Return Value:
  247. // The new reference count.
  248. //
  249. //--
  250. //////////////////////////////////////////////////////////////////////////////
  251. STDMETHODIMP_( ULONG )
  252. CTaskAnalyzeCluster::Release( void )
  253. {
  254. TraceFunc( "[IUnknown]" );
  255. ULONG c = UlRelease();
  256. CRETURN( c );
  257. } //*** CTaskAnalyzeCluster::Release
  258. //*************************************************************************//
  259. /////////////////////////////////////////////////////////////////////////////
  260. // CTaskAnalyzeCluster - IDoTask/ITaskAnalyzeCluster interface.
  261. /////////////////////////////////////////////////////////////////////////////
  262. //////////////////////////////////////////////////////////////////////////////
  263. //++
  264. //
  265. // CTaskAnalyzeCluster::BeginTask
  266. //
  267. // Description:
  268. // Task entry point.
  269. //
  270. // Arguments:
  271. // None.
  272. //
  273. // Return Value:
  274. // S_OK
  275. // Success
  276. //
  277. // HRESULT failure.
  278. //
  279. //--
  280. //////////////////////////////////////////////////////////////////////////////
  281. STDMETHODIMP
  282. CTaskAnalyzeCluster::BeginTask( void )
  283. {
  284. TraceFunc( "[IDoTask]" );
  285. HRESULT hr = THR( HrBeginTask() );
  286. HRETURN( hr );
  287. } //*** CTaskAnalyzeCluster::BeginTask
  288. //////////////////////////////////////////////////////////////////////////////
  289. //++
  290. //
  291. // CTaskAnalyzeCluster::StopTask
  292. //
  293. // Description:
  294. // Stop task entry point.
  295. //
  296. // Arguments:
  297. // None.
  298. //
  299. // Return Value:
  300. // S_OK
  301. // Success
  302. //
  303. // HRESULT failure.
  304. //
  305. //--
  306. //////////////////////////////////////////////////////////////////////////////
  307. STDMETHODIMP
  308. CTaskAnalyzeCluster::StopTask( void )
  309. {
  310. TraceFunc( "[IDoTask]" );
  311. HRESULT hr = THR( HrStopTask() );
  312. HRETURN( hr );
  313. } //*** CTaskAnalyzeCluster::StopTask
  314. //////////////////////////////////////////////////////////////////////////////
  315. //++
  316. //
  317. // CTaskAnalyzeCluster::SetJoiningMode
  318. //
  319. // Description:
  320. // Tell this task whether we are joining nodes to the cluster?
  321. //
  322. // Arguments:
  323. // None.
  324. //
  325. // Return Value:
  326. // S_OK
  327. // Success
  328. //
  329. // HRESULT failure.
  330. //
  331. //--
  332. //////////////////////////////////////////////////////////////////////////////
  333. STDMETHODIMP
  334. CTaskAnalyzeCluster::SetJoiningMode( void )
  335. {
  336. TraceFunc( "[ITaskAnalyzeCluster]" );
  337. HRESULT hr = THR( HrSetJoiningMode() );
  338. HRETURN( hr );
  339. } //*** CTaskAnalyzeCluster::SetJoiningMode
  340. //////////////////////////////////////////////////////////////////////////////
  341. //++
  342. //
  343. // CTaskAnalyzeCluster::SetCookie
  344. //
  345. // Description:
  346. // Receive the completion cookier from the task creator.
  347. //
  348. // Arguments:
  349. // cookieIn
  350. // The completion cookie to send back to the creator when this
  351. // task is complete.
  352. //
  353. // Return Value:
  354. // S_OK
  355. // Success
  356. //
  357. // HRESULT failure.
  358. //
  359. //--
  360. //////////////////////////////////////////////////////////////////////////////
  361. STDMETHODIMP
  362. CTaskAnalyzeCluster::SetCookie(
  363. OBJECTCOOKIE cookieIn
  364. )
  365. {
  366. TraceFunc( "[ITaskAnalyzeCluster]" );
  367. HRESULT hr = THR( HrSetCookie( cookieIn ) );
  368. HRETURN( hr );
  369. } //*** CTaskAnalyzeCluster::SetCookie
  370. //////////////////////////////////////////////////////////////////////////////
  371. //++
  372. //
  373. // CTaskAnalyzeCluster::SetClusterCookie
  374. //
  375. // Description:
  376. // Receive the object manager cookie of the cluster that we are going
  377. // to analyze.
  378. //
  379. // Arguments:
  380. // cookieClusterIn
  381. // The cookie for the cluster to work on.
  382. //
  383. // Return Value:
  384. // S_OK
  385. // Success
  386. //
  387. // HRESULT failure.
  388. //
  389. //--
  390. //////////////////////////////////////////////////////////////////////////////
  391. STDMETHODIMP
  392. CTaskAnalyzeCluster::SetClusterCookie(
  393. OBJECTCOOKIE cookieClusterIn
  394. )
  395. {
  396. TraceFunc( "[ITaskAnalyzeCluster]" );
  397. HRESULT hr = THR( HrSetClusterCookie( cookieClusterIn ) );
  398. HRETURN( hr );
  399. } //*** CTaskAnalyzeCluster::SetClusterCookie
  400. //////////////////////////////////////////////////////////////////////////////
  401. //++
  402. //
  403. // CTaskAnalyzeCluster::HrCompareDriveLetterMappings
  404. //
  405. // Description:
  406. // Compare the drive letter mappings on each node to make sure there
  407. // are no conflicts. Specifically, verify that the system disk on each
  408. // node does not conflict with storage devices that could be failed over
  409. // to that node.
  410. //
  411. // Arguments:
  412. // None.
  413. //
  414. // Return Values:
  415. // S_OK - Operation completed successfully.
  416. // Other HRESULTs.
  417. //
  418. //--
  419. //////////////////////////////////////////////////////////////////////////////
  420. HRESULT
  421. CTaskAnalyzeCluster::HrCompareDriveLetterMappings( void )
  422. {
  423. TraceFunc( "" );
  424. HRESULT hr = S_OK;
  425. HRESULT hrDriveConflictError = S_OK;
  426. HRESULT hrDriveConflictWarning = S_OK;
  427. OBJECTCOOKIE cookieDummy;
  428. OBJECTCOOKIE cookieClusterNode;
  429. DWORD idxCurrentNode;
  430. DWORD cNodes;
  431. ULONG celtDummy;
  432. int idxDLM;
  433. BSTR bstrOuterNodeName = NULL;
  434. BSTR bstrInnerNodeName = NULL;
  435. BSTR bstrMsg = NULL;
  436. BSTR bstrMsgREF = NULL;
  437. IUnknown * punk = NULL;
  438. IEnumCookies * pecNodes = NULL;
  439. IClusCfgNodeInfo * pccniOuter = NULL;
  440. IClusCfgNodeInfo * pccniInner = NULL;
  441. SDriveLetterMapping dlmOuter;
  442. SDriveLetterMapping dlmInner;
  443. hr = THR( HrSendStatusReport(
  444. CTaskAnalyzeClusterBase::m_bstrClusterName
  445. , TASKID_Major_Check_Cluster_Feasibility
  446. , TASKID_Minor_Check_DriveLetter_Mappings
  447. , 0
  448. , 1
  449. , 0
  450. , hr
  451. , IDS_TASKID_MINOR_CHECK_DRIVELETTER_MAPPINGS
  452. ) );
  453. if ( FAILED( hr ) )
  454. {
  455. goto Cleanup;
  456. } // if:
  457. //
  458. // Get the node cookie enumerator.
  459. //
  460. hr = THR( CTaskAnalyzeClusterBase::m_pom->FindObject( CLSID_NodeType, CTaskAnalyzeClusterBase::m_cookieCluster, NULL, DFGUID_EnumCookies, &cookieDummy, &punk ) );
  461. if ( FAILED( hr ) )
  462. {
  463. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CompareDriveLetterMappings_Find_Object, hr );
  464. goto Cleanup;
  465. }
  466. hr = THR( punk->TypeSafeQI( IEnumCookies, &pecNodes ) );
  467. if ( FAILED( hr ) )
  468. {
  469. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CompareDriveLetterMappings_Find_Object_QI, hr );
  470. goto Cleanup;
  471. }
  472. //pecNodes = TraceInterface( L"CTaskAnalyzeCluster!IEnumCookies", IEnumCookies, pecNodes, 1 );
  473. punk->Release();
  474. punk = NULL;
  475. //
  476. // If there is only one node, just exit this function.
  477. //
  478. hr = THR( pecNodes->Count( &cNodes ) );
  479. if ( FAILED( hr ) )
  480. {
  481. goto Cleanup;
  482. }
  483. if ( cNodes == 1 )
  484. {
  485. goto Cleanup;
  486. }
  487. //
  488. // Loop through the enumerator to compare each node with every other node.
  489. // This requires an outer loop and an inner loop.
  490. //
  491. for ( idxCurrentNode = 0 ;; idxCurrentNode++ )
  492. {
  493. //
  494. // Cleanup.
  495. //
  496. if ( pccniOuter != NULL )
  497. {
  498. pccniOuter->Release();
  499. pccniOuter = NULL;
  500. }
  501. TraceSysFreeString( bstrOuterNodeName );
  502. bstrOuterNodeName = NULL;
  503. //
  504. // Skip to the next node. This is necessary since there is only one
  505. // enumerator for both the outer and inner loop.
  506. //
  507. if ( idxCurrentNode > 0 )
  508. {
  509. // Reset back to the first item in the enumerator.
  510. hr = STHR( pecNodes->Reset() );
  511. if ( FAILED( hr ) )
  512. {
  513. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Compare_Drive_Letter_Mappings_Reset_Node_Enumerator, hr );
  514. goto Cleanup;
  515. }
  516. // Skip to the current node.
  517. hr = STHR( pecNodes->Skip( idxCurrentNode ) );
  518. if ( FAILED( hr ) )
  519. {
  520. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Compare_Drive_Letter_Mappings_Skip_To_Node, hr );
  521. goto Cleanup;
  522. }
  523. if ( hr == S_FALSE )
  524. {
  525. //
  526. // Reached the end of the list.
  527. //
  528. hr = S_OK;
  529. break;
  530. }
  531. } // if: not at first node
  532. //
  533. // Find the next node.
  534. //
  535. hr = STHR( pecNodes->Next( 1, &cookieClusterNode, &celtDummy ) );
  536. if ( FAILED( hr ) )
  537. {
  538. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Compare_Drive_Letter_Mappings_Find_Outer_Node_Next, hr );
  539. goto Cleanup;
  540. }
  541. if ( hr == S_FALSE )
  542. {
  543. //
  544. // Reached the end of the list.
  545. //
  546. hr = S_OK;
  547. break;
  548. }
  549. //
  550. // Retrieve the node information.
  551. //
  552. hr = THR( CTaskAnalyzeClusterBase::m_pom->GetObject( DFGUID_NodeInformation, cookieClusterNode, &punk ) );
  553. if ( FAILED( hr ) )
  554. {
  555. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Compare_Drive_Letter_Mappings_Outer_NodeInfo_FindObject, hr );
  556. goto Cleanup;
  557. }
  558. hr = THR( punk->TypeSafeQI( IClusCfgNodeInfo, &pccniOuter ) );
  559. if ( FAILED( hr ) )
  560. {
  561. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Compare_Drive_Letter_Mappings_Outer_NodeInfo_FindObject_QI, hr );
  562. goto Cleanup;
  563. }
  564. //pccniOuter = TraceInterface( L"CTaskAnalyzeCluster!IClusCfgNodeInfo", IClusCfgNodeInfo, pccni, 1 );
  565. punk->Release();
  566. punk = NULL;
  567. //
  568. // Get the drive letter mappings for the outer node.
  569. //
  570. hr = THR( pccniOuter->GetDriveLetterMappings( &dlmOuter ) );
  571. if ( FAILED( hr ) )
  572. {
  573. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Compare_Drive_Letter_Mappings_Outer_NodeInfo_GetDLM, hr );
  574. goto Cleanup;
  575. }
  576. //
  577. // Get the name of the node.
  578. //
  579. hr = THR( pccniOuter->GetName( &bstrOuterNodeName ) );
  580. if ( FAILED( hr ) )
  581. {
  582. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Compare_Drive_Letter_Mappings_Outer_GetNodeName, hr );
  583. goto Cleanup;
  584. }
  585. TraceMemoryAddBSTR( bstrOuterNodeName );
  586. //
  587. // Loop through all the other nodes in the cluster.
  588. //
  589. for ( ;; )
  590. {
  591. //
  592. // Cleanup.
  593. //
  594. if ( pccniInner != NULL )
  595. {
  596. pccniInner->Release();
  597. pccniInner = NULL;
  598. }
  599. TraceSysFreeString( bstrInnerNodeName );
  600. bstrInnerNodeName = NULL;
  601. //
  602. // Find the next node.
  603. //
  604. hr = STHR( pecNodes->Next( 1, &cookieClusterNode, &celtDummy ) );
  605. if ( FAILED( hr ) )
  606. {
  607. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Compare_Drive_Letter_Mappings_Find_Inner_Node_Next, hr );
  608. goto Cleanup;
  609. }
  610. if ( hr == S_FALSE )
  611. {
  612. //
  613. // Reached the end of the list.
  614. //
  615. hr = S_OK;
  616. break;
  617. }
  618. //
  619. // Retrieve the node information.
  620. //
  621. hr = THR( CTaskAnalyzeClusterBase::m_pom->GetObject( DFGUID_NodeInformation, cookieClusterNode, &punk ) );
  622. if ( FAILED( hr ) )
  623. {
  624. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Compare_Drive_Letter_Mappings_Inner_NodeInfo_FindObject, hr );
  625. goto Cleanup;
  626. }
  627. hr = THR( punk->TypeSafeQI( IClusCfgNodeInfo, &pccniInner ) );
  628. if ( FAILED( hr ) )
  629. {
  630. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Compare_Drive_Letter_Mappings_Inner_NodeInfo_FindObject_QI, hr );
  631. goto Cleanup;
  632. }
  633. //pccniInner = TraceInterface( L"CTaskAnalyzeCluster!IClusCfgNodeInfo", IClusCfgNodeInfo, pccni, 1 );
  634. punk->Release();
  635. punk = NULL;
  636. //
  637. // Get the drive letter mappings for the inner node.
  638. //
  639. hr = THR( pccniInner->GetDriveLetterMappings( &dlmInner ) );
  640. if ( FAILED( hr ) )
  641. {
  642. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Compare_Drive_Letter_Mappings_Inner_NodeInfo_GetDLM, hr );
  643. goto Cleanup;
  644. }
  645. //
  646. // Get the name of the node.
  647. //
  648. hr = THR( pccniInner->GetName( &bstrInnerNodeName ) );
  649. if ( FAILED( hr ) )
  650. {
  651. SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Compare_Drive_Letter_Mappings_Inner_GetNodeName, hr );
  652. goto Cleanup;
  653. }
  654. TraceMemoryAddBSTR( bstrInnerNodeName );
  655. //
  656. // Loop through the drive letter mappings to make sure that there
  657. // are no conflicts between the two machines.
  658. //
  659. for ( idxDLM = 0 ; idxDLM < 26 ; idxDLM++ )
  660. {
  661. if ( dlmOuter.dluDrives[ idxDLM ] == dluSYSTEM )
  662. {
  663. CLSID clsidMinorId;
  664. hr = THR( CoCreateGuid( &clsidMinorId ) );
  665. if ( FAILED( hr ) )
  666. {
  667. clsidMinorId = IID_NULL;
  668. }
  669. switch ( dlmInner.dluDrives[ idxDLM ] )
  670. {
  671. case dluFIXED_DISK:
  672. case dluREMOVABLE_DISK:
  673. {
  674. LPCWSTR pwszMsg;
  675. LPCWSTR pwszMsgREF;
  676. hrDriveConflictError = HRESULT_FROM_WIN32( ERROR_CLUSCFG_SYSTEM_DISK_DRIVE_LETTER_CONFLICT );
  677. hr = THR( HrFormatStringIntoBSTR(
  678. g_hInstance
  679. , IDS_TASKID_MINOR_SYSTEM_DRIVE_LETTER_CONFLICT_ERROR
  680. , &bstrMsg
  681. , bstrOuterNodeName
  682. , L'A' + idxDLM // construct the drive letter
  683. , bstrInnerNodeName
  684. ) );
  685. if ( bstrMsg == NULL )
  686. {
  687. pwszMsg = L"System drive conflicts.";
  688. }
  689. else
  690. {
  691. pwszMsg = bstrMsg;
  692. }
  693. hr = THR( HrFormatStringIntoBSTR(
  694. g_hInstance
  695. , IDS_TASKID_MINOR_SYSTEM_DRIVE_LETTER_CONFLICT_ERROR_REF
  696. , &bstrMsgREF
  697. ) );
  698. if ( bstrMsgREF == NULL )
  699. {
  700. pwszMsgREF = L"System drive conflicts. Make sure there is no drive letter conflict between these nodes and re-run the cluster setup.";
  701. }
  702. else
  703. {
  704. pwszMsgREF = bstrMsgREF;
  705. }
  706. hr = THR( SendStatusReport(
  707. CTaskAnalyzeClusterBase::m_bstrClusterName
  708. , TASKID_Minor_Check_DriveLetter_Mappings
  709. , clsidMinorId
  710. , 0
  711. , 1
  712. , 1
  713. , hrDriveConflictError
  714. , pwszMsg
  715. , NULL
  716. , pwszMsgREF
  717. ) );
  718. if ( FAILED( hr ) )
  719. {
  720. goto Cleanup;
  721. }
  722. break;
  723. } // case: fixed disk or removable disk
  724. case dluCOMPACT_DISC:
  725. case dluNETWORK_DRIVE:
  726. case dluRAM_DISK:
  727. {
  728. LPCWSTR pwszMsg;
  729. LPCWSTR pwszMsgREF;
  730. UINT ids = 0;
  731. hrDriveConflictWarning = MAKE_HRESULT( 0, FACILITY_WIN32, ERROR_CLUSCFG_SYSTEM_DISK_DRIVE_LETTER_CONFLICT );
  732. if ( dlmInner.dluDrives[ idxDLM ] == dluCOMPACT_DISC )
  733. {
  734. ids = IDS_TASKID_MINOR_SYSTEM_DRIVE_LETTER_CONFLICT_CD_WARNING;
  735. } // if: ( dlmInner.dluDrives[ idxDLM ] == dluCOMPACT_DISC )
  736. else if ( dlmInner.dluDrives[ idxDLM ] == dluNETWORK_DRIVE )
  737. {
  738. ids = IDS_TASKID_MINOR_SYSTEM_DRIVE_LETTER_CONFLICT_NET_WARNING;
  739. } // if: ( dlmInner.dluDrives[ idxDLM ] == dluNETWORK_DRIVE )
  740. else if ( dlmInner.dluDrives[ idxDLM ] == dluRAM_DISK )
  741. {
  742. ids = IDS_TASKID_MINOR_SYSTEM_DRIVE_LETTER_CONFLICT_RAM_WARNING;
  743. } // if: ( dlmInner.dluDrives[ idxDLM ] == dluRAM_DISK )
  744. Assert( ids != 0 );
  745. hr = THR( HrFormatStringIntoBSTR(
  746. g_hInstance
  747. , ids
  748. , &bstrMsg
  749. , bstrOuterNodeName
  750. , L'A' + idxDLM // construct the drive letter
  751. , bstrInnerNodeName
  752. ) );
  753. if ( FAILED( hr ) )
  754. {
  755. goto Cleanup;
  756. }
  757. if ( bstrMsg == NULL )
  758. {
  759. pwszMsg = L"System drive conflicts.";
  760. }
  761. else
  762. {
  763. pwszMsg = bstrMsg;
  764. }
  765. hr = THR( HrFormatStringIntoBSTR(
  766. g_hInstance
  767. , IDS_TASKID_MINOR_SYSTEM_DRIVE_LETTER_CONFLICT_WARNING_REF
  768. , &bstrMsgREF
  769. ) );
  770. if ( FAILED( hr ) )
  771. {
  772. goto Cleanup;
  773. }
  774. if ( bstrMsgREF == NULL )
  775. {
  776. pwszMsgREF = L"System drive conflicts. It is recommended not to have any drive letter conflicts between nodes.";
  777. }
  778. else
  779. {
  780. pwszMsgREF = bstrMsgREF;
  781. }
  782. hr = THR( SendStatusReport(
  783. CTaskAnalyzeClusterBase::m_bstrClusterName
  784. , TASKID_Minor_Check_DriveLetter_Mappings
  785. , clsidMinorId
  786. , 0
  787. , 1
  788. , 1
  789. , hrDriveConflictWarning
  790. , pwszMsg
  791. , NULL
  792. , pwszMsgREF
  793. ) );
  794. if ( FAILED( hr ) )
  795. {
  796. goto Cleanup;
  797. }
  798. break;
  799. } // case: compact disc, network drive, or ram disk
  800. } // switch: inner drive letter usage
  801. } // if: outer node drive is a system drive
  802. if ( dlmInner.dluDrives[ idxDLM ] == dluSYSTEM )
  803. {
  804. CLSID clsidMinorId;
  805. hr = THR( CoCreateGuid( &clsidMinorId ) );
  806. if ( FAILED( hr ) )
  807. {
  808. clsidMinorId = IID_NULL;
  809. }
  810. switch ( dlmOuter.dluDrives[ idxDLM ] )
  811. {
  812. case dluFIXED_DISK:
  813. case dluREMOVABLE_DISK:
  814. {
  815. LPCWSTR pwszMsg;
  816. LPCWSTR pwszMsgREF;
  817. hrDriveConflictError = HRESULT_FROM_WIN32( ERROR_CLUSCFG_SYSTEM_DISK_DRIVE_LETTER_CONFLICT );
  818. hr = THR( HrFormatStringIntoBSTR(
  819. g_hInstance
  820. , IDS_TASKID_MINOR_SYSTEM_DRIVE_LETTER_CONFLICT_ERROR
  821. , &bstrMsg
  822. , bstrInnerNodeName
  823. , L'A' + idxDLM // construct the drive letter
  824. , bstrOuterNodeName
  825. ) );
  826. if ( bstrMsg == NULL )
  827. {
  828. pwszMsg = L"System drive conflicts.";
  829. }
  830. else
  831. {
  832. pwszMsg = bstrMsg;
  833. }
  834. hr = THR( HrFormatStringIntoBSTR(
  835. g_hInstance
  836. , IDS_TASKID_MINOR_SYSTEM_DRIVE_LETTER_CONFLICT_ERROR_REF
  837. , &bstrMsgREF
  838. ) );
  839. if ( bstrMsgREF == NULL )
  840. {
  841. pwszMsgREF = L"System drive conflicts. Make sure there is no drive letter conflict between these nodes and re-run the cluster setup.";
  842. }
  843. else
  844. {
  845. pwszMsgREF = bstrMsgREF;
  846. }
  847. hr = THR( SendStatusReport(
  848. CTaskAnalyzeClusterBase::m_bstrClusterName
  849. , TASKID_Minor_Check_DriveLetter_Mappings
  850. , clsidMinorId
  851. , 0
  852. , 1
  853. , 1
  854. , hrDriveConflictError
  855. , pwszMsg
  856. , NULL
  857. , pwszMsgREF
  858. ) );
  859. if ( FAILED( hr ) )
  860. {
  861. goto Cleanup;
  862. }
  863. break;
  864. } // case: fixed disk or removable disk
  865. case dluCOMPACT_DISC:
  866. case dluNETWORK_DRIVE:
  867. case dluRAM_DISK:
  868. {
  869. LPCWSTR pwszMsg;
  870. LPCWSTR pwszMsgREF;
  871. UINT ids = 0;
  872. hrDriveConflictWarning = MAKE_HRESULT( 0, FACILITY_WIN32, ERROR_CLUSCFG_SYSTEM_DISK_DRIVE_LETTER_CONFLICT );
  873. if ( dlmOuter.dluDrives[ idxDLM ] == dluCOMPACT_DISC )
  874. {
  875. ids = IDS_TASKID_MINOR_SYSTEM_DRIVE_LETTER_CONFLICT_CD_WARNING;
  876. } // if: ( dlmOuter.dluDrives[ idxDLM ] == dluCOMPACT_DISC )
  877. else if ( dlmOuter.dluDrives[ idxDLM ] == dluNETWORK_DRIVE )
  878. {
  879. ids = IDS_TASKID_MINOR_SYSTEM_DRIVE_LETTER_CONFLICT_NET_WARNING;
  880. } // if: ( dlmOuter.dluDrives[ idxDLM ] == dluNETWORK_DRIVE )
  881. else if ( dlmOuter.dluDrives[ idxDLM ] == dluRAM_DISK )
  882. {
  883. ids = IDS_TASKID_MINOR_SYSTEM_DRIVE_LETTER_CONFLICT_RAM_WARNING;
  884. } // if: ( dlmOuter.dluDrives[ idxDLM ] == dluRAM_DISK )
  885. Assert( ids != 0 );
  886. hr = THR( HrFormatStringIntoBSTR(
  887. g_hInstance
  888. , ids
  889. , &bstrMsg
  890. , bstrInnerNodeName
  891. , L'A' + idxDLM // construct the drive letter
  892. , bstrOuterNodeName
  893. ) );
  894. if ( FAILED( hr ) )
  895. {
  896. goto Cleanup;
  897. }
  898. if ( bstrMsg == NULL )
  899. {
  900. pwszMsg = L"System drive conflicts.";
  901. }
  902. else
  903. {
  904. pwszMsg = bstrMsg;
  905. }
  906. hr = THR( HrFormatStringIntoBSTR(
  907. g_hInstance
  908. , IDS_TASKID_MINOR_SYSTEM_DRIVE_LETTER_CONFLICT_WARNING_REF
  909. , &bstrMsgREF
  910. ) );
  911. if ( FAILED( hr ) )
  912. {
  913. goto Cleanup;
  914. }
  915. if ( bstrMsgREF == NULL )
  916. {
  917. pwszMsgREF = L"System drive conflicts. It is recommended not to have any drive letter conflicts between nodes.";
  918. }
  919. else
  920. {
  921. pwszMsgREF = bstrMsgREF;
  922. }
  923. hr = THR( SendStatusReport(
  924. CTaskAnalyzeClusterBase::m_bstrClusterName
  925. , TASKID_Minor_Check_DriveLetter_Mappings
  926. , clsidMinorId
  927. , 0
  928. , 1
  929. , 1
  930. , hrDriveConflictWarning
  931. , pwszMsg
  932. , NULL
  933. , pwszMsgREF
  934. ) );
  935. if ( FAILED( hr ) )
  936. {
  937. goto Cleanup;
  938. }
  939. break;
  940. } // case: compact disc, network drive, or ram disk
  941. } // switch: outer drive letter usage
  942. } // if: inner node drive is a system drive
  943. } // for: each drive letter mapping
  944. } // for ever: inner node loop
  945. } // for ever: outer node loop
  946. Cleanup:
  947. THR( HrSendStatusReport(
  948. CTaskAnalyzeClusterBase::m_bstrClusterName
  949. , TASKID_Major_Check_Cluster_Feasibility
  950. , TASKID_Minor_Check_DriveLetter_Mappings
  951. , 0
  952. , 1
  953. , 1
  954. , hr
  955. , IDS_TASKID_MINOR_CHECK_DRIVELETTER_MAPPINGS
  956. ) );
  957. TraceSysFreeString( bstrOuterNodeName );
  958. TraceSysFreeString( bstrInnerNodeName );
  959. TraceSysFreeString( bstrMsg );
  960. TraceSysFreeString( bstrMsgREF );
  961. if ( pecNodes != NULL )
  962. {
  963. pecNodes->Release();
  964. }
  965. if ( pccniOuter != NULL )
  966. {
  967. pccniOuter->Release();
  968. }
  969. if ( pccniInner != NULL )
  970. {
  971. pccniInner->Release();
  972. }
  973. if ( punk != NULL )
  974. {
  975. punk->Release();
  976. }
  977. //
  978. // Set the return value if an error or warning occurred.
  979. // An error will override a warning.
  980. //
  981. if ( hrDriveConflictError != S_OK )
  982. {
  983. hr = hrDriveConflictError;
  984. }
  985. else if ( hrDriveConflictWarning != S_OK )
  986. {
  987. hr = hrDriveConflictWarning;
  988. }
  989. HRETURN( hr );
  990. } //*** CTaskAnalyzeCluster::HrCompareDriveLetterMappings
  991. //////////////////////////////////////////////////////////////////////////////
  992. //++
  993. //
  994. // CTaskAnalyzeCluster::HrCreateNewResourceInCluster
  995. //
  996. // Description:
  997. // Create a new resource in the cluster configuration since there was
  998. // not a match to the resource already in the cluster.
  999. //
  1000. // Arguments:
  1001. // pccmriIn
  1002. //
  1003. // Return Value:
  1004. // S_OK
  1005. // Success.
  1006. //
  1007. // Other HRESULT error.
  1008. //
  1009. //--
  1010. //////////////////////////////////////////////////////////////////////////////
  1011. HRESULT
  1012. CTaskAnalyzeCluster::HrCreateNewResourceInCluster(
  1013. IClusCfgManagedResourceInfo * pccmriIn
  1014. , BSTR bstrNodeResNameIn
  1015. , BSTR * pbstrNodeResUIDInout
  1016. , BSTR bstrNodeNameIn
  1017. )
  1018. {
  1019. TraceFunc( "" );
  1020. Assert( pccmriIn != NULL );
  1021. Assert( pbstrNodeResUIDInout != NULL );
  1022. HRESULT hr = S_OK;
  1023. IClusCfgManagedResourceInfo * pccmriNew = NULL;
  1024. //
  1025. // Need to create a new object.
  1026. //
  1027. hr = THR( HrCreateNewManagedResourceInClusterConfiguration( pccmriIn, &pccmriNew ) );
  1028. if ( FAILED( hr ) )
  1029. {
  1030. goto Cleanup;
  1031. } // if:
  1032. //
  1033. // Display the name of the node's resource in the log.
  1034. //
  1035. LogMsg(
  1036. L"[MT] Created object for resource '%ws' ('%ws') from node '%ws' in the cluster configuration."
  1037. , bstrNodeResNameIn
  1038. , *pbstrNodeResUIDInout
  1039. , bstrNodeNameIn
  1040. );
  1041. //
  1042. // If this is the quorum resource, remember it.
  1043. //
  1044. hr = STHR( pccmriNew->IsQuorumResource() );
  1045. if ( hr == S_OK )
  1046. {
  1047. //
  1048. // Remember the quorum device's UID.
  1049. //
  1050. Assert( m_bstrQuorumUID == NULL );
  1051. m_bstrQuorumUID = *pbstrNodeResUIDInout;
  1052. *pbstrNodeResUIDInout = NULL;
  1053. } // if:
  1054. hr = S_OK;
  1055. Cleanup:
  1056. if ( pccmriNew != NULL )
  1057. {
  1058. pccmriNew->Release();
  1059. } // if:
  1060. HRETURN( hr );
  1061. } //*** CTaskAnalyzeCluster::HrCreateNewResourceInCluster
  1062. //////////////////////////////////////////////////////////////////////////////
  1063. //++
  1064. //
  1065. // CTaskAnalyzeCluster::HrCreateNewResourceInCluster
  1066. //
  1067. // Description:
  1068. // Create a new resource in the cluster configuration since there was
  1069. // not a match to the resource already in the cluster.
  1070. //
  1071. // Arguments:
  1072. // pccmriIn
  1073. // The source object.
  1074. //
  1075. // ppccmriOut
  1076. // The new object that was created.
  1077. //
  1078. // Return Value:
  1079. // S_OK
  1080. // Success.
  1081. //
  1082. // Other HRESULT error.
  1083. //
  1084. //--
  1085. //////////////////////////////////////////////////////////////////////////////
  1086. HRESULT
  1087. CTaskAnalyzeCluster::HrCreateNewResourceInCluster(
  1088. IClusCfgManagedResourceInfo * pccmriIn
  1089. , IClusCfgManagedResourceInfo ** ppccmriOut
  1090. )
  1091. {
  1092. TraceFunc( "" );
  1093. Assert( pccmriIn != NULL );
  1094. Assert( ppccmriOut != NULL );
  1095. HRESULT hr = S_OK;
  1096. //
  1097. // Need to create a new object.
  1098. //
  1099. hr = THR( HrCreateNewManagedResourceInClusterConfiguration( pccmriIn, ppccmriOut ) );
  1100. if ( FAILED( hr ) )
  1101. {
  1102. goto Cleanup;
  1103. } // if:
  1104. //
  1105. // If the resource is manageable in a cluster then we should set it
  1106. // to be managed so it will be created by PostConfig.
  1107. //
  1108. hr = STHR( (*ppccmriOut)->IsManagedByDefault() );
  1109. if ( FAILED( hr ) )
  1110. {
  1111. goto Cleanup;
  1112. } // if:
  1113. if ( hr == S_OK )
  1114. {
  1115. hr = THR( (*ppccmriOut)->SetManaged( TRUE ) );
  1116. if ( FAILED( hr ) )
  1117. {
  1118. goto Cleanup;
  1119. } // if:
  1120. } // if:
  1121. hr = S_OK;
  1122. Cleanup:
  1123. HRETURN( hr );
  1124. } //*** CTaskAnalyzeCluster::HrCreateNewResourceInCluster
  1125. //////////////////////////////////////////////////////////////////////////////
  1126. //++
  1127. //
  1128. // CTaskAnalyzeCluster::HrFixupErrorCode
  1129. //
  1130. // Description:
  1131. // Do any fix ups needed for the passed in error code and return the
  1132. // fixed up value. The default implementation is to do no fixups.
  1133. //
  1134. // Arguments:
  1135. // hrIn
  1136. // The error code to fix up.
  1137. //
  1138. // Return Value:
  1139. // The passed in error code.
  1140. //
  1141. //--
  1142. //////////////////////////////////////////////////////////////////////////////
  1143. HRESULT
  1144. CTaskAnalyzeCluster::HrFixupErrorCode(
  1145. HRESULT hrIn
  1146. )
  1147. {
  1148. TraceFunc( "" );
  1149. HRETURN( hrIn );
  1150. } //*** CTaskAnalyzeCluster::HrFixupErrorCode
  1151. //////////////////////////////////////////////////////////////////////////////
  1152. //++
  1153. //
  1154. // CTaskAnalyzeCluster::GetNodeCannotVerifyQuorumStringRefId
  1155. //
  1156. // Description:
  1157. // Return the correct string ids for the message that is displayed
  1158. // to the user when there isn't a quorum resource.
  1159. //
  1160. // Arguments:
  1161. // pdwRefIdOut
  1162. // The reference text to show the user.
  1163. //
  1164. // Return Value:
  1165. // None.
  1166. //
  1167. //--
  1168. //////////////////////////////////////////////////////////////////////////////
  1169. void
  1170. CTaskAnalyzeCluster::GetNodeCannotVerifyQuorumStringRefId(
  1171. DWORD * pdwRefIdOut
  1172. )
  1173. {
  1174. TraceFunc( "" );
  1175. Assert( pdwRefIdOut != NULL );
  1176. *pdwRefIdOut = IDS_TASKID_MINOR_NODE_CANNOT_ACCESS_QUORUM_ERROR_REF;
  1177. TraceFuncExit();
  1178. } //*** CTaskAnalyzeCluster::GetNodeCannotVerifyQuorumStringRefId
  1179. //////////////////////////////////////////////////////////////////////////////
  1180. //++
  1181. //
  1182. // CTaskAnalyzeCluster::GetNoCommonQuorumToAllNodesStringIds
  1183. //
  1184. // Description:
  1185. // Return the correct string ids for the message that is displayed
  1186. // to the user when there isn't a common to all nodes quorum resource.
  1187. //
  1188. // Arguments:
  1189. // pdwMessageIdOut
  1190. // The message to show the user.
  1191. //
  1192. // pdwRefIdOut
  1193. // The reference text to show the user.
  1194. //
  1195. // Return Value:
  1196. // None.
  1197. //
  1198. //--
  1199. //////////////////////////////////////////////////////////////////////////////
  1200. void
  1201. CTaskAnalyzeCluster::GetNoCommonQuorumToAllNodesStringIds(
  1202. DWORD * pdwMessageIdOut
  1203. , DWORD * pdwRefIdOut
  1204. )
  1205. {
  1206. TraceFunc( "" );
  1207. Assert( pdwMessageIdOut != NULL );
  1208. Assert( pdwRefIdOut != NULL );
  1209. *pdwMessageIdOut = IDS_TASKID_MINOR_MISSING_COMMON_QUORUM_RESOURCE_ERROR;
  1210. *pdwRefIdOut = IDS_TASKID_MINOR_MISSING_COMMON_QUORUM_RESOURCE_ERROR_REF;
  1211. TraceFuncExit();
  1212. } //*** CTaskAnalyzeCluster::GetNoCommonQuorumToAllNodesStringIds
  1213. //////////////////////////////////////////////////////////////////////////////
  1214. //++
  1215. //
  1216. // CTaskAnalyzeCluster::HrShowLocalQuorumWarning
  1217. //
  1218. // Description:
  1219. // Send the warning about forcing local quorum to the UI.
  1220. //
  1221. // Arguments:
  1222. // None.
  1223. //
  1224. // Return Value:
  1225. // S_OK
  1226. // The SSR was done properly.
  1227. //
  1228. //--
  1229. //////////////////////////////////////////////////////////////////////////////
  1230. HRESULT
  1231. CTaskAnalyzeCluster::HrShowLocalQuorumWarning( void )
  1232. {
  1233. TraceFunc( "" );
  1234. HRESULT hr = S_OK;
  1235. hr = THR( HrSendStatusReport(
  1236. CTaskAnalyzeClusterBase::m_bstrClusterName
  1237. , TASKID_Minor_Finding_Common_Quorum_Device
  1238. , TASKID_Minor_Forced_Local_Quorum
  1239. , 1
  1240. , 1
  1241. , 1
  1242. , MAKE_HRESULT( SEVERITY_SUCCESS, FACILITY_WIN32, ERROR_QUORUM_DISK_NOT_FOUND )
  1243. , IDS_TASKID_MINOR_FORCED_LOCAL_QUORUM
  1244. ) );
  1245. HRETURN( hr );
  1246. } //*** CTaskAnalyzeCluster::HrShowLocalQuorumWarning