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.

1815 lines
51 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2000-2001 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // CBCAInterface.cpp
  7. //
  8. // Description:
  9. // This file contains the implementation of the CBCAInterface
  10. // class.
  11. //
  12. // Maintained By:
  13. // David Potter (DavidP) 12-JUN-2001
  14. // Vij Vasu (VVasu) 07-MAR-2000
  15. //
  16. //////////////////////////////////////////////////////////////////////////////
  17. //////////////////////////////////////////////////////////////////////////////
  18. // Include Files
  19. //////////////////////////////////////////////////////////////////////////////
  20. // The precompiled header for this library
  21. #include "Pch.h"
  22. // The header file for this class
  23. #include "CBCAInterface.h"
  24. // Needed by Dll.h
  25. #include <CFactory.h>
  26. // For g_cObjects
  27. #include <Dll.h>
  28. // For the CBaseClusterForm class
  29. #include "CBaseClusterForm.h"
  30. // For the CBaseClusterJoin class
  31. #include "CBaseClusterJoin.h"
  32. // For the CBaseClusterCleanup class
  33. #include "CBaseClusterCleanup.h"
  34. // For the exception classes
  35. #include "Exceptions.h"
  36. //////////////////////////////////////////////////////////////////////////////
  37. // Macro Definitions
  38. //////////////////////////////////////////////////////////////////////////////
  39. //////////////////////////////////////////////////////////////////////////////
  40. // Constant Definitions
  41. //////////////////////////////////////////////////////////////////////////////
  42. DEFINE_THISCLASS( "CBCAInterface" );
  43. //////////////////////////////////////////////////////////////////////////////
  44. //++
  45. //
  46. // CBCAInterface::CBCAInterface
  47. //
  48. // Description:
  49. // Constructor of the CBCAInterface class. This initializes
  50. // the m_cRef variable to 1 instead of 0 to account of possible
  51. // QueryInterface failure in DllGetClassObject.
  52. //
  53. // Arguments:
  54. // None.
  55. //
  56. // Return Value:
  57. // None.
  58. //
  59. // Remarks:
  60. // None.
  61. //
  62. //--
  63. //////////////////////////////////////////////////////////////////////////////
  64. CBCAInterface::CBCAInterface( void )
  65. : m_cRef( 1 )
  66. , m_fCommitComplete( false )
  67. , m_fRollbackPossible( false )
  68. , m_lcid( LOCALE_SYSTEM_DEFAULT )
  69. , m_fCallbackSupported( false )
  70. {
  71. TraceFunc( "" );
  72. // Increment the count of components in memory so the DLL hosting this
  73. // object cannot be unloaded.
  74. InterlockedIncrement( &g_cObjects );
  75. TraceFlow1( "Component count = %d.", g_cObjects );
  76. TraceFuncExit();
  77. } //*** CBCAInterface::CBCAInterface
  78. //////////////////////////////////////////////////////////////////////////////
  79. //++
  80. //
  81. // CBCAInterface::~CBCAInterface
  82. //
  83. // Description:
  84. // Destructor of the CBCAInterface class.
  85. //
  86. // Arguments:
  87. // None.
  88. //
  89. // Return Value:
  90. // None.
  91. //
  92. // Remarks:
  93. // None.
  94. //
  95. //--
  96. //////////////////////////////////////////////////////////////////////////////
  97. CBCAInterface::~CBCAInterface( void )
  98. {
  99. TraceFunc( "" );
  100. // There's going to be one less component in memory. Decrement component count.
  101. InterlockedDecrement( &g_cObjects );
  102. TraceFlow1( "Component count = %d.", g_cObjects );
  103. TraceFuncExit();
  104. } //*** CBCAInterface::~CBCAInterface
  105. //////////////////////////////////////////////////////////////////////////////
  106. //++
  107. //
  108. // static
  109. // CBCAInterface::S_HrCreateInstance
  110. //
  111. // Description:
  112. // Creates a CBCAInterface instance.
  113. //
  114. // Arguments:
  115. // ppunkOut
  116. // The IUnknown interface of the new object.
  117. //
  118. // Return Values:
  119. // S_OK
  120. // Success.
  121. //
  122. // E_OUTOFMEMORY
  123. // Not enough memory to create the object.
  124. //
  125. // other HRESULTs
  126. // Object initialization failed.
  127. //
  128. //--
  129. //////////////////////////////////////////////////////////////////////////////
  130. HRESULT
  131. CBCAInterface::S_HrCreateInstance(
  132. IUnknown ** ppunkOut
  133. )
  134. {
  135. TraceFunc( "" );
  136. HRESULT hr = S_OK;
  137. CBCAInterface * pbcaInterface = NULL;
  138. Assert( ppunkOut != NULL );
  139. if ( ppunkOut == NULL )
  140. {
  141. hr = THR( E_POINTER );
  142. goto Cleanup;
  143. }
  144. pbcaInterface = new CBCAInterface();
  145. if ( pbcaInterface == NULL )
  146. {
  147. hr = THR( E_OUTOFMEMORY );
  148. goto Cleanup;
  149. }
  150. hr = THR( pbcaInterface->QueryInterface(
  151. IID_IUnknown
  152. , reinterpret_cast< void ** >( ppunkOut )
  153. )
  154. );
  155. if ( FAILED( hr ) )
  156. {
  157. goto Cleanup;
  158. }
  159. Cleanup:
  160. if ( pbcaInterface != NULL )
  161. {
  162. pbcaInterface->Release();
  163. }
  164. HRETURN( hr );
  165. } //*** CBCAInterface::S_HrCreateInstance
  166. //////////////////////////////////////////////////////////////////////////////
  167. //++
  168. //
  169. // CBCAInterface::AddRef
  170. //
  171. // Description:
  172. // Increment the reference count of this object by one.
  173. //
  174. // Arguments:
  175. // None.
  176. //
  177. // Return Value:
  178. // The new reference count.
  179. //
  180. // Remarks:
  181. // None.
  182. //
  183. //--
  184. //////////////////////////////////////////////////////////////////////////////
  185. STDMETHODIMP_( ULONG )
  186. CBCAInterface::AddRef( void )
  187. {
  188. TraceFunc( "[IUnknown]" );
  189. InterlockedIncrement( &m_cRef );
  190. CRETURN( m_cRef );
  191. } //*** CBCAInterface::AddRef
  192. //////////////////////////////////////////////////////////////////////////////
  193. //++
  194. //
  195. // CBCAInterface::Release
  196. //
  197. // Description:
  198. // Decrement the reference count of this object by one.
  199. //
  200. // Arguments:
  201. // None.
  202. //
  203. // Return Value:
  204. // The new reference count.
  205. //
  206. // Remarks:
  207. // None.
  208. //
  209. //--
  210. //////////////////////////////////////////////////////////////////////////////
  211. STDMETHODIMP_( ULONG )
  212. CBCAInterface::Release( void )
  213. {
  214. TraceFunc( "[IUnknown]" );
  215. LONG cRef;
  216. cRef = InterlockedDecrement( &m_cRef );
  217. if ( cRef == 0 )
  218. {
  219. TraceDo( delete this );
  220. } // if: reference count decremented to zero
  221. CRETURN( cRef );
  222. } //*** CBCAInterface::Release
  223. //////////////////////////////////////////////////////////////////////////////
  224. //++
  225. //
  226. // CBCAInterface::QueryInterface
  227. //
  228. // Description:
  229. // Query this object for the passed in interface.
  230. //
  231. // Arguments:
  232. // riidIn
  233. // Id of interface requested.
  234. //
  235. // ppvOut
  236. // Pointer to the requested interface.
  237. //
  238. // Return Value:
  239. // S_OK
  240. // If the interface is available on this object.
  241. //
  242. // E_NOINTERFACE
  243. // If the interface is not available.
  244. //
  245. // E_POINTER
  246. // If ppvOut is NULL.
  247. //
  248. // Remarks:
  249. // None.
  250. //
  251. //--
  252. //////////////////////////////////////////////////////////////////////////////
  253. STDMETHODIMP
  254. CBCAInterface::QueryInterface(
  255. REFIID riidIn
  256. , void ** ppvOut
  257. )
  258. {
  259. TraceQIFunc( riidIn, ppvOut );
  260. HRESULT hr = S_OK;
  261. //
  262. // Validate arguments.
  263. //
  264. Assert( ppvOut != NULL );
  265. if ( ppvOut == NULL )
  266. {
  267. hr = THR( E_POINTER );
  268. goto Cleanup;
  269. }
  270. //
  271. // Handle known interfaces.
  272. //
  273. if ( IsEqualIID( riidIn, IID_IUnknown ) )
  274. {
  275. *ppvOut = static_cast< IClusCfgBaseCluster * >( this );
  276. } // if: IUnknown
  277. else if ( IsEqualIID( riidIn, IID_IClusCfgBaseCluster ) )
  278. {
  279. *ppvOut = TraceInterface( __THISCLASS__, IClusCfgBaseCluster, this, 0 );
  280. } // else if:
  281. else if ( IsEqualIID( riidIn, IID_IClusCfgInitialize ) )
  282. {
  283. *ppvOut = TraceInterface( __THISCLASS__, IClusCfgInitialize, this, 0 );
  284. } // else if:
  285. else
  286. {
  287. *ppvOut = NULL;
  288. hr = E_NOINTERFACE;
  289. } // else
  290. //
  291. // Add a reference to the interface if successful.
  292. //
  293. if ( SUCCEEDED( hr ) )
  294. {
  295. ((IUnknown *) *ppvOut)->AddRef( );
  296. } // if: success
  297. Cleanup:
  298. QIRETURN_IGNORESTDMARSHALLING( hr, riidIn );
  299. } //*** CBCAInterface::QueryInterface
  300. //////////////////////////////////////////////////////////////////////////////
  301. //++
  302. //
  303. // CBCAInterface::Initialize
  304. //
  305. // Description:
  306. // Initialize this component.
  307. //
  308. // Arguments:
  309. // punkCallbackIn
  310. // Pointer to the IUnknown interface of a component that implements
  311. // the IClusCfgCallback interface.
  312. //
  313. // lcidIn
  314. // Locale id for this component.
  315. //
  316. // Return Value:
  317. // S_OK
  318. // If the call succeeded
  319. //
  320. // Other HRESULTs
  321. // If the call failed.
  322. //
  323. //--
  324. //////////////////////////////////////////////////////////////////////////////
  325. STDMETHODIMP
  326. CBCAInterface::Initialize(
  327. IUnknown * punkCallbackIn,
  328. LCID lcidIn
  329. )
  330. {
  331. TraceFunc( "[IClusCfgInitialize]" );
  332. HRESULT hrRetVal = S_OK;
  333. // Store the locale id in the member variable.
  334. m_lcid = lcidIn;
  335. // Indicate that SendStatusReports will not be supported unless a non-
  336. // NULL callback interface pointer was specified. This is done in
  337. // the constructor as well, but is also done here since this method
  338. // could be called multiple times.
  339. SetCallbackSupported( false );
  340. if ( punkCallbackIn == NULL )
  341. {
  342. LogMsg( "[BC] No notifications will be sent." );
  343. goto Cleanup;
  344. }
  345. TraceFlow( "The callback pointer is not NULL." );
  346. // Try and get the "normal" callback interface.
  347. hrRetVal = THR( m_spcbCallback.HrQueryAndAssign( punkCallbackIn ) );
  348. if ( FAILED( hrRetVal ) )
  349. {
  350. LogMsg( "[BC] An error occurred (0x%#08x) trying to get a pointer to the callback interface. No notifications will be sent.", hrRetVal );
  351. goto Cleanup;
  352. } // if: we could not get the callback interface
  353. SetCallbackSupported( true );
  354. LogMsg( "[BC] Progress messages will be sent." );
  355. Cleanup:
  356. HRETURN( hrRetVal );
  357. } //*** CBCAInterface::Initialize
  358. //////////////////////////////////////////////////////////////////////////////
  359. //++
  360. //
  361. // CBCAInterface::SetCreate
  362. //
  363. // Description:
  364. // Indicate that a cluster is to be created with this computer as the first node.
  365. //
  366. // Arguments:
  367. // pcszClusterNameIn
  368. // Name of the cluster to be formed.
  369. //
  370. // pcccServiceAccountIn
  371. // Information about the cluster service account.
  372. //
  373. // dwClusterIPAddressIn
  374. // dwClusterIPSubnetMaskIn
  375. // pcszClusterIPNetworkIn
  376. // Information about the cluster IP address
  377. //
  378. // Return Value:
  379. // S_OK
  380. // If the call succeeded
  381. //
  382. // Other HRESULTs
  383. // If the call failed.
  384. //
  385. //--
  386. //////////////////////////////////////////////////////////////////////////////
  387. STDMETHODIMP
  388. CBCAInterface::SetCreate(
  389. const WCHAR * pcszClusterNameIn
  390. , const WCHAR * pcszClusterBindingStringIn
  391. , IClusCfgCredentials * pcccServiceAccountIn
  392. , const DWORD dwClusterIPAddressIn
  393. , const DWORD dwClusterIPSubnetMaskIn
  394. , const WCHAR * pcszClusterIPNetworkIn
  395. )
  396. {
  397. TraceFunc( "[IClusCfgBaseCluster]" );
  398. HRESULT hrRetVal = S_OK;
  399. // Set the thread locale.
  400. if ( SetThreadLocale( m_lcid ) == FALSE )
  401. {
  402. DWORD sc = TW32( GetLastError() );
  403. // If SetThreadLocale() fails, do not abort. Just log the error.
  404. LogMsg( "[BC] Error 0x%#08x occurred trying to set the thread locale.", sc );
  405. } // if: SetThreadLocale() failed
  406. try
  407. {
  408. LogMsg( "[BC] Initializing a cluster create operation." );
  409. // Reset these state variables, to account for exceptions.
  410. SetRollbackPossible( false );
  411. // Setting this to true prevents Commit from being called while we are
  412. // in this routine or if this routine doesn't complete successfully.
  413. SetCommitCompleted( true );
  414. {
  415. // Create a CBaseClusterForm object and assign it to a smart pointer.
  416. SmartBCAPointer spbcaTemp(
  417. new CBaseClusterForm(
  418. this
  419. , pcszClusterNameIn
  420. , pcszClusterBindingStringIn
  421. , pcccServiceAccountIn
  422. , dwClusterIPAddressIn
  423. , dwClusterIPSubnetMaskIn
  424. , pcszClusterIPNetworkIn
  425. )
  426. );
  427. if ( spbcaTemp.FIsEmpty() )
  428. {
  429. LogMsg( "Could not initialize the cluster create operation. A memory allocation failure occurred." );
  430. THROW_RUNTIME_ERROR( E_OUTOFMEMORY, IDS_ERROR_CLUSTER_FORM_INIT );
  431. } // if: the memory allocation failed.
  432. //
  433. // If the creation succeeded store the pointer in a member variable for
  434. // use during commit.
  435. //
  436. m_spbcaCurrentAction = spbcaTemp;
  437. }
  438. LogMsg( "[BC] Initialization completed. A cluster will be created on commit." );
  439. // Indicate if rollback is possible.
  440. SetRollbackPossible( m_spbcaCurrentAction->FIsRollbackPossible() );
  441. // Indicate that this action has not been committed.
  442. SetCommitCompleted( false );
  443. } // try: to initialize a cluster create operation
  444. catch( CAssert & raExceptionObject )
  445. {
  446. // Process the exception.
  447. hrRetVal = THR( HrProcessException( raExceptionObject ) );
  448. } // catch( CAssert & )
  449. catch( CExceptionWithString & resExceptionObject )
  450. {
  451. // Process the exception.
  452. hrRetVal = THR( HrProcessException( resExceptionObject ) );
  453. } // catch( CExceptionWithString & )
  454. catch( CException & reExceptionObject )
  455. {
  456. // Process the exception.
  457. hrRetVal = THR( HrProcessException( reExceptionObject ) );
  458. } // catch( CException & )
  459. catch( ... )
  460. {
  461. // Catch everything. Do not let any exceptions pass out of this function.
  462. hrRetVal = THR( HrProcessException() );
  463. } // catch all
  464. HRETURN( hrRetVal );
  465. } //*** CBCAInterface::SetCreate
  466. //////////////////////////////////////////////////////////////////////////////
  467. //++
  468. //
  469. // CBCAInterface::SetAdd
  470. //
  471. // Description:
  472. // Indicate that this computer should be added to a cluster.
  473. //
  474. // Arguments:
  475. // pcszClusterNameIn
  476. // Name of the cluster to add nodes to.
  477. //
  478. // pcccServiceAccountIn
  479. // Information about the cluster service account.
  480. //
  481. // Return Value:
  482. // S_OK
  483. // If the call succeeded
  484. //
  485. // Other HRESULTs
  486. // If the call failed.
  487. //
  488. //--
  489. //////////////////////////////////////////////////////////////////////////////
  490. STDMETHODIMP
  491. CBCAInterface::SetAdd(
  492. const WCHAR * pcszClusterNameIn
  493. , const WCHAR * pcszClusterBindingStringIn
  494. , IClusCfgCredentials * pcccServiceAccountIn
  495. )
  496. {
  497. TraceFunc( "[IClusCfgBaseCluster]" );
  498. HRESULT hrRetVal = S_OK;
  499. // Set the thread locale.
  500. if ( SetThreadLocale( m_lcid ) == FALSE )
  501. {
  502. DWORD sc = TW32( GetLastError() );
  503. // If SetThreadLocale() fails, do not abort. Just log the error.
  504. LogMsg( "[BC] Error 0x%#08x occurred trying to set the thread locale.", sc );
  505. } // if: SetThreadLocale() failed
  506. try
  507. {
  508. LogMsg( "[BC] Initializing add nodes to cluster." );
  509. // Reset these state variables, to account for exceptions.
  510. SetRollbackPossible( false );
  511. // Setting this to true prevents Commit from being called while we are
  512. // in this routine or if this routine doesn't complete successfully.
  513. SetCommitCompleted( true );
  514. {
  515. // Create a CBaseClusterJoin object and assign it to a smart pointer.
  516. SmartBCAPointer spbcaTemp(
  517. new CBaseClusterJoin(
  518. this
  519. , pcszClusterNameIn
  520. , pcszClusterBindingStringIn
  521. , pcccServiceAccountIn
  522. )
  523. );
  524. if ( spbcaTemp.FIsEmpty() )
  525. {
  526. LogMsg( "[BC] Could not initialize cluster add nodes. A memory allocation failure occurred." );
  527. THROW_RUNTIME_ERROR( E_OUTOFMEMORY, IDS_ERROR_CLUSTER_JOIN_INIT );
  528. } // if: the memory allocation failed.
  529. //
  530. // If the creation succeeded store the pointer in a member variable for
  531. // use during commit.
  532. //
  533. m_spbcaCurrentAction = spbcaTemp;
  534. }
  535. LogMsg( "[BC] Initialization completed. This computer will be added to a cluster on commit." );
  536. // Indicate if rollback is possible.
  537. SetRollbackPossible( m_spbcaCurrentAction->FIsRollbackPossible() );
  538. // Indicate that this action has not been committed.
  539. SetCommitCompleted( false );
  540. } // try: to initialize for adding nodes to a cluster
  541. catch( CAssert & raExceptionObject )
  542. {
  543. // Process the exception.
  544. hrRetVal = THR( HrProcessException( raExceptionObject ) );
  545. } // catch( CAssert & )
  546. catch( CExceptionWithString & resExceptionObject )
  547. {
  548. // Process the exception.
  549. hrRetVal = THR( HrProcessException( resExceptionObject ) );
  550. } // catch( CExceptionWithString & )
  551. catch( CException & reExceptionObject )
  552. {
  553. // Process the exception.
  554. hrRetVal = THR( HrProcessException( reExceptionObject ) );
  555. } // catch( CException & )
  556. catch( ... )
  557. {
  558. // Catch everything. Do not let any exceptions pass out of this function.
  559. hrRetVal = THR( HrProcessException() );
  560. } // catch all
  561. HRETURN( hrRetVal );
  562. } //*** CBCAInterface::SetAdd
  563. //////////////////////////////////////////////////////////////////////////////
  564. //++
  565. //
  566. // CBCAInterface::SetCleanup
  567. //
  568. // Description:
  569. // Indicate that this node needs to be cleaned up. The ClusSvc service
  570. // should not be running when this action is committed.
  571. //
  572. // Arguments:
  573. // None.
  574. //
  575. // Return Value:
  576. // S_OK
  577. // If the call succeeded
  578. //
  579. // Other HRESULTs
  580. // If the call failed.
  581. //
  582. //--
  583. //////////////////////////////////////////////////////////////////////////////
  584. STDMETHODIMP
  585. CBCAInterface::SetCleanup( void )
  586. {
  587. TraceFunc( "[IClusCfgBaseCluster]" );
  588. HRESULT hrRetVal = S_OK;
  589. // Set the thread locale.
  590. if ( SetThreadLocale( m_lcid ) == FALSE )
  591. {
  592. DWORD sc = TW32( GetLastError() );
  593. // If SetThreadLocale() fails, do not abort. Just log the error.
  594. LogMsg( "[BC] Error 0x%#08x occurred trying to set the thread locale.", sc );
  595. } // if: SetThreadLocale() failed
  596. try
  597. {
  598. LogMsg( "[BC] Initializing node clean up." );
  599. // Reset these state variables, to account for exceptions.
  600. SetRollbackPossible( false );
  601. // Setting this to true prevents Commit from being called while we are
  602. // in this routine or if this routine doesn't complete successfully.
  603. SetCommitCompleted( true );
  604. {
  605. // Create a CBaseClusterCleanup object and assign it to a smart pointer.
  606. SmartBCAPointer spbcaTemp( new CBaseClusterCleanup( this ) );
  607. if ( spbcaTemp.FIsEmpty() )
  608. {
  609. LogMsg( "[BC] Could not initialize node clean up. A memory allocation failure occurred. Throwing an exception" );
  610. THROW_RUNTIME_ERROR( E_OUTOFMEMORY, IDS_ERROR_CLUSTER_CLEANUP_INIT );
  611. } // if: the memory allocation failed.
  612. //
  613. // If the creation succeeded store the pointer in a member variable for
  614. // use during commit.
  615. //
  616. m_spbcaCurrentAction = spbcaTemp;
  617. }
  618. LogMsg( "[BC] Initialization completed. This node will be cleaned up on commit." );
  619. // Indicate if rollback is possible.
  620. SetRollbackPossible( m_spbcaCurrentAction->FIsRollbackPossible() );
  621. // Indicate that this action has not been committed.
  622. SetCommitCompleted( false );
  623. } // try: to initialize node clean up
  624. catch( CAssert & raExceptionObject )
  625. {
  626. // Process the exception.
  627. hrRetVal = THR( HrProcessException( raExceptionObject ) );
  628. } // catch( CAssert & )
  629. catch( CExceptionWithString & resExceptionObject )
  630. {
  631. // Process the exception.
  632. hrRetVal = THR( HrProcessException( resExceptionObject ) );
  633. } // catch( CExceptionWithString & )
  634. catch( CException & reExceptionObject )
  635. {
  636. // Process the exception.
  637. hrRetVal = THR( HrProcessException( reExceptionObject ) );
  638. } // catch( CException & )
  639. catch( ... )
  640. {
  641. // Catch everything. Do not let any exceptions pass out of this function.
  642. hrRetVal = THR( HrProcessException() );
  643. } // catch all
  644. HRETURN( hrRetVal );
  645. } //*** CBCAInterface::SetCleanup
  646. //////////////////////////////////////////////////////////////////////////////
  647. //++
  648. //
  649. // CBCAInterface::Commit
  650. //
  651. // Description:
  652. // Perform the action indicated by a previous call to one of the SetXXX
  653. // routines.
  654. //
  655. // Arguments:
  656. // None.
  657. //
  658. // Return Value:
  659. // S_OK
  660. // If the call succeeded
  661. //
  662. // HRESULT_FROM_WIN32( ERROR_CLUSCFG_ALREADY_COMMITTED )
  663. // If this commit has already been performed.
  664. //
  665. // E_INVALIDARG
  666. // If no action has been set using a SetXXX call.
  667. //
  668. // Other HRESULTs
  669. // If the call failed.
  670. //
  671. // Remarks:
  672. // None.
  673. //
  674. //--
  675. //////////////////////////////////////////////////////////////////////////////
  676. STDMETHODIMP
  677. CBCAInterface::Commit( void )
  678. {
  679. TraceFunc( "[IClusCfgBaseCluster]" );
  680. HRESULT hrRetVal = S_OK;
  681. // Set the thread locale.
  682. if ( SetThreadLocale( m_lcid ) == FALSE )
  683. {
  684. DWORD sc = TW32( GetLastError() );
  685. // If SetThreadLocale() fails, do not abort. Just log the error.
  686. LogMsg( "[BC] Error 0x%#08x occurred trying to set the thread locale.", sc );
  687. } // if: SetThreadLocale() failed
  688. // Has this action already been committed?
  689. if ( FIsCommitComplete() )
  690. {
  691. SendStatusReport(
  692. TASKID_Major_Configure_Cluster_Services
  693. , TASKID_Minor_Commit_Already_Complete
  694. , 0
  695. , 1
  696. , 1
  697. , HRESULT_FROM_WIN32( TW32( ERROR_CLUSCFG_ALREADY_COMMITTED ) )
  698. , IDS_ERROR_COMMIT_ALREADY_COMPLETE
  699. , true
  700. );
  701. LogMsg( "[BC] The desired cluster configuration has already been performed." );
  702. hrRetVal = HRESULT_FROM_WIN32( TW32( ERROR_CLUSCFG_ALREADY_COMMITTED ) );
  703. goto Cleanup;
  704. } // if: already committed
  705. // Check if the arguments to commit have been set.
  706. if ( m_spbcaCurrentAction.FIsEmpty() )
  707. {
  708. LogMsg( "[BC] Commit was called when an operation has not been specified." );
  709. hrRetVal = THR( E_INVALIDARG ); // BUGBUG: 29-JAN-2001 DavidP Replace E_INVALIDARG
  710. goto Cleanup;
  711. } // if: the pointer to the action to be committed is NULL
  712. LogMsg( "[BC] About to perform the desired cluster configuration." );
  713. // Commit the desired action.
  714. try
  715. {
  716. m_spbcaCurrentAction->Commit();
  717. LogMsg( "[BC] Cluster configuration completed successfully." );
  718. // If we are here, then everything has gone well.
  719. SetCommitCompleted( true );
  720. } // try: to commit the desired action.
  721. catch( CAssert & raExceptionObject )
  722. {
  723. // Process the exception.
  724. hrRetVal = THR( HrProcessException( raExceptionObject ) );
  725. } // catch( CAssert & )
  726. catch( CExceptionWithString & resExceptionObject )
  727. {
  728. // Process the exception.
  729. hrRetVal = THR( HrProcessException( resExceptionObject ) );
  730. } // catch( CExceptionWithString & )
  731. catch( CException & reExceptionObject )
  732. {
  733. // Process the exception.
  734. hrRetVal = THR( HrProcessException( reExceptionObject ) );
  735. } // catch( CException & )
  736. catch( ... )
  737. {
  738. // Catch everything. Do not let any exceptions pass out of this function.
  739. hrRetVal = THR( HrProcessException() );
  740. } // catch all
  741. Cleanup:
  742. HRETURN( hrRetVal );
  743. } //*** CBCAInterface::Commit
  744. //////////////////////////////////////////////////////////////////////////////
  745. //++
  746. //
  747. // STDMETHODIMP
  748. // CBCAInterface::Rollback( void )
  749. //
  750. // Description:
  751. // Rollback a committed configuration.
  752. //
  753. // Arguments:
  754. // None.
  755. //
  756. // Return Value:
  757. // S_OK
  758. // If the call succeeded
  759. //
  760. // E_PENDING
  761. // If this action has not yet been committed successfully.
  762. //
  763. // HRESULT_FROM_WIN32( ERROR_CLUSCFG_ROLLBACK_FAILED )
  764. // If this action cannot be rolled back.
  765. //
  766. // E_INVALIDARG
  767. // If no action has been set using a SetXXX call.
  768. //
  769. // Other HRESULTs
  770. // If the call failed.
  771. //
  772. // Remarks:
  773. // None.
  774. //
  775. //--
  776. //////////////////////////////////////////////////////////////////////////////
  777. STDMETHODIMP
  778. CBCAInterface::Rollback( void )
  779. {
  780. TraceFunc( "[IClusCfgCallback]" );
  781. HRESULT hrRetVal = S_OK;
  782. // Check if this action list has completed successfully.
  783. if ( ! FIsCommitComplete() )
  784. {
  785. // Cannot rollback an incomplete action.
  786. SendStatusReport(
  787. TASKID_Major_Configure_Cluster_Services
  788. , TASKID_Minor_Rollback_Failed_Incomplete_Commit
  789. , 0
  790. , 1
  791. , 1
  792. , E_PENDING
  793. , IDS_ERROR_ROLLBACK_FAILED_INCOMPLETE_COMMIT
  794. , true
  795. );
  796. LogMsg( "[BC] Cannot rollback - action not yet committed." );
  797. hrRetVal = THR( E_PENDING );
  798. goto Cleanup;
  799. } // if: this action was not completed successfully
  800. // Check if this action can be rolled back.
  801. if ( ! FIsRollbackPossible() )
  802. {
  803. // Cannot rollback an incompleted action.
  804. SendStatusReport(
  805. TASKID_Major_Configure_Cluster_Services
  806. , TASKID_Minor_Rollback_Not_Possible
  807. , 0
  808. , 1
  809. , 1
  810. , HRESULT_FROM_WIN32( ERROR_CLUSCFG_ROLLBACK_FAILED )
  811. , IDS_ERROR_ROLLBACK_NOT_POSSIBLE
  812. , true
  813. );
  814. LogMsg( "[BC] This action cannot be rolled back." ); // BUGBUG: 29-JAN-2001 DavidP Why?
  815. hrRetVal = HRESULT_FROM_WIN32( TW32( ERROR_CLUSCFG_ROLLBACK_FAILED ) );
  816. goto Cleanup;
  817. } // if: this action was not completed successfully
  818. // Check if the arguments to rollback have been set.
  819. if ( m_spbcaCurrentAction.FIsEmpty() )
  820. {
  821. LogMsg( "[BC] Rollback was called when an operation has not been specified." );
  822. hrRetVal = THR( E_INVALIDARG ); // BUGBUG: 29-JAN-2001 DavidP Replace E_INVALIDARG
  823. goto Cleanup;
  824. } // if: the pointer to the action to be committed is NULL
  825. LogMsg( "[BC] About to rollback the cluster configuration just committed." );
  826. // Commit the desired action.
  827. try
  828. {
  829. m_spbcaCurrentAction->Rollback();
  830. LogMsg( "[BC] Cluster configuration rolled back." );
  831. // If we are here, then everything has gone well.
  832. SetCommitCompleted( false );
  833. } // try: to rollback the desired action.
  834. catch( CAssert & raExceptionObject )
  835. {
  836. // Process the exception.
  837. hrRetVal = THR( HrProcessException( raExceptionObject ) );
  838. } // catch( CAssert & )
  839. catch( CExceptionWithString & resExceptionObject )
  840. {
  841. // Process the exception.
  842. hrRetVal = THR( HrProcessException( resExceptionObject ) );
  843. } // catch( CExceptionWithString & )
  844. catch( CException & reExceptionObject )
  845. {
  846. // Process the exception.
  847. hrRetVal = THR( HrProcessException( reExceptionObject ) );
  848. } // catch( CException & )
  849. catch( ... )
  850. {
  851. // Catch everything. Do not let any exceptions pass out of this function.
  852. hrRetVal = THR( HrProcessException() );
  853. } // catch all
  854. Cleanup:
  855. HRETURN( hrRetVal );
  856. } //*** CBCAInterface::Rollback
  857. //////////////////////////////////////////////////////////////////////////////
  858. //++
  859. //
  860. // CBCAInterface::SendStatusReport
  861. //
  862. // Description:
  863. // Send a progress notification [ string id overload ].
  864. //
  865. // Arguments:
  866. // clsidTaskMajorIn
  867. // clsidTaskMinorIn
  868. // GUIDs identifying the notification.
  869. //
  870. // ulMinIn
  871. // ulMaxIn
  872. // ulCurrentIn
  873. // Values that indicate the percentage of this task that is
  874. // completed.
  875. //
  876. // hrStatusIn
  877. // Error code.
  878. //
  879. // uiDescriptionStringIdIn
  880. // String ID of the description of the notification.
  881. //
  882. // fIsAbortAllowedIn
  883. //
  884. // Return Value:
  885. // None.
  886. //
  887. // Exceptions Thrown:
  888. // CRuntimeError
  889. // If any of the APIs fail.
  890. //
  891. // CAbortException
  892. // If the configuration was aborted.
  893. //
  894. // Remarks:
  895. // In the current implementation, IClusCfgCallback::SendStatusReport
  896. // returns E_ABORT to indicate that the user wants to abort
  897. // the cluster configuration.
  898. //--
  899. //////////////////////////////////////////////////////////////////////////////
  900. void
  901. CBCAInterface::SendStatusReport(
  902. const CLSID & clsidTaskMajorIn
  903. , const CLSID & clsidTaskMinorIn
  904. , ULONG ulMinIn
  905. , ULONG ulMaxIn
  906. , ULONG ulCurrentIn
  907. , HRESULT hrStatusIn
  908. , UINT uiDescriptionStringIdIn
  909. , bool fIsAbortAllowedIn // = true
  910. )
  911. {
  912. TraceFunc( "uiDescriptionStringIdIn" );
  913. if ( FIsCallbackSupported() )
  914. {
  915. CStr strDescription;
  916. // Lookup the string using the string Id.
  917. strDescription.LoadString( g_hInstance, uiDescriptionStringIdIn );
  918. // Send progress notification ( call the overloaded function )
  919. SendStatusReport(
  920. clsidTaskMajorIn
  921. , clsidTaskMinorIn
  922. , ulMinIn
  923. , ulMaxIn
  924. , ulCurrentIn
  925. , hrStatusIn
  926. , strDescription.PszData()
  927. , fIsAbortAllowedIn
  928. );
  929. } // if: callbacks are supported
  930. else
  931. {
  932. LogMsg( "[BC] Callbacks are not supported. No status report will be sent." );
  933. } // else: callbacks are not supported
  934. TraceFuncExit();
  935. } //*** CBCAInterface::SendStatusReport
  936. //////////////////////////////////////////////////////////////////////////////
  937. //++
  938. //
  939. // CBCAInterface::SendStatusReport
  940. //
  941. // Description:
  942. // Send a progress notification [ string id & REF string id overload ].
  943. //
  944. // Arguments:
  945. // clsidTaskMajorIn
  946. // clsidTaskMinorIn
  947. // GUIDs identifying the notification.
  948. //
  949. // ulMinIn
  950. // ulMaxIn
  951. // ulCurrentIn
  952. // Values that indicate the percentage of this task that is
  953. // completed.
  954. //
  955. // hrStatusIn
  956. // Error code.
  957. //
  958. // uiDescriptionStringIdIn
  959. // String ID of the description of the notification.
  960. //
  961. // uiDescriptionRefStringIdIn
  962. // REF String ID of the description of the notification.
  963. //
  964. // fIsAbortAllowedIn
  965. //
  966. // Return Value:
  967. // None.
  968. //
  969. // Exceptions Thrown:
  970. // CRuntimeError
  971. // If any of the APIs fail.
  972. //
  973. // CAbortException
  974. // If the configuration was aborted.
  975. //
  976. // Remarks:
  977. // In the current implementation, IClusCfgCallback::SendStatusReport
  978. // returns E_ABORT to indicate that the user wants to abort
  979. // the cluster configuration.
  980. //--
  981. //////////////////////////////////////////////////////////////////////////////
  982. void
  983. CBCAInterface::SendStatusReport(
  984. const CLSID & clsidTaskMajorIn
  985. , const CLSID & clsidTaskMinorIn
  986. , ULONG ulMinIn
  987. , ULONG ulMaxIn
  988. , ULONG ulCurrentIn
  989. , HRESULT hrStatusIn
  990. , UINT uiDescriptionStringIdIn
  991. , UINT uiDescriptionRefStringIdIn
  992. , bool fIsAbortAllowedIn // = true
  993. )
  994. {
  995. TraceFunc( "uiDescriptionStringIdIn" );
  996. if ( FIsCallbackSupported() )
  997. {
  998. CStr strDescription;
  999. // Lookup the string using the string Id.
  1000. strDescription.LoadString( g_hInstance, uiDescriptionStringIdIn );
  1001. if ( uiDescriptionRefStringIdIn == 0 )
  1002. {
  1003. // Send progress notification ( call the overloaded function )
  1004. SendStatusReport(
  1005. clsidTaskMajorIn
  1006. , clsidTaskMinorIn
  1007. , ulMinIn
  1008. , ulMaxIn
  1009. , ulCurrentIn
  1010. , hrStatusIn
  1011. , strDescription.PszData()
  1012. , fIsAbortAllowedIn
  1013. );
  1014. }
  1015. else
  1016. {
  1017. CStr strDescriptionRef;
  1018. // Lookup the string using the Ref string Id.
  1019. strDescriptionRef.LoadString( g_hInstance, uiDescriptionRefStringIdIn );
  1020. // Send progress notification ( call the overloaded function )
  1021. SendStatusReport(
  1022. clsidTaskMajorIn
  1023. , clsidTaskMinorIn
  1024. , ulMinIn
  1025. , ulMaxIn
  1026. , ulCurrentIn
  1027. , hrStatusIn
  1028. , strDescription.PszData()
  1029. , strDescriptionRef.PszData()
  1030. , fIsAbortAllowedIn
  1031. );
  1032. }
  1033. } // if: callbacks are supported
  1034. else
  1035. {
  1036. LogMsg( "[BC] Callbacks are not supported. No status report will be sent." );
  1037. } // else: callbacks are not supported
  1038. TraceFuncExit();
  1039. } //*** CBCAInterface::SendStatusReport
  1040. //////////////////////////////////////////////////////////////////////////////
  1041. //++
  1042. //
  1043. // CBCAInterface::SendStatusReport
  1044. //
  1045. // Description:
  1046. // Send a progress notification [ string overload ].
  1047. //
  1048. // Arguments:
  1049. // clsidTaskMajorIn
  1050. // clsidTaskMinorIn
  1051. // GUIDs identifying the notification.
  1052. //
  1053. // ulMinIn
  1054. // ulMaxIn
  1055. // ulCurrentIn
  1056. // Values that indicate the percentage of this task that is
  1057. // completed.
  1058. //
  1059. // hrStatusIn
  1060. // Error code.
  1061. //
  1062. // pcszDescriptionStringIn
  1063. // String ID of the description of the notification.
  1064. //
  1065. // fIsAbortAllowedIn
  1066. // An optional parameter indicating if this configuration step can
  1067. // be aborted or not. Default value is true.
  1068. //
  1069. // Return Value:
  1070. // None.
  1071. //
  1072. // Exceptions Thrown:
  1073. // CRuntimeError
  1074. // If any of the APIs fail.
  1075. //
  1076. // CAbortException
  1077. // If the configuration was aborted.
  1078. //
  1079. // Remarks:
  1080. // In the current implementation, IClusCfgCallback::SendStatusReport
  1081. // returns E_ABORT to indicate that the user wants to abort
  1082. // the cluster configuration.
  1083. //--
  1084. //////////////////////////////////////////////////////////////////////////////
  1085. void
  1086. CBCAInterface::SendStatusReport(
  1087. const CLSID & clsidTaskMajorIn
  1088. , const CLSID & clsidTaskMinorIn
  1089. , ULONG ulMinIn
  1090. , ULONG ulMaxIn
  1091. , ULONG ulCurrentIn
  1092. , HRESULT hrStatusIn
  1093. , const WCHAR * pcszDescriptionStringIn
  1094. , bool fIsAbortAllowedIn // = true
  1095. )
  1096. {
  1097. TraceFunc1( "pcszDescriptionStringIn = '%ws'", pcszDescriptionStringIn );
  1098. HRESULT hrRetVal = S_OK;
  1099. FILETIME ft;
  1100. if ( !FIsCallbackSupported() )
  1101. {
  1102. // Nothing needs to be done.
  1103. goto Cleanup;
  1104. } // if: callbacks are not supported
  1105. GetSystemTimeAsFileTime( &ft );
  1106. // Send progress notification
  1107. hrRetVal = THR(
  1108. m_spcbCallback->SendStatusReport(
  1109. NULL
  1110. , clsidTaskMajorIn
  1111. , clsidTaskMinorIn
  1112. , ulMinIn
  1113. , ulMaxIn
  1114. , ulCurrentIn
  1115. , hrStatusIn
  1116. , pcszDescriptionStringIn
  1117. , &ft
  1118. , NULL
  1119. )
  1120. );
  1121. // Has the user requested an abort?
  1122. if ( hrRetVal == E_ABORT )
  1123. {
  1124. LogMsg( "[BC] A request to abort the configuration has been recieved." );
  1125. if ( fIsAbortAllowedIn )
  1126. {
  1127. LogMsg( "[BC] Configuration will be aborted." );
  1128. THROW_ABORT( E_ABORT, IDS_USER_ABORT );
  1129. } // if: this operation can be aborted
  1130. else
  1131. {
  1132. LogMsg( "[BC] This configuration operation cannot be aborted. Request will be ignored." );
  1133. } // else: this operation cannot be aborted
  1134. } // if: the user has indicated that that configuration should be aborted
  1135. else
  1136. {
  1137. if ( FAILED( hrRetVal ) )
  1138. {
  1139. LogMsg( "[BC] Error 0x%#08x has occurred - no more status messages will be sent.", hrRetVal );
  1140. // Disable all further callbacks.
  1141. SetCallbackSupported( false );
  1142. } // if: something went wrong trying to send a status report
  1143. } // else: abort was not requested
  1144. Cleanup:
  1145. if ( FAILED( hrRetVal ) )
  1146. {
  1147. LogMsg( "[BC] Error 0x%#08x occurred trying send a status message. Throwing an exception.", hrRetVal );
  1148. THROW_RUNTIME_ERROR( hrRetVal, IDS_ERROR_SENDING_REPORT );
  1149. } // if: an error occurred
  1150. TraceFuncExit();
  1151. } //*** CBCAInterface::SendStatusReport
  1152. //////////////////////////////////////////////////////////////////////////////
  1153. //++
  1154. //
  1155. // CBCAInterface::SendStatusReport
  1156. //
  1157. // Description:
  1158. // Send a progress notification [ string & REF string overload ].
  1159. //
  1160. // Arguments:
  1161. // clsidTaskMajorIn
  1162. // clsidTaskMinorIn
  1163. // GUIDs identifying the notification.
  1164. //
  1165. // ulMinIn
  1166. // ulMaxIn
  1167. // ulCurrentIn
  1168. // Values that indicate the percentage of this task that is
  1169. // completed.
  1170. //
  1171. // hrStatusIn
  1172. // Error code.
  1173. //
  1174. // pcszDescriptionStringIn
  1175. // String ID of the description of the notification.
  1176. //
  1177. // pcszDescriptionRefStringIn
  1178. // REF String ID of the description of the notification.
  1179. //
  1180. // fIsAbortAllowedIn
  1181. // An optional parameter indicating if this configuration step can
  1182. // be aborted or not. Default value is true.
  1183. //
  1184. // Return Value:
  1185. // None.
  1186. //
  1187. // Exceptions Thrown:
  1188. // CRuntimeError
  1189. // If any of the APIs fail.
  1190. //
  1191. // CAbortException
  1192. // If the configuration was aborted.
  1193. //
  1194. // Remarks:
  1195. // In the current implementation, IClusCfgCallback::SendStatusReport
  1196. // returns E_ABORT to indicate that the user wants to abort
  1197. // the cluster configuration.
  1198. //--
  1199. //////////////////////////////////////////////////////////////////////////////
  1200. void
  1201. CBCAInterface::SendStatusReport(
  1202. const CLSID & clsidTaskMajorIn
  1203. , const CLSID & clsidTaskMinorIn
  1204. , ULONG ulMinIn
  1205. , ULONG ulMaxIn
  1206. , ULONG ulCurrentIn
  1207. , HRESULT hrStatusIn
  1208. , const WCHAR * pcszDescriptionStringIn
  1209. , const WCHAR * pcszDescriptionRefStringIn
  1210. , bool fIsAbortAllowedIn // = true
  1211. )
  1212. {
  1213. TraceFunc1( "pcszDescriptionRefStringIn = '%ws'", pcszDescriptionRefStringIn );
  1214. HRESULT hrRetVal = S_OK;
  1215. FILETIME ft;
  1216. if ( !FIsCallbackSupported() )
  1217. {
  1218. // Nothing needs to be done.
  1219. goto Cleanup;
  1220. } // if: callbacks are not supported
  1221. GetSystemTimeAsFileTime( &ft );
  1222. // Send progress notification
  1223. hrRetVal = THR(
  1224. m_spcbCallback->SendStatusReport(
  1225. NULL
  1226. , clsidTaskMajorIn
  1227. , clsidTaskMinorIn
  1228. , ulMinIn
  1229. , ulMaxIn
  1230. , ulCurrentIn
  1231. , hrStatusIn
  1232. , pcszDescriptionStringIn
  1233. , &ft
  1234. , pcszDescriptionRefStringIn
  1235. )
  1236. );
  1237. // Has the user requested an abort?
  1238. if ( hrRetVal == E_ABORT )
  1239. {
  1240. LogMsg( "[BC] A request to abort the configuration has been recieved." );
  1241. if ( fIsAbortAllowedIn )
  1242. {
  1243. LogMsg( "[BC] Configuration will be aborted." );
  1244. THROW_ABORT( E_ABORT, IDS_USER_ABORT );
  1245. } // if: this operation can be aborted
  1246. else
  1247. {
  1248. LogMsg( "[BC] This configuration operation cannot be aborted. Request will be ignored." );
  1249. } // else: this operation cannot be aborted
  1250. } // if: the user has indicated that that configuration should be aborted
  1251. else
  1252. {
  1253. if ( FAILED( hrRetVal ) )
  1254. {
  1255. LogMsg( "[BC] Error 0x%#08x has occurred - no more status messages will be sent.", hrRetVal );
  1256. // Disable all further callbacks.
  1257. SetCallbackSupported( false );
  1258. } // if: something went wrong trying to send a status report
  1259. } // else: abort was not requested
  1260. Cleanup:
  1261. if ( FAILED( hrRetVal ) )
  1262. {
  1263. LogMsg( "[BC] Error 0x%#08x occurred trying send a status message. Throwing an exception.", hrRetVal );
  1264. THROW_RUNTIME_ERROR( hrRetVal, IDS_ERROR_SENDING_REPORT );
  1265. } // if: an error occurred
  1266. TraceFuncExit();
  1267. } //*** CBCAInterface::SendStatusReport
  1268. //////////////////////////////////////////////////////////////////////////////
  1269. //++
  1270. //
  1271. // CBCAInterface::QueueStatusReportCompletion
  1272. //
  1273. // Description:
  1274. // Queue a status report for sending when an exception is caught.
  1275. //
  1276. // Arguments:
  1277. // clsidTaskMajorIn
  1278. // clsidTaskMinorIn
  1279. // GUIDs identifying the notification.
  1280. //
  1281. // ulMinIn
  1282. // ulMaxIn
  1283. // Values that indicate the range of steps for this report.
  1284. //
  1285. // uiDescriptionStringIdIn
  1286. // String ID of the description of the notification.
  1287. //
  1288. // uiReferenceStringIdIn
  1289. // Reference string ID of the description of the notification.
  1290. //
  1291. // Return Value:
  1292. // None.
  1293. //
  1294. // Exceptions Thrown:
  1295. // Any thrown by CList::Append()
  1296. //--
  1297. //////////////////////////////////////////////////////////////////////////////
  1298. void
  1299. CBCAInterface::QueueStatusReportCompletion(
  1300. const CLSID & clsidTaskMajorIn
  1301. , const CLSID & clsidTaskMinorIn
  1302. , ULONG ulMinIn
  1303. , ULONG ulMaxIn
  1304. , UINT uiDescriptionStringIdIn
  1305. , UINT uiReferenceStringIdIn
  1306. )
  1307. {
  1308. TraceFunc( "" );
  1309. // Queue the status report only if callbacks are supported.
  1310. if ( m_fCallbackSupported )
  1311. {
  1312. // Append this status report to the end of the pending list.
  1313. m_prlPendingReportList.Append(
  1314. SPendingStatusReport(
  1315. clsidTaskMajorIn
  1316. , clsidTaskMinorIn
  1317. , ulMinIn
  1318. , ulMaxIn
  1319. , uiDescriptionStringIdIn
  1320. , uiReferenceStringIdIn
  1321. )
  1322. );
  1323. }
  1324. TraceFuncExit();
  1325. } //*** CBCAInterface::QueueStatusReportCompletion
  1326. //////////////////////////////////////////////////////////////////////////////
  1327. //++
  1328. //
  1329. // CBCAInterface::CompletePendingStatusReports
  1330. //
  1331. // Description:
  1332. // Send all the status reports that were queued for sending when an
  1333. // exception occurred. This function is meant to be called from an exception
  1334. // handler when an exception is caught.
  1335. //
  1336. // Arguments:
  1337. // hrStatusIn
  1338. // The error code to be sent with the pending status reports.
  1339. //
  1340. // Return Value:
  1341. // None.
  1342. //
  1343. // Exceptions Thrown:
  1344. // None, since this function is usually called in an exception handler.
  1345. //
  1346. //--
  1347. //////////////////////////////////////////////////////////////////////////////
  1348. void
  1349. CBCAInterface::CompletePendingStatusReports(
  1350. HRESULT hrStatusIn
  1351. ) throw()
  1352. {
  1353. TraceFunc( "" );
  1354. if ( m_fCallbackSupported )
  1355. {
  1356. try
  1357. {
  1358. PendingReportList::CIterator ciCurrent = m_prlPendingReportList.CiBegin();
  1359. PendingReportList::CIterator ciLast = m_prlPendingReportList.CiEnd();
  1360. // Iterate through the list of pending status reports and send each pending report.
  1361. while ( ciCurrent != ciLast )
  1362. {
  1363. // Send the current status report.
  1364. SendStatusReport(
  1365. ciCurrent->m_clsidTaskMajor
  1366. , ciCurrent->m_clsidTaskMinor
  1367. , ciCurrent->m_ulMin
  1368. , ciCurrent->m_ulMax
  1369. , ciCurrent->m_ulMax
  1370. , hrStatusIn
  1371. , ciCurrent->m_uiDescriptionStringId
  1372. , ciCurrent->m_uiReferenceStringId
  1373. , false
  1374. );
  1375. // Move to the next one.
  1376. m_prlPendingReportList.DeleteAndMoveToNext( ciCurrent );
  1377. } // while: the pending status report list is not empty
  1378. } // try: to send status report
  1379. catch( ... )
  1380. {
  1381. THR( E_UNEXPECTED );
  1382. // Nothing can be done here if the sending of the status report fails.
  1383. LogMsg( "[BC] An unexpected error has occurred trying to complete pending status messages. It will not be propagated." );
  1384. } // catch: all exceptions
  1385. } // if: callbacks are supported
  1386. // Empty the pending status report list.
  1387. m_prlPendingReportList.Empty();
  1388. TraceFuncExit();
  1389. } //*** CBCAInterface::CompletePendingStatusReports
  1390. //////////////////////////////////////////////////////////////////////////////
  1391. //++
  1392. //
  1393. // CBCAInterface::HrProcessException
  1394. //
  1395. // Description:
  1396. // Process an exception that should be shown to the user.
  1397. //
  1398. // Arguments:
  1399. // CExceptionWithString & resExceptionObjectInOut
  1400. // The exception object that has been caught.
  1401. //
  1402. // Return Value:
  1403. // The error code stored in the exception object.
  1404. //
  1405. // Exceptions Thrown:
  1406. // None.
  1407. //
  1408. //--
  1409. //////////////////////////////////////////////////////////////////////////////
  1410. HRESULT
  1411. CBCAInterface::HrProcessException(
  1412. CExceptionWithString & resExceptionObjectInOut
  1413. ) throw()
  1414. {
  1415. TraceFunc( "resExceptionObjectInOut" );
  1416. LogMsg(
  1417. TEXT("[BC] A runtime error has occurred in file '%s', line %d. Error code is %#08x.") SZ_NEWLINE
  1418. TEXT(" The error string is '%s'.")
  1419. , resExceptionObjectInOut.PszGetThrowingFile()
  1420. , resExceptionObjectInOut.UiGetThrowingLine()
  1421. , resExceptionObjectInOut.HrGetErrorCode()
  1422. , resExceptionObjectInOut.StrGetErrorString().PszData()
  1423. );
  1424. // If the user has not been notified
  1425. if ( ! resExceptionObjectInOut.FHasUserBeenNotified() )
  1426. {
  1427. try
  1428. {
  1429. SendStatusReport(
  1430. TASKID_Major_Configure_Cluster_Services
  1431. , TASKID_Minor_Rolling_Back_Cluster_Configuration
  1432. , 1, 1, 1
  1433. , resExceptionObjectInOut.HrGetErrorCode()
  1434. , resExceptionObjectInOut.StrGetErrorString().PszData()
  1435. , resExceptionObjectInOut.StrGetErrorRefString().PszData()
  1436. , false // fIsAbortAllowedIn
  1437. );
  1438. resExceptionObjectInOut.SetUserNotified();
  1439. } // try: to send status report
  1440. catch( ... )
  1441. {
  1442. THR( E_UNEXPECTED );
  1443. // Nothing can be done here if the sending of the status report fails.
  1444. LogMsg( "[BC] An unexpected error has occurred trying to send a progress notification. It will not be propagated." );
  1445. } // catch: all exceptions
  1446. } // if: the user has not been notified of this exception
  1447. // Complete sending pending status reports.
  1448. CompletePendingStatusReports( resExceptionObjectInOut.HrGetErrorCode() );
  1449. HRETURN( resExceptionObjectInOut.HrGetErrorCode() );
  1450. } //*** CBCAInterface::HrProcessException
  1451. //////////////////////////////////////////////////////////////////////////////
  1452. //++
  1453. //
  1454. // CBCAInterface::HrProcessException
  1455. //
  1456. // Description:
  1457. // Process an assert exception.
  1458. //
  1459. // Arguments:
  1460. // const CAssert & rcaExceptionObjectIn
  1461. // The exception object that has been caught.
  1462. //
  1463. // Return Value:
  1464. // The error code stored in the exception object.
  1465. //
  1466. // Exceptions Thrown:
  1467. // None.
  1468. //
  1469. //--
  1470. //////////////////////////////////////////////////////////////////////////////
  1471. HRESULT
  1472. CBCAInterface::HrProcessException(
  1473. const CAssert & rcaExceptionObjectIn
  1474. ) throw()
  1475. {
  1476. TraceFunc( "rcaExceptionObjectIn" );
  1477. LogMsg(
  1478. TEXT("[BC] An assertion has failed in file '%s', line %d. Error code is %#08x.") SZ_NEWLINE
  1479. TEXT(" The error string is '%s'.")
  1480. , rcaExceptionObjectIn.PszGetThrowingFile()
  1481. , rcaExceptionObjectIn.UiGetThrowingLine()
  1482. , rcaExceptionObjectIn.HrGetErrorCode()
  1483. , rcaExceptionObjectIn.StrGetErrorString().PszData()
  1484. );
  1485. // Complete sending pending status reports.
  1486. CompletePendingStatusReports( rcaExceptionObjectIn.HrGetErrorCode() );
  1487. HRETURN( rcaExceptionObjectIn.HrGetErrorCode() );
  1488. } //*** CBCAInterface::HrProcessException
  1489. //////////////////////////////////////////////////////////////////////////////
  1490. //++
  1491. //
  1492. // CBCAInterface::HrProcessException
  1493. //
  1494. // Description:
  1495. // Process a general exception.
  1496. //
  1497. // Arguments:
  1498. // const CException & rceExceptionObjectIn
  1499. // The exception object that has been caught.
  1500. //
  1501. // Return Value:
  1502. // The error code stored in the exception object.
  1503. //
  1504. // Exceptions Thrown:
  1505. // None.
  1506. //
  1507. //--
  1508. //////////////////////////////////////////////////////////////////////////////
  1509. HRESULT
  1510. CBCAInterface::HrProcessException(
  1511. const CException & rceExceptionObjectIn
  1512. ) throw()
  1513. {
  1514. TraceFunc( "roeExceptionObjectIn" );
  1515. LogMsg(
  1516. "[BC] An exception has occurred in file '%s', line %d. Error code is %#08x."
  1517. , rceExceptionObjectIn.PszGetThrowingFile()
  1518. , rceExceptionObjectIn.UiGetThrowingLine()
  1519. , rceExceptionObjectIn.HrGetErrorCode()
  1520. );
  1521. // Complete sending pending status reports.
  1522. CompletePendingStatusReports( rceExceptionObjectIn.HrGetErrorCode() );
  1523. HRETURN( rceExceptionObjectIn.HrGetErrorCode() );
  1524. } //*** CBCAInterface::HrProcessException
  1525. //////////////////////////////////////////////////////////////////////////////
  1526. //++
  1527. //
  1528. // CBCAInterface::HrProcessException
  1529. //
  1530. // Description:
  1531. // Process an unknown exception.
  1532. //
  1533. // Arguments:
  1534. // None.
  1535. //
  1536. // Return Value:
  1537. // E_UNEXPECTED
  1538. //
  1539. // Exceptions Thrown:
  1540. // None.
  1541. //
  1542. //--
  1543. //////////////////////////////////////////////////////////////////////////////
  1544. HRESULT
  1545. CBCAInterface::HrProcessException( void ) throw()
  1546. {
  1547. TraceFunc( "void" );
  1548. HRESULT hr = E_UNEXPECTED;
  1549. LogMsg( "[BC] An unknown exception (for example, an access violation) has occurred." );
  1550. // Complete sending pending status reports.
  1551. CompletePendingStatusReports( hr );
  1552. HRETURN( hr );
  1553. } //*** CBCAInterface::HrProcessException