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

789 lines
19 KiB

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