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.

990 lines
27 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2000-2001 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // StartupNotify.cpp
  7. //
  8. // Description:
  9. // This file contains the implementation of the CStartupNotify
  10. // class.
  11. //
  12. // Maintained By:
  13. // David Potter (DavidP) 14-JUN-2001
  14. // Vij Vasu (VVasu) 15-JUN-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 "StartupNotify.h"
  24. #include "clusrtl.h"
  25. // For IClusCfgNodeInfo and related interfaces
  26. #include <ClusCfgServer.h>
  27. // For IClusCfgServer and related interfaces
  28. #include <ClusCfgPrivate.h>
  29. // For CClCfgSrvLogger
  30. #include <Logger.h>
  31. // For POSTCONFIG_COMPLETE_EVENT_NAME
  32. #include "EventName.h"
  33. //////////////////////////////////////////////////////////////////////////////
  34. // Macro Definitions
  35. //////////////////////////////////////////////////////////////////////////////
  36. DEFINE_THISCLASS( "CStartupNotify" );
  37. //////////////////////////////////////////////////////////////////////////////
  38. //++
  39. //
  40. // CStartupNotify::CStartupNotify
  41. //
  42. // Description:
  43. // Constructor of the CStartupNotify class. This initializes
  44. // the m_cRef variable to 1 instead of 0 to account of possible
  45. // QueryInterface failure in DllGetClassObject.
  46. //
  47. // Arguments:
  48. // None.
  49. //
  50. // Return Value:
  51. // None.
  52. //
  53. // Remarks:
  54. // None.
  55. //
  56. //--
  57. //////////////////////////////////////////////////////////////////////////////
  58. CStartupNotify::CStartupNotify( void )
  59. : m_cRef( 1 )
  60. {
  61. TraceFunc( "" );
  62. m_bstrNodeName = NULL;
  63. m_plLogger = NULL;
  64. // Increment the count of components in memory so the DLL hosting this
  65. // object cannot be unloaded.
  66. InterlockedIncrement( &g_cObjects );
  67. TraceFlow1( "Component count = %d.", g_cObjects );
  68. TraceFuncExit();
  69. } //*** CStartupNotify::CStartupNotify
  70. //////////////////////////////////////////////////////////////////////////////
  71. //++
  72. //
  73. // CStartupNotify::~CStartupNotify
  74. //
  75. // Description:
  76. // Destructor of the CStartupNotify class.
  77. //
  78. // Arguments:
  79. // None.
  80. //
  81. // Return Value:
  82. // None.
  83. //
  84. // Remarks:
  85. // None.
  86. //
  87. //--
  88. //////////////////////////////////////////////////////////////////////////////
  89. CStartupNotify::~CStartupNotify( void )
  90. {
  91. TraceFunc( "" );
  92. if ( m_plLogger != NULL )
  93. {
  94. m_plLogger->Release();
  95. } // if:
  96. TraceSysFreeString( m_bstrNodeName );
  97. // There's going to be one less component in memory. Decrement component count.
  98. InterlockedDecrement( &g_cObjects );
  99. TraceFlow1( "Component count = %d.", g_cObjects );
  100. TraceFuncExit();
  101. } //*** CStartupNotify::~CStartupNotify
  102. //////////////////////////////////////////////////////////////////////////////
  103. //++
  104. //
  105. // HRESULT
  106. // CStartupNotify::S_HrCreateInstance(
  107. // IUnknown ** ppunkOut
  108. // )
  109. //
  110. // Description:
  111. // Creates a CStartupNotify instance.
  112. //
  113. // Arguments:
  114. // ppunkOut
  115. // The IUnknown interface of the new object.
  116. //
  117. // Return Values:
  118. // S_OK
  119. // Success.
  120. //
  121. // E_OUTOFMEMORY
  122. // Not enough memory to create the object.
  123. //
  124. // other HRESULTs
  125. // Object initialization failed.
  126. //
  127. //--
  128. //////////////////////////////////////////////////////////////////////////////
  129. HRESULT
  130. CStartupNotify::S_HrCreateInstance( IUnknown ** ppunkOut )
  131. {
  132. TraceFunc( "" );
  133. HRESULT hr = S_OK;
  134. CStartupNotify * pStartupNotify = NULL;
  135. Assert( ppunkOut != NULL );
  136. if ( ppunkOut == NULL )
  137. {
  138. hr = THR( E_POINTER );
  139. goto Cleanup;
  140. }
  141. // Allocate memory for the new object.
  142. pStartupNotify = new CStartupNotify();
  143. if ( pStartupNotify == NULL )
  144. {
  145. hr = THR( E_OUTOFMEMORY );
  146. goto Cleanup;
  147. } // if: out of memory
  148. // Initialize the new object.
  149. hr = THR( pStartupNotify->HrInit() );
  150. if ( FAILED( hr ) )
  151. {
  152. goto Cleanup;
  153. } // if: the object could not be initialized.
  154. hr = THR( pStartupNotify->QueryInterface( IID_IUnknown, reinterpret_cast< void ** >( ppunkOut ) ) );
  155. if ( FAILED( hr ) )
  156. {
  157. goto Cleanup;
  158. }
  159. Cleanup:
  160. if ( pStartupNotify != NULL )
  161. {
  162. pStartupNotify->Release();
  163. } // if: the pointer to the notification object is not NULL
  164. HRETURN( hr );
  165. } //*** CStartupNotify::S_HrCreateInstance
  166. //////////////////////////////////////////////////////////////////////////////
  167. //++
  168. //
  169. // CStartupNotify::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. CStartupNotify::AddRef( void )
  187. {
  188. TraceFunc( "[IUnknown]" );
  189. InterlockedIncrement( &m_cRef );
  190. CRETURN( m_cRef );
  191. } //*** CStartupNotify::AddRef
  192. //////////////////////////////////////////////////////////////////////////////
  193. //++
  194. //
  195. // CStartupNotify::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. CStartupNotify::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. } //*** CStartupNotify::Release
  223. //////////////////////////////////////////////////////////////////////////////
  224. //++
  225. //
  226. // CStartupNotify::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. // ppvOut was NULL.
  247. //
  248. // Remarks:
  249. // None.
  250. //
  251. //--
  252. //////////////////////////////////////////////////////////////////////////////
  253. STDMETHODIMP
  254. CStartupNotify::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< IClusCfgStartupNotify * >( this );
  276. } // if: IUnknown
  277. else if ( IsEqualIID( riidIn, IID_IClusCfgStartupNotify ) )
  278. {
  279. *ppvOut = TraceInterface( __THISCLASS__, IClusCfgStartupNotify, this, 0 );
  280. } // else if: IClusCfgStartupNotify
  281. else if ( IsEqualIID( riidIn, IID_IClusCfgCallback ) )
  282. {
  283. *ppvOut = TraceInterface( __THISCLASS__, IClusCfgCallback, this, 0 );
  284. } // else if: IClusCfgCallback
  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. } //*** CStartupNotify::QueryInterface
  300. //////////////////////////////////////////////////////////////////////////////
  301. //++
  302. //
  303. // CStartupNotify::HrInit
  304. //
  305. // Description:
  306. // Second phase of a two phase constructor.
  307. //
  308. // Arguments:
  309. // None.
  310. //
  311. // Return Value:
  312. // S_OK
  313. // If the call succeeded
  314. //
  315. // Other HRESULTs
  316. // If the call failed.
  317. //
  318. //--
  319. //////////////////////////////////////////////////////////////////////////////
  320. HRESULT
  321. CStartupNotify::HrInit( void )
  322. {
  323. TraceFunc( "" );
  324. HRESULT hr = S_OK;
  325. IServiceProvider * psp = NULL;
  326. ILogManager * plm = NULL;
  327. // IUnknown
  328. Assert( m_cRef == 1 );
  329. //
  330. // Get a ClCfgSrv ILogger instance.
  331. //
  332. hr = THR( CoCreateInstance(
  333. CLSID_ServiceManager
  334. , NULL
  335. , CLSCTX_INPROC_SERVER
  336. , IID_IServiceProvider
  337. , reinterpret_cast< void ** >( &psp )
  338. ) );
  339. if ( FAILED( hr ) )
  340. {
  341. goto Cleanup;
  342. }
  343. hr = THR( psp->TypeSafeQS( CLSID_LogManager, ILogManager, &plm ) );
  344. if ( FAILED( hr ) )
  345. {
  346. goto Cleanup;
  347. }
  348. hr = THR( plm->GetLogger( &m_plLogger ) );
  349. if ( FAILED( hr ) )
  350. {
  351. goto Cleanup;
  352. }
  353. //
  354. // Save off the local computer name.
  355. // If we can't get the fully-qualified name, just get the NetBIOS name.
  356. //
  357. hr = THR( HrGetComputerName(
  358. ComputerNameDnsFullyQualified
  359. , &m_bstrNodeName
  360. , TRUE // fBestEffortIn
  361. ) );
  362. if ( FAILED( hr ) )
  363. {
  364. THR( hr );
  365. LogMsg( L"[SN] An error occurred trying to get the fully-qualified Dns name for the local machine during initialization. Status code is= %1!#08x!.", hr );
  366. goto Cleanup;
  367. } // if: error occurred getting computer name
  368. Cleanup:
  369. if ( psp != NULL )
  370. {
  371. psp->Release();
  372. }
  373. if ( plm != NULL )
  374. {
  375. plm->Release();
  376. }
  377. HRETURN( hr );
  378. } //*** CStartupNotify::HrInit
  379. //////////////////////////////////////////////////////////////////////////////
  380. //++
  381. //
  382. // CStartupNotify::SendNotifications
  383. //
  384. // Description:
  385. // This method is called by the Cluster Service to inform the implementor
  386. // of this interface to send out notification of cluster service startup
  387. // to interested listeners. If this method is being called for the first
  388. // time, the method waits till the post configuration steps are complete
  389. // before sending out the notifications.
  390. //
  391. // Arguments:
  392. // None.
  393. //
  394. // Return Values:
  395. // S_OK
  396. // Success.
  397. //
  398. // Other HRESULTs
  399. // The call failed.
  400. //
  401. //--
  402. //////////////////////////////////////////////////////////////////////////////
  403. STDMETHODIMP
  404. CStartupNotify::SendNotifications( void )
  405. {
  406. TraceFunc( "[IClusCfgStartupNotify]" );
  407. HRESULT hr = S_OK;
  408. HANDLE heventPostCfgCompletion = NULL;
  409. //
  410. // If the cluster service is being started for the first time, as a part
  411. // of adding this node to a cluster (forming or joining), then we have
  412. // to wait till the post-configuration steps are completed before we
  413. // can send out notifications.
  414. //
  415. LogMsg( "[SN] Trying to create an event named '%s'.", POSTCONFIG_COMPLETE_EVENT_NAME );
  416. // Create an event in the signalled state. If this event already existed
  417. // we get a handle to that event, and the state of the event is not changed.
  418. heventPostCfgCompletion = CreateEvent(
  419. NULL // event security attributes
  420. , TRUE // manual-reset event
  421. , TRUE // create in signaled state
  422. , POSTCONFIG_COMPLETE_EVENT_NAME
  423. );
  424. if ( heventPostCfgCompletion == NULL )
  425. {
  426. hr = HRESULT_FROM_WIN32( TW32( GetLastError() ) );
  427. LogMsg( "[SN] Error %#08x occurred trying to create an event named '%s'.", hr, POSTCONFIG_COMPLETE_EVENT_NAME );
  428. goto Cleanup;
  429. } // if: we could not get a handle to the event
  430. TraceFlow( "Waiting for the event to be signaled." );
  431. //
  432. // Now, wait for this event to be signaled. If this method was called due to this
  433. // node being part of a cluster, this event would have been created in the unsignaled state
  434. // by the cluster configuration server. However, if this was not the first time that
  435. // the cluster service is starting on this node, the event would have been created in the
  436. // signaled state above, and so, the wait below will exit immediately.
  437. //
  438. do
  439. {
  440. DWORD dwStatus;
  441. // Wait for any message sent or posted to this queue
  442. // or for our event to be signaled.
  443. dwStatus = MsgWaitForMultipleObjects(
  444. 1
  445. , &heventPostCfgCompletion
  446. , FALSE
  447. , 900000 // If no one has signaled this event in 15 minutes, abort.
  448. , QS_ALLINPUT
  449. );
  450. // The result tells us the type of event we have.
  451. if ( dwStatus == ( WAIT_OBJECT_0 + 1 ) )
  452. {
  453. MSG msg;
  454. // Read all of the messages in this next loop,
  455. // removing each message as we read it.
  456. while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) != 0 )
  457. {
  458. // If it is a quit message, we are done pumping messages.
  459. if ( msg.message == WM_QUIT )
  460. {
  461. TraceFlow( "Get a WM_QUIT message. Exit message pump loop." );
  462. break;
  463. } // if: we got a WM_QUIT message
  464. // Otherwise, dispatch the message.
  465. DispatchMessage( &msg );
  466. } // while: there are still messages in the window message queue
  467. } // if: we have a message in the window message queue
  468. else
  469. {
  470. if ( dwStatus == WAIT_OBJECT_0 )
  471. {
  472. TraceFlow( "Our event has been signaled. Exiting wait loop." );
  473. break;
  474. } // else if: our event is signaled
  475. else
  476. {
  477. if ( dwStatus == -1 )
  478. {
  479. dwStatus = TW32( GetLastError() );
  480. hr = HRESULT_FROM_WIN32( dwStatus );
  481. LogMsg( "[SN] Error %#08x occurred trying to wait for an event to be signaled.", dwStatus );
  482. } // if: MsgWaitForMultipleObjects() returned an error
  483. else
  484. {
  485. hr = HRESULT_FROM_WIN32( TW32( dwStatus ) );
  486. LogMsg( "[SN] Error %#08x occurred trying to wait for an event to be signaled.", dwStatus );
  487. } // else: an unexpected value was returned by MsgWaitForMultipleObjects()
  488. break;
  489. } // else: an unexpected result
  490. } // else: MsgWaitForMultipleObjects() exited for a reason other than a waiting message
  491. }
  492. while( true ); // do-while: loop infinitely
  493. if ( FAILED( hr ) )
  494. {
  495. TraceFlow( "Something went wrong trying to wait for the event to be signaled." );
  496. goto Cleanup;
  497. } // if: something has gone wrong
  498. TraceFlow( "Our event has been signaled. Proceed with the notifications." );
  499. // Send out the notifications
  500. hr = THR( HrNotifyListeners() );
  501. if ( FAILED( hr ) )
  502. {
  503. LogMsg( "[SN] Error %#08x occurred trying to notify cluster startup listeners.", hr );
  504. goto Cleanup;
  505. } // if: something went wrong while sending out notifications
  506. LogMsg( "[SN] Sending of cluster startup notifications complete. (hr = %#08x)", hr );
  507. Cleanup:
  508. //
  509. // Clean up
  510. //
  511. if ( heventPostCfgCompletion != NULL )
  512. {
  513. CloseHandle( heventPostCfgCompletion );
  514. } // if: we had created the event
  515. HRETURN( hr );
  516. } //*** CStartupNotify::SendNotifications
  517. //////////////////////////////////////////////////////////////////////////////
  518. //++
  519. //
  520. // HRESULT
  521. // CStartupNotify::HrNotifyListeners
  522. //
  523. // Description:
  524. // Enumerate all components on the local computer registered for cluster
  525. // startup notification.
  526. //
  527. // Arguments:
  528. // None.
  529. //
  530. // Return Values:
  531. // S_OK
  532. // Success.
  533. //
  534. // other HRESULTs
  535. // Something went wrong during the enumeration.
  536. //
  537. //--
  538. //////////////////////////////////////////////////////////////////////////////
  539. HRESULT
  540. CStartupNotify::HrNotifyListeners( void )
  541. {
  542. TraceFunc( "" );
  543. const UINT uiCHUNK_SIZE = 16;
  544. HRESULT hr = S_OK;
  545. ICatInformation * pciCatInfo = NULL;
  546. IEnumCLSID * psleStartupListenerClsidEnum = NULL;
  547. IUnknown * punkResTypeServices = NULL;
  548. ULONG cReturned = 0;
  549. CATID rgCatIdsImplemented[ 1 ];
  550. rgCatIdsImplemented[ 0 ] = CATID_ClusCfgStartupListeners;
  551. //
  552. // Enumerate all the enumerators registered in the
  553. // CATID_ClusCfgStartupListeners category
  554. //
  555. hr = THR(
  556. CoCreateInstance(
  557. CLSID_StdComponentCategoriesMgr
  558. , NULL
  559. , CLSCTX_SERVER
  560. , IID_ICatInformation
  561. , reinterpret_cast< void ** >( &pciCatInfo )
  562. )
  563. );
  564. if ( FAILED( hr ) )
  565. {
  566. LogMsg( "[SN] Error %#08x occurred trying to get a pointer to the enumerator of the CATID_ClusCfgStartupListeners category.", hr );
  567. goto Cleanup;
  568. } // if: we could not get a pointer to the ICatInformation interface
  569. // Get a pointer to the enumerator of the CLSIDs that belong to the CATID_ClusCfgStartupListeners category.
  570. hr = THR(
  571. pciCatInfo->EnumClassesOfCategories(
  572. 1
  573. , rgCatIdsImplemented
  574. , 0
  575. , NULL
  576. , &psleStartupListenerClsidEnum
  577. )
  578. );
  579. if ( FAILED( hr ) )
  580. {
  581. LogMsg( "[SN] Error %#08x occurred trying to get a pointer to the enumerator of the CATID_ClusCfgStartupListeners category.", hr );
  582. goto Cleanup;
  583. } // if: we could not get a pointer to the IEnumCLSID interface
  584. //
  585. // Create an instance of the resource type services component
  586. //
  587. hr = THR(
  588. HrCoCreateInternalInstance(
  589. CLSID_ClusCfgResTypeServices
  590. , NULL
  591. , CLSCTX_INPROC_SERVER
  592. , __uuidof( punkResTypeServices )
  593. , reinterpret_cast< void ** >( &punkResTypeServices )
  594. )
  595. );
  596. if ( FAILED( hr ) )
  597. {
  598. LogMsg( "[SN] Error %#08x occurred trying to create the resource type services component.", hr );
  599. goto Cleanup;
  600. } // if: we could not create the resource type services component
  601. // Enumerate the CLSIDs of the registered startup listeners
  602. do
  603. {
  604. CLSID rgStartupListenerClsids[ uiCHUNK_SIZE ];
  605. ULONG idxCLSID;
  606. cReturned = 0;
  607. hr = STHR(
  608. psleStartupListenerClsidEnum->Next(
  609. uiCHUNK_SIZE
  610. , rgStartupListenerClsids
  611. , &cReturned
  612. )
  613. );
  614. if ( FAILED( hr ) )
  615. {
  616. LogMsg( "[SN] Error %#08x occurred trying enumerate startup listener components.", hr );
  617. break;
  618. } // if: we could not get the next set of CLSIDs
  619. // hr may be S_FALSE here, so reset it.
  620. hr = S_OK;
  621. for ( idxCLSID = 0; idxCLSID < cReturned; ++idxCLSID )
  622. {
  623. hr = THR( HrProcessListener( rgStartupListenerClsids[ idxCLSID ], punkResTypeServices ) );
  624. if ( FAILED( hr ) )
  625. {
  626. // The processing of one of the listeners failed.
  627. // Log the error, but continue processing other listeners.
  628. TraceMsgGUID( mtfALWAYS, "The CLSID of the failed listener is ", rgStartupListenerClsids[ idxCLSID ] );
  629. LogMsg( "[SN] Error %#08x occurred trying to process a cluster startup listener. Other listeners will be processed.", hr );
  630. hr = S_OK;
  631. } // if: this enumerator failed
  632. } // for: iterate through the returned CLSIDs
  633. }
  634. while( cReturned > 0 ); // while: there are still CLSIDs to be enumerated
  635. if ( FAILED( hr ) )
  636. {
  637. goto Cleanup;
  638. } // if: something went wrong in the loop above
  639. Cleanup:
  640. //
  641. // Cleanup code
  642. //
  643. if ( pciCatInfo != NULL )
  644. {
  645. pciCatInfo->Release();
  646. } // if: we had obtained a pointer to the ICatInformation interface
  647. if ( psleStartupListenerClsidEnum != NULL )
  648. {
  649. psleStartupListenerClsidEnum->Release();
  650. } // if: we had obtained a pointer to the enumerator of startup listener CLSIDs
  651. if ( punkResTypeServices != NULL )
  652. {
  653. punkResTypeServices->Release();
  654. } // if: we had created the resource type services component
  655. HRETURN( hr );
  656. } //*** CStartupNotify::HrNotifyListeners
  657. //////////////////////////////////////////////////////////////////////////////
  658. //++
  659. //
  660. // HRESULT
  661. // CStartupNotify::HrProcessListener
  662. //
  663. // Description:
  664. // This function instantiates a cluster startup listener component
  665. // and calls the appropriate methods.
  666. //
  667. // Arguments:
  668. // rclsidListenerCLSIDIn
  669. // CLSID of the startup listener component
  670. //
  671. // punkResTypeServicesIn
  672. // Pointer to the IUnknown interface on the resource type services
  673. // component. This interface provides methods that help configure
  674. // resource types.
  675. //
  676. // Return Values:
  677. // S_OK
  678. // Success.
  679. //
  680. // other HRESULTs
  681. // Something went wrong during the processing of the listener.
  682. //
  683. //--
  684. //////////////////////////////////////////////////////////////////////////////
  685. HRESULT
  686. CStartupNotify::HrProcessListener(
  687. const CLSID & rclsidListenerCLSIDIn
  688. , IUnknown * punkResTypeServicesIn
  689. )
  690. {
  691. TraceFunc( "" );
  692. HRESULT hr = S_OK;
  693. IClusCfgInitialize * pciInitialize = NULL;
  694. IClusCfgStartupListener * pcslStartupListener = NULL;
  695. TraceMsgGUID( mtfALWAYS, "The CLSID of this startup listener is ", rclsidListenerCLSIDIn );
  696. //
  697. // Create the component represented by the CLSID passed in
  698. //
  699. hr = THR(
  700. CoCreateInstance(
  701. rclsidListenerCLSIDIn
  702. , NULL
  703. , CLSCTX_INPROC_SERVER
  704. , __uuidof( pcslStartupListener )
  705. , reinterpret_cast< void ** >( &pcslStartupListener )
  706. )
  707. );
  708. if ( FAILED( hr ) )
  709. {
  710. LogMsg( "[SN] Error %#08x occurred trying to create a cluster startup listener component.", hr );
  711. goto Cleanup;
  712. } // if: we could not create the cluster startup listener component
  713. // Initialize the listener if supported.
  714. hr = pcslStartupListener->TypeSafeQI( IClusCfgInitialize, &pciInitialize );
  715. if ( FAILED( hr ) && ( hr != E_NOINTERFACE ) )
  716. {
  717. LogMsg( "[SN] Error %#08x occurred trying to query for IClusCfgInitialize on the listener component.", THR( hr ) );
  718. goto Cleanup;
  719. } // if: we could not create the cluster startup listener component
  720. // Initialize the listener if supported.
  721. if ( pciInitialize != NULL )
  722. {
  723. hr = THR( pciInitialize->Initialize( static_cast< IClusCfgCallback * >( this ), GetUserDefaultLCID() ) );
  724. if ( FAILED( hr ) )
  725. {
  726. LogMsg( "[SN] Error %#08x occurred trying to initialize the listener component.", hr );
  727. goto Cleanup;
  728. } // if:
  729. pciInitialize->Release();
  730. pciInitialize = NULL;
  731. } // if: pciInitialize != NULL
  732. // Notify this listener.
  733. hr = THR( pcslStartupListener->Notify( punkResTypeServicesIn ) );
  734. if ( FAILED( hr ) )
  735. {
  736. LogMsg( "[SN] Error %#08x occurred trying to notify a cluster startup listener.", hr );
  737. goto Cleanup;
  738. } // if: this notification
  739. Cleanup:
  740. //
  741. // Cleanup code
  742. //
  743. if ( pcslStartupListener != NULL )
  744. {
  745. pcslStartupListener->Release();
  746. } // if: we had obtained a pointer to the startup listener interface
  747. if ( pciInitialize != NULL )
  748. {
  749. pciInitialize->Release();
  750. } // if: we obtained a pointer to the initialize interface
  751. HRETURN( hr );
  752. } //*** CStartupNotify::HrProcessListener
  753. //****************************************************************************
  754. //
  755. // IClusCfgCallback
  756. //
  757. //****************************************************************************
  758. //////////////////////////////////////////////////////////////////////////////
  759. //++
  760. //
  761. // CStartupNotify::SendStatusReport(
  762. // LPCWSTR pcszNodeNameIn
  763. // , CLSID clsidTaskMajorIn
  764. // , CLSID clsidTaskMinorIn
  765. // , ULONG ulMinIn
  766. // , ULONG ulMaxIn
  767. // , ULONG ulCurrentIn
  768. // , HRESULT hrStatusIn
  769. // , LPCWSTR pcszDescriptionIn
  770. // , FILETIME * pftTimeIn
  771. // , LPCWSTR pcszReferenceIn
  772. // )
  773. //
  774. // Description:
  775. //
  776. // Arguments:
  777. //
  778. // Return Value:
  779. //
  780. // Remarks:
  781. // None.
  782. //
  783. //--
  784. //////////////////////////////////////////////////////////////////////////////
  785. STDMETHODIMP
  786. CStartupNotify::SendStatusReport(
  787. LPCWSTR pcszNodeNameIn
  788. , CLSID clsidTaskMajorIn
  789. , CLSID clsidTaskMinorIn
  790. , ULONG ulMinIn
  791. , ULONG ulMaxIn
  792. , ULONG ulCurrentIn
  793. , HRESULT hrStatusIn
  794. , LPCWSTR pcszDescriptionIn
  795. , FILETIME * pftTimeIn
  796. , LPCWSTR pcszReferenceIn
  797. )
  798. {
  799. TraceFunc1( "[IClusCfgCallback] pcszDescriptionIn = '%s'", pcszDescriptionIn == NULL ? TEXT("<null>") : pcszDescriptionIn );
  800. HRESULT hr = S_OK;
  801. if ( pcszNodeNameIn == NULL )
  802. {
  803. pcszNodeNameIn = m_bstrNodeName;
  804. } // if:
  805. TraceMsg( mtfFUNC, L"pcszNodeNameIn = %s", pcszNodeNameIn );
  806. TraceMsgGUID( mtfFUNC, "clsidTaskMajorIn ", clsidTaskMajorIn );
  807. TraceMsgGUID( mtfFUNC, "clsidTaskMinorIn ", clsidTaskMinorIn );
  808. TraceMsg( mtfFUNC, L"ulMinIn = %u", ulMinIn );
  809. TraceMsg( mtfFUNC, L"ulMaxIn = %u", ulMaxIn );
  810. TraceMsg( mtfFUNC, L"ulCurrentIn = %u", ulCurrentIn );
  811. TraceMsg( mtfFUNC, L"hrStatusIn = %#08x", hrStatusIn );
  812. TraceMsg( mtfFUNC, L"pcszDescriptionIn = '%ws'", ( pcszDescriptionIn ? pcszDescriptionIn : L"<null>" ) );
  813. //
  814. // TODO: 21 NOV 2000 GalenB
  815. //
  816. // How do we log pftTimeIn?
  817. //
  818. TraceMsg( mtfFUNC, L"pcszReferenceIn = '%ws'", ( pcszReferenceIn ? pcszReferenceIn : L"<null>" ) );
  819. hr = THR( CClCfgSrvLogger::S_HrLogStatusReport(
  820. m_plLogger
  821. , pcszNodeNameIn
  822. , clsidTaskMajorIn
  823. , clsidTaskMinorIn
  824. , ulMinIn
  825. , ulMaxIn
  826. , ulCurrentIn
  827. , hrStatusIn
  828. , pcszDescriptionIn
  829. , pftTimeIn
  830. , pcszReferenceIn
  831. ) );
  832. HRETURN( hr );
  833. } //*** CStartupNotify::SendStatusReport