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.

877 lines
21 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1999-2002 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // ConnectionManager.cpp
  7. //
  8. // Description:
  9. // Connection Manager implementation.
  10. //
  11. // Maintained By:
  12. // Galen Barbee (GalenB) 22-NOV-1999
  13. //
  14. //////////////////////////////////////////////////////////////////////////////
  15. #include "Pch.h"
  16. #include "ConnectionManager.h"
  17. DEFINE_THISCLASS("CConnectionManager")
  18. #define THISCLASS CConnectionManager
  19. // ************************************************************************
  20. //
  21. // Constructor / Destructor
  22. //
  23. // ************************************************************************
  24. //////////////////////////////////////////////////////////////////////////////
  25. //
  26. // HRESULT
  27. // CConnectionManager::S_HrCreateInstance(
  28. // IUnknown ** ppunkOut
  29. // )
  30. //
  31. //////////////////////////////////////////////////////////////////////////////
  32. HRESULT
  33. CConnectionManager::S_HrCreateInstance(
  34. IUnknown ** ppunkOut
  35. )
  36. {
  37. TraceFunc( "" );
  38. HRESULT hr = S_OK;
  39. CConnectionManager * pcm = NULL;
  40. Assert( ppunkOut != NULL );
  41. if ( ppunkOut == NULL )
  42. {
  43. hr = THR( E_POINTER );
  44. goto Cleanup;
  45. }
  46. pcm = new CConnectionManager();
  47. if ( pcm == NULL )
  48. {
  49. hr = THR( E_OUTOFMEMORY );
  50. goto Cleanup;
  51. }
  52. hr = THR( pcm->HrInit() );
  53. if ( FAILED( hr ) )
  54. {
  55. goto Cleanup;
  56. }
  57. hr = THR( pcm->TypeSafeQI( IUnknown, ppunkOut ) );
  58. if ( FAILED( hr ) )
  59. {
  60. goto Cleanup;
  61. }
  62. Cleanup:
  63. if ( pcm != NULL )
  64. {
  65. pcm->Release();
  66. }
  67. HRETURN( hr );
  68. } //*** CConnectionManager::S_HrCreateInstance;
  69. //////////////////////////////////////////////////////////////////////////////
  70. //
  71. // CConnectionManager::CConnectionManager
  72. //
  73. //////////////////////////////////////////////////////////////////////////////
  74. CConnectionManager::CConnectionManager( void )
  75. : m_cRef( 1 )
  76. {
  77. TraceFunc( "" );
  78. InterlockedIncrement( &g_cObjects );
  79. TraceFuncExit();
  80. } //*** CConnectionManager::CConnectionManager
  81. //////////////////////////////////////////////////////////////////////////////
  82. //
  83. // STDMETHODIMP
  84. // CConnectionManager::HrInit
  85. //
  86. //////////////////////////////////////////////////////////////////////////////
  87. STDMETHODIMP
  88. CConnectionManager::HrInit( void )
  89. {
  90. TraceFunc( "" );
  91. // IUnknown stuff
  92. Assert( m_cRef == 1 );
  93. HRETURN( S_OK );
  94. } //*** CConnectionManager::HrInit
  95. //////////////////////////////////////////////////////////////////////////////
  96. //
  97. // CConnectionManager::~CConnectionManager
  98. //
  99. //////////////////////////////////////////////////////////////////////////////
  100. CConnectionManager::~CConnectionManager( void )
  101. {
  102. TraceFunc( "" );
  103. InterlockedDecrement( &g_cObjects );
  104. TraceFuncExit();
  105. } //*** CConnectionManager::~CConnectionManager
  106. // ************************************************************************
  107. //
  108. // IUnknown
  109. //
  110. // ************************************************************************
  111. //////////////////////////////////////////////////////////////////////////////
  112. //++
  113. //
  114. // CConnectionManager::QueryInterface
  115. //
  116. // Description:
  117. // Query this object for the passed in interface.
  118. //
  119. // Arguments:
  120. // riidIn
  121. // Id of interface requested.
  122. //
  123. // ppvOut
  124. // Pointer to the requested interface.
  125. //
  126. // Return Value:
  127. // S_OK
  128. // If the interface is available on this object.
  129. //
  130. // E_NOINTERFACE
  131. // If the interface is not available.
  132. //
  133. // E_POINTER
  134. // ppvOut was NULL.
  135. //
  136. // Remarks:
  137. // None.
  138. //
  139. //--
  140. //////////////////////////////////////////////////////////////////////////////
  141. STDMETHODIMP
  142. CConnectionManager::QueryInterface(
  143. REFIID riidIn
  144. , LPVOID * ppvOut
  145. )
  146. {
  147. TraceQIFunc( riidIn, ppvOut );
  148. HRESULT hr = S_OK;
  149. //
  150. // Validate arguments.
  151. //
  152. Assert( ppvOut != NULL );
  153. if ( ppvOut == NULL )
  154. {
  155. hr = THR( E_POINTER );
  156. goto Cleanup;
  157. }
  158. //
  159. // Handle known interfaces.
  160. //
  161. if ( IsEqualIID( riidIn, IID_IUnknown ) )
  162. {
  163. *ppvOut = static_cast< IConnectionManager * >( this );
  164. } // if: IUnknown
  165. else if ( IsEqualIID( riidIn, IID_IConnectionManager ) )
  166. {
  167. *ppvOut = TraceInterface( __THISCLASS__, IConnectionManager, this, 0 );
  168. } // else if: IConnectionManager
  169. else
  170. {
  171. *ppvOut = NULL;
  172. hr = E_NOINTERFACE;
  173. } // else
  174. //
  175. // Add a reference to the interface if successful.
  176. //
  177. if ( SUCCEEDED( hr ) )
  178. {
  179. ((IUnknown *) *ppvOut)->AddRef();
  180. } // if: success
  181. Cleanup:
  182. QIRETURN_IGNORESTDMARSHALLING( hr, riidIn );
  183. } //*** CConnectionManager::QueryInterface
  184. //////////////////////////////////////////////////////////////////////////////
  185. //
  186. // STDMETHODIMP_( ULONG )
  187. // CConnectionManager::AddRef
  188. //
  189. //////////////////////////////////////////////////////////////////////////////
  190. STDMETHODIMP_( ULONG )
  191. CConnectionManager::AddRef( void )
  192. {
  193. TraceFunc( "[IUnknown]" );
  194. InterlockedIncrement( &m_cRef );
  195. CRETURN( m_cRef );
  196. } //*** CConnectionManager::AddRef
  197. //////////////////////////////////////////////////////////////////////////////
  198. //
  199. // STDMETHODIMP_( ULONG )
  200. // CConnectionManager::Release
  201. //
  202. //////////////////////////////////////////////////////////////////////////////
  203. STDMETHODIMP_( ULONG )
  204. CConnectionManager::Release( void )
  205. {
  206. TraceFunc( "[IUnknown]" );
  207. LONG cRef;
  208. cRef = InterlockedDecrement( &m_cRef );
  209. if ( cRef == 0 )
  210. {
  211. TraceDo( delete this );
  212. }
  213. CRETURN( cRef );
  214. } //*** CConnectionManager::Release
  215. // ************************************************************************
  216. //
  217. // IConnectionManager
  218. //
  219. // ************************************************************************
  220. //////////////////////////////////////////////////////////////////////////////
  221. //
  222. // STDMETHODIMP
  223. // CConnectionManager::GetConnectionToObject(
  224. // OBJECTCOOKIE cookieIn,
  225. // IUnknown ** ppunkOut
  226. // )
  227. //
  228. //////////////////////////////////////////////////////////////////////////////
  229. STDMETHODIMP
  230. CConnectionManager::GetConnectionToObject(
  231. OBJECTCOOKIE cookieIn,
  232. IUnknown ** ppunkOut
  233. )
  234. {
  235. TraceFunc1( "[IConnectionManager] cookieIn = %#x", cookieIn );
  236. HRESULT hr;
  237. CLSID clsid;
  238. OBJECTCOOKIE cookieParent;
  239. IServiceProvider * psp;
  240. BSTR bstrName = NULL;
  241. IUnknown * punk = NULL;
  242. IObjectManager * pom = NULL;
  243. IConnectionInfo * pci = NULL;
  244. IConnectionInfo * pciParent = NULL;
  245. IStandardInfo * psi = NULL;
  246. IConfigurationConnection * pcc = NULL;
  247. //
  248. // Validate parameters
  249. //
  250. if ( cookieIn == NULL )
  251. {
  252. hr = THR( E_INVALIDARG );
  253. goto Cleanup;
  254. }
  255. if ( ppunkOut == NULL )
  256. {
  257. hr = THR( E_POINTER );
  258. goto Cleanup;
  259. }
  260. //
  261. // Collect the managers needed to complete this method.
  262. //
  263. hr = THR( CoCreateInstance( CLSID_ServiceManager,
  264. NULL,
  265. CLSCTX_INPROC_SERVER,
  266. TypeSafeParams( IServiceProvider, &psp )
  267. ) );
  268. if ( FAILED( hr ) )
  269. {
  270. goto Cleanup;
  271. }
  272. hr = THR( psp->TypeSafeQS( CLSID_ObjectManager, IObjectManager, &pom ) );
  273. psp->Release();
  274. if ( FAILED( hr ) )
  275. {
  276. goto Cleanup;
  277. }
  278. //
  279. // Check to see if we already have a connection cached.
  280. //
  281. //
  282. // Get the connection info for this cookie.
  283. //
  284. hr = THR( pom->GetObject( DFGUID_ConnectionInfoFormat,
  285. cookieIn,
  286. &punk
  287. ) );
  288. if ( FAILED( hr ) )
  289. {
  290. goto Cleanup;
  291. }
  292. hr = THR( punk->TypeSafeQI( IConnectionInfo, &pci ) );
  293. if ( FAILED( hr ) )
  294. {
  295. goto Cleanup;
  296. }
  297. pci = TraceInterface( L"ConnectionManager!IConnectionInfo", IConnectionInfo, pci, 1 );
  298. punk->Release();
  299. punk = NULL;
  300. //
  301. // See if there is a current connection.
  302. //
  303. hr = STHR( pci->GetConnection( &pcc ) );
  304. if ( FAILED( hr ) )
  305. {
  306. goto Cleanup;
  307. }
  308. if ( hr == S_FALSE )
  309. {
  310. //
  311. // Check to see if the parent has a connection.
  312. //
  313. //
  314. // Get the standard info for this cookie.
  315. //
  316. hr = THR( pom->GetObject( DFGUID_StandardInfo,
  317. cookieIn,
  318. &punk
  319. ) );
  320. if ( FAILED( hr ) )
  321. {
  322. goto Cleanup;
  323. }
  324. hr = THR( punk->TypeSafeQI( IStandardInfo, &psi ) );
  325. if ( FAILED( hr ) )
  326. {
  327. goto Cleanup;
  328. }
  329. psi = TraceInterface( L"ConnectionManager!IStandardInfo", IStandardInfo, psi, 1 );
  330. punk->Release();
  331. punk = NULL;
  332. hr = STHR( psi->GetType( &clsid ) );
  333. if ( FAILED( hr ) )
  334. {
  335. goto Cleanup;
  336. }
  337. if ( !IsEqualIID( clsid, CLSID_NodeType )
  338. && !IsEqualIID( clsid, CLSID_ClusterConfigurationType )
  339. )
  340. {
  341. hr = STHR( psi->GetParent( &cookieParent ) );
  342. if ( FAILED( hr ) )
  343. {
  344. goto Cleanup;
  345. }
  346. // Release it.
  347. psi->Release();
  348. psi = NULL;
  349. //
  350. // If there is a parent, follow it.
  351. //
  352. if ( hr == S_OK )
  353. {
  354. //
  355. // Get the connection info for this cookie.
  356. //
  357. hr = THR( pom->GetObject( DFGUID_ConnectionInfoFormat,
  358. cookieParent,
  359. &punk
  360. ) );
  361. if ( FAILED( hr ) )
  362. {
  363. goto Cleanup;
  364. }
  365. hr = THR( punk->TypeSafeQI( IConnectionInfo, &pciParent ) );
  366. if ( FAILED( hr ) )
  367. {
  368. goto Cleanup;
  369. }
  370. pciParent = TraceInterface( L"ConnectionManager!IConnectionInfo", IConnectionInfo, pciParent, 1 );
  371. punk->Release();
  372. punk = NULL;
  373. //
  374. // See if there is a current connection.
  375. //
  376. hr = STHR( pciParent->GetConnection( &pcc ) );
  377. if ( FAILED( hr ) )
  378. {
  379. goto Cleanup;
  380. }
  381. //
  382. // TODO: gpease 08-MAR-2000
  383. // Find a better error code.
  384. //
  385. //if ( hr == S_FALSE )
  386. // goto InvalidArg;
  387. } // if: parent found
  388. } // if: not a node or cluster
  389. else
  390. {
  391. psi->Release();
  392. psi = NULL;
  393. }
  394. } // if: no established connection
  395. //
  396. // Did we have to contact the parent to get to the child?
  397. //
  398. if ( pcc != NULL )
  399. {
  400. //
  401. // Reuse the existing connection.
  402. //
  403. hr = THR( pcc->QueryInterface( IID_IUnknown, reinterpret_cast< void ** >( ppunkOut ) ) );
  404. goto Cleanup;
  405. }
  406. //
  407. // Need to build a connection to the object because the object doesn't
  408. // have a parent and it doesn't currently have a connection.
  409. //
  410. //
  411. // Find out what type of object it is.
  412. //
  413. hr = THR( pom->GetObject( DFGUID_StandardInfo,
  414. cookieIn,
  415. &punk
  416. ) );
  417. if ( FAILED( hr ) )
  418. {
  419. goto Cleanup;
  420. }
  421. hr = THR( punk->TypeSafeQI( IStandardInfo, &psi ) );
  422. if ( FAILED( hr ) )
  423. {
  424. goto Cleanup;
  425. }
  426. psi = TraceInterface( L"ConnectionManager!IStandardInfo", IStandardInfo, psi, 1 );
  427. punk->Release();
  428. punk = NULL;
  429. hr = THR( psi->GetType( &clsid ) );
  430. if ( FAILED( hr ) )
  431. {
  432. goto Cleanup;
  433. }
  434. //
  435. // Create the appropriate connection for that type of object.
  436. //
  437. if ( IsEqualIID( clsid, CLSID_NodeType ) )
  438. {
  439. hr = THRE( HrGetConfigurationConnection( cookieIn, pci, ppunkOut ), HR_S_RPC_S_CLUSTER_NODE_DOWN );
  440. } // if: node
  441. else if ( IsEqualIID( clsid, CLSID_ClusterConfigurationType ) )
  442. {
  443. hr = THRE( HrGetConfigurationConnection( cookieIn, pci, ppunkOut ), HR_S_RPC_S_SERVER_UNAVAILABLE );
  444. } // if: cluster
  445. else
  446. {
  447. hr = HRESULT_FROM_WIN32( TW32( ERROR_CLUSTER_RESOURCE_TYPE_NOT_FOUND ) );
  448. goto Cleanup;
  449. } // else: no connection support
  450. Cleanup:
  451. if ( punk != NULL )
  452. {
  453. punk->Release();
  454. }
  455. TraceSysFreeString( bstrName );
  456. if ( pci != NULL )
  457. {
  458. pci->Release();
  459. } // if: pci
  460. if ( pom != NULL )
  461. {
  462. pom->Release();
  463. } // if: pom
  464. if ( psi != NULL )
  465. {
  466. psi->Release();
  467. } // if: psi
  468. if ( pciParent != NULL )
  469. {
  470. pciParent->Release();
  471. } // if: pciParent
  472. if ( pcc != NULL )
  473. {
  474. pcc->Release();
  475. } // if: pcc
  476. HRETURN( hr );
  477. } //*** CConnectionManager::GetConnectionToObject
  478. //////////////////////////////////////////////////////////////////////////////
  479. //
  480. // HRESULT
  481. // CConnectionManager::HrGetConfigurationConnection(
  482. // OBJECTCOOKIE cookieIn,
  483. // IConnectionInfo * pciIn,
  484. // IUnknown ** ppunkOut
  485. // )
  486. //
  487. //////////////////////////////////////////////////////////////////////////////
  488. HRESULT
  489. CConnectionManager::HrGetConfigurationConnection(
  490. OBJECTCOOKIE cookieIn,
  491. IConnectionInfo * pciIn,
  492. IUnknown ** ppunkOut
  493. )
  494. {
  495. TraceFunc( "" );
  496. HRESULT hr;
  497. IConfigurationConnection * pccNode = NULL;
  498. IConfigurationConnection * pccCluster = NULL;
  499. IConfigurationConnection * pcc = NULL;
  500. // Try and connect to the node using the new server.
  501. hr = HrGetNodeConnection( cookieIn, &pccNode );
  502. if ( hr == HR_S_RPC_S_CLUSTER_NODE_DOWN )
  503. {
  504. Assert( *ppunkOut == NULL );
  505. goto Cleanup;
  506. } // if:
  507. // Try and connect to the node using the W2K object.
  508. if ( hr == HRESULT_FROM_WIN32( REGDB_E_CLASSNOTREG ) )
  509. {
  510. HRESULT hrCluster = THR( HrGetClusterConnection( cookieIn, &pccCluster ) );
  511. if ( hrCluster == S_OK )
  512. {
  513. Assert( pccCluster != NULL );
  514. Assert( pcc == NULL );
  515. pcc = pccCluster;
  516. pccCluster = NULL;
  517. hr = hrCluster;
  518. } // if:
  519. } // if: failed to get a node connection
  520. if ( FAILED( hr ) )
  521. {
  522. THR( hr );
  523. goto Cleanup;
  524. }
  525. if ( pcc == NULL )
  526. {
  527. Assert( pccNode != NULL );
  528. pcc = pccNode;
  529. pccNode = NULL;
  530. }
  531. //
  532. // VERY IMPORTANT: Store the connection and retrieve the IUnknown pointer
  533. // only if the result is S_OK.
  534. //
  535. if ( hr == S_OK )
  536. {
  537. THR( HrStoreConnection( pciIn, pcc, ppunkOut ) );
  538. }
  539. Cleanup:
  540. if ( pcc )
  541. {
  542. pcc->Release();
  543. }
  544. if ( pccNode != NULL )
  545. {
  546. pccNode->Release();
  547. }
  548. if ( pccCluster != NULL )
  549. {
  550. pccCluster->Release();
  551. }
  552. HRETURN( hr );
  553. } //*** CConnectionManager::HrGetConfigurationConnection
  554. //////////////////////////////////////////////////////////////////////////////
  555. //
  556. // HRESULT
  557. // CConnectionManager::HrGetNodeConnection(
  558. // OBJECTCOOKIE cookieIn,
  559. // IConfigurationConnection ** ppccOut
  560. // )
  561. //
  562. // This connection may be valid even if the ConnectTo call fails.
  563. // -That means that there is no cluster installed on the target node.
  564. //
  565. //////////////////////////////////////////////////////////////////////////////
  566. HRESULT
  567. CConnectionManager::HrGetNodeConnection(
  568. OBJECTCOOKIE cookieIn,
  569. IConfigurationConnection ** ppccOut
  570. )
  571. {
  572. TraceFunc( "" );
  573. HRESULT hr;
  574. IConfigurationConnection * pcc = NULL;
  575. // Check the pointers in.
  576. Assert( ppccOut != NULL );
  577. Assert( *ppccOut == NULL );
  578. hr = THR( HrCoCreateInternalInstance(
  579. CLSID_ConfigurationConnection
  580. , NULL
  581. , CLSCTX_SERVER
  582. , TypeSafeParams( IConfigurationConnection, &pcc )
  583. ) );
  584. if ( FAILED( hr ) )
  585. {
  586. goto Cleanup;
  587. }
  588. // Don't wrap - we want to handle some of the failures.
  589. hr = pcc->ConnectTo( cookieIn );
  590. switch( hr )
  591. {
  592. // Known valid return codes.
  593. case HR_S_RPC_S_SERVER_UNAVAILABLE:
  594. break;
  595. // Known error codes.
  596. case HRESULT_FROM_WIN32( REGDB_E_CLASSNOTREG ):
  597. // This means the ClusCfg server is not available.
  598. goto Cleanup;
  599. case HR_S_RPC_S_CLUSTER_NODE_DOWN:
  600. // This means the service is not running on that node.
  601. Assert( *ppccOut == NULL );
  602. goto Cleanup;
  603. default:
  604. if( FAILED( hr ) )
  605. {
  606. THR( hr );
  607. goto Cleanup;
  608. }
  609. } // switch:
  610. // Return the connection.
  611. *ppccOut = pcc;
  612. pcc = NULL;
  613. Cleanup:
  614. if ( pcc )
  615. {
  616. pcc->Release();
  617. }
  618. HRETURN( hr );
  619. } //*** CConnectionManager::HrGetNodeConnection
  620. //////////////////////////////////////////////////////////////////////////////
  621. //
  622. // HRESULT
  623. // CConnectionManager::HrGetClusterConnection(
  624. // OBJECTCOOKIE cookieIn,
  625. // IConfigurationConnection ** ppccOut
  626. // )
  627. //
  628. //
  629. // This connection must succeede completely to return a valid object.
  630. //
  631. //////////////////////////////////////////////////////////////////////////////
  632. HRESULT
  633. CConnectionManager::HrGetClusterConnection(
  634. OBJECTCOOKIE cookieIn,
  635. IConfigurationConnection ** ppccOut
  636. )
  637. {
  638. TraceFunc( "" );
  639. HRESULT hr;
  640. IConfigurationConnection * pcc = NULL;
  641. // Check the pointers in.
  642. Assert( ppccOut != NULL );
  643. Assert( *ppccOut == NULL );
  644. //
  645. // Should be a downlevel cluster.
  646. //
  647. hr = THR( HrCoCreateInternalInstance(
  648. CLSID_ConfigClusApi
  649. , NULL
  650. , CLSCTX_SERVER
  651. , TypeSafeParams( IConfigurationConnection, &pcc )
  652. ) );
  653. if ( FAILED( hr ) )
  654. {
  655. goto Cleanup;
  656. }
  657. // Don't wrap - we want to handle some of the failures.
  658. hr = pcc->ConnectTo( cookieIn );
  659. if ( hr == HR_S_RPC_S_CLUSTER_NODE_DOWN )
  660. {
  661. goto Cleanup;
  662. } // if:
  663. // Handle the expected error messages.
  664. // If the cluster service is not running, then the endpoint
  665. // is unavailable and we cannot connect to it.
  666. if ( hr == HRESULT_FROM_WIN32( EPT_S_NOT_REGISTERED ) )
  667. {
  668. goto Cleanup;
  669. }
  670. if ( FAILED( hr ) )
  671. {
  672. THR( hr );
  673. goto Cleanup;
  674. } // if:
  675. // Return the connection.
  676. *ppccOut = pcc;
  677. pcc = NULL;
  678. Cleanup:
  679. if ( pcc )
  680. {
  681. pcc->Release();
  682. }
  683. HRETURN( hr );
  684. } //*** CConnectionManager::HrGetClusterConnection
  685. //////////////////////////////////////////////////////////////////////////////
  686. //
  687. // HRESULT
  688. // CConnectionManager::HrStoreConnection(
  689. // IConnectionInfo * pciIn,
  690. // IConfigurationConnection * pccIn,
  691. // IUnknown ** ppunkOut
  692. // )
  693. //
  694. //////////////////////////////////////////////////////////////////////////////
  695. HRESULT
  696. CConnectionManager::HrStoreConnection(
  697. IConnectionInfo * pciIn,
  698. IConfigurationConnection * pccIn,
  699. IUnknown ** ppunkOut
  700. )
  701. {
  702. TraceFunc( "" );
  703. HRESULT hr;
  704. //
  705. // Save it away to be used next time.
  706. //
  707. // TODO: gpease 08-MAR-2000
  708. // If we failed to save away the connection, does
  709. // the caller need to know this? I don't think so.
  710. //
  711. THR( pciIn->SetConnection( pccIn ) );
  712. hr = THR( pccIn->QueryInterface( IID_IUnknown,
  713. reinterpret_cast< void ** >( ppunkOut )
  714. ) );
  715. HRETURN( hr );
  716. } //*** CConnectionManager::HrStoreConnection