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.

1319 lines
32 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1999-2002 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // ObjectManager.cpp
  7. //
  8. // Description:
  9. // Object Manager implementation.
  10. //
  11. // Maintained By:
  12. // Galen Barbee (GalenB) 22-NOV-1999
  13. //
  14. //////////////////////////////////////////////////////////////////////////////
  15. #include "Pch.h"
  16. #include "ObjectManager.h"
  17. #include "ConnectionInfo.h"
  18. #include "StandardInfo.h"
  19. #include "EnumCookies.h"
  20. DEFINE_THISCLASS("CObjectManager")
  21. #define COOKIE_BUFFER_GROW_SIZE 100
  22. // ************************************************************************
  23. //
  24. // Constructor / Destructor
  25. //
  26. // ************************************************************************
  27. //////////////////////////////////////////////////////////////////////////////
  28. //
  29. // LPUNKNOWN
  30. // CObjectManager::S_HrCreateInstance(
  31. // IUnknown ** ppunkOut
  32. // )
  33. //
  34. //////////////////////////////////////////////////////////////////////////////
  35. HRESULT
  36. CObjectManager::S_HrCreateInstance(
  37. IUnknown ** ppunkOut
  38. )
  39. {
  40. TraceFunc( "" );
  41. HRESULT hr = S_OK;
  42. IServiceProvider * psp = NULL;
  43. CObjectManager * pom = NULL;
  44. Assert( ppunkOut != NULL );
  45. if ( ppunkOut == NULL )
  46. {
  47. hr = THR( E_POINTER );
  48. goto Cleanup;
  49. }
  50. // Don't wrap - this can fail with E_POINTER.
  51. hr = CServiceManager::S_HrGetManagerPointer( &psp );
  52. if ( hr == E_POINTER )
  53. {
  54. //
  55. // This happens when the Service Manager is first started.
  56. //
  57. pom = new CObjectManager();
  58. if ( pom == NULL )
  59. {
  60. hr = THR( E_OUTOFMEMORY );
  61. goto Cleanup;
  62. }
  63. hr = THR( pom->HrInit() );
  64. if ( FAILED( hr ) )
  65. {
  66. goto Cleanup;
  67. }
  68. hr = THR( pom->TypeSafeQI( IUnknown, ppunkOut ) );
  69. if ( FAILED( hr ) )
  70. {
  71. goto Cleanup;
  72. }
  73. } // if: service manager doesn't exists
  74. else if ( FAILED( hr ) )
  75. {
  76. THR( hr );
  77. goto Cleanup;
  78. }
  79. else
  80. {
  81. hr = THR( psp->TypeSafeQS( CLSID_ObjectManager,
  82. IUnknown,
  83. ppunkOut
  84. ) );
  85. psp->Release();
  86. } // else: service manager exists
  87. Cleanup:
  88. if ( pom != NULL )
  89. {
  90. pom->Release();
  91. }
  92. HRETURN( hr );
  93. } //*** CObjectManager::S_HrCreateInstance
  94. //////////////////////////////////////////////////////////////////////////////
  95. //
  96. // CObjectManager::CObjectManager
  97. //
  98. //////////////////////////////////////////////////////////////////////////////
  99. CObjectManager::CObjectManager( void )
  100. : m_cRef( 1 )
  101. {
  102. TraceFunc( "" );
  103. InterlockedIncrement( &g_cObjects );
  104. TraceFuncExit();
  105. } //*** CObjectManager::CObjectManager
  106. //////////////////////////////////////////////////////////////////////////////
  107. //
  108. // STDMETHODIMP
  109. // CObjectManager::HrInit
  110. //
  111. //////////////////////////////////////////////////////////////////////////////
  112. STDMETHODIMP
  113. CObjectManager::HrInit( void )
  114. {
  115. TraceFunc( "" );
  116. HRESULT hr = S_OK;
  117. // IUnknown stuff
  118. Assert( m_cRef == 1 );
  119. // IObjectManager
  120. Assert( m_cAllocSize == 0 );
  121. Assert( m_cCurrentUsed == 0 );
  122. Assert( m_pCookies == NULL );
  123. hr = THR( m_csInstanceGuard.HrInitialized() );
  124. HRETURN( hr );
  125. } //*** CObjectManager::HrInit
  126. //////////////////////////////////////////////////////////////////////////////
  127. //
  128. // CObjectManager::~CObjectManager
  129. //
  130. //////////////////////////////////////////////////////////////////////////////
  131. CObjectManager::~CObjectManager( void )
  132. {
  133. TraceFunc( "" );
  134. if ( m_pCookies != NULL )
  135. {
  136. while ( m_cCurrentUsed != 0 )
  137. {
  138. m_cCurrentUsed --;
  139. if ( m_pCookies[ m_cCurrentUsed ] != NULL )
  140. {
  141. m_pCookies[ m_cCurrentUsed ]->Release();
  142. }
  143. }
  144. TraceFree( m_pCookies );
  145. }
  146. InterlockedDecrement( &g_cObjects );
  147. TraceFuncExit();
  148. } //*** CObjectManager::~CObjectManager
  149. // ************************************************************************
  150. //
  151. // IUnknown
  152. //
  153. // ************************************************************************
  154. //////////////////////////////////////////////////////////////////////////////
  155. //++
  156. //
  157. // CObjectManager::QueryInterface
  158. //
  159. // Description:
  160. // Query this object for the passed in interface.
  161. //
  162. // Arguments:
  163. // riidIn
  164. // Id of interface requested.
  165. //
  166. // ppvOut
  167. // Pointer to the requested interface.
  168. //
  169. // Return Value:
  170. // S_OK
  171. // If the interface is available on this object.
  172. //
  173. // E_NOINTERFACE
  174. // If the interface is not available.
  175. //
  176. // E_POINTER
  177. // ppvOut was NULL.
  178. //
  179. // Remarks:
  180. // None.
  181. //
  182. //--
  183. //////////////////////////////////////////////////////////////////////////////
  184. STDMETHODIMP
  185. CObjectManager::QueryInterface(
  186. REFIID riidIn
  187. , LPVOID * ppvOut
  188. )
  189. {
  190. TraceQIFunc( riidIn, ppvOut );
  191. HRESULT hr = S_OK;
  192. //
  193. // Validate arguments.
  194. //
  195. Assert( ppvOut != NULL );
  196. if ( ppvOut == NULL )
  197. {
  198. hr = THR( E_POINTER );
  199. goto Cleanup;
  200. }
  201. //
  202. // Handle known interfaces.
  203. //
  204. if ( IsEqualIID( riidIn, IID_IUnknown ) )
  205. {
  206. *ppvOut = static_cast< LPUNKNOWN >( this );
  207. } // if: IUnknown
  208. else if ( IsEqualIID( riidIn, IID_IObjectManager ) )
  209. {
  210. *ppvOut = TraceInterface( __THISCLASS__, IObjectManager, this, 0 );
  211. } // else if: IObjectManager
  212. else
  213. {
  214. *ppvOut = NULL;
  215. hr = E_NOINTERFACE;
  216. }
  217. //
  218. // Add a reference to the interface if successful.
  219. //
  220. if ( SUCCEEDED( hr ) )
  221. {
  222. ((IUnknown *) *ppvOut)->AddRef();
  223. } // if: success
  224. Cleanup:
  225. QIRETURN_IGNORESTDMARSHALLING( hr, riidIn );
  226. } //*** CObjectManager::QueryInterface
  227. //////////////////////////////////////////////////////////////////////////////
  228. //
  229. // STDMETHODIMP_(ULONG)
  230. // CObjectManager::AddRef
  231. //
  232. //////////////////////////////////////////////////////////////////////////////
  233. STDMETHODIMP_(ULONG)
  234. CObjectManager::AddRef( void )
  235. {
  236. TraceFunc( "[IUnknown]" );
  237. InterlockedIncrement( &m_cRef );
  238. CRETURN( m_cRef );
  239. } //*** CObjectManager::AddRef
  240. //////////////////////////////////////////////////////////////////////////////
  241. //
  242. // STDMETHODIMP_(ULONG)
  243. // CObjectManager::Release
  244. //
  245. //////////////////////////////////////////////////////////////////////////////
  246. STDMETHODIMP_(ULONG)
  247. CObjectManager::Release( void )
  248. {
  249. TraceFunc( "[IUnknown]" );
  250. LONG cRef;
  251. cRef = InterlockedDecrement( &m_cRef );
  252. if ( cRef == 0 )
  253. {
  254. TraceDo( delete this );
  255. }
  256. CRETURN( cRef );
  257. } //*** CObjectManager::Release
  258. // ************************************************************************
  259. //
  260. // IObjectManager
  261. //
  262. // ************************************************************************
  263. //////////////////////////////////////////////////////////////////////////////
  264. //
  265. // STDMETHODIMP
  266. // CObjectManager::FindObject(
  267. // REFCLSID rclsidTypeIn,
  268. // OBJECTCOOKIE cookieParentIn,
  269. // LPCWSTR pcszNameIn,
  270. // REFCLSID rclsidFormatIn,
  271. // OBJECTCOOKIE * cookieOut,
  272. // LPUNKNOWN * punkOut
  273. // )
  274. //
  275. //////////////////////////////////////////////////////////////////////////////
  276. STDMETHODIMP
  277. CObjectManager::FindObject(
  278. REFCLSID rclsidTypeIn,
  279. OBJECTCOOKIE cookieParentIn,
  280. LPCWSTR pcszNameIn,
  281. REFCLSID rclsidFormatIn,
  282. OBJECTCOOKIE * pcookieOut,
  283. LPUNKNOWN * ppunkOut
  284. )
  285. {
  286. TraceFunc( "[IObjectManager]" );
  287. ExtObjectEntry * pentry;
  288. HRESULT hr = HRESULT_FROM_WIN32( ERROR_OBJECT_NOT_FOUND );
  289. OBJECTCOOKIE cookie = 0;
  290. CStandardInfo * pcsi = NULL; // don't free
  291. BOOL fTempCookie = FALSE;
  292. CEnumCookies * pcec = NULL;
  293. IUnknown * punk = NULL;
  294. IExtendObjectManager * peom = NULL;
  295. //
  296. // Check to see if we already have an object.
  297. //
  298. m_csInstanceGuard.Enter();
  299. if ( pcszNameIn != NULL )
  300. {
  301. hr = STHR( HrSearchForExistingCookie( rclsidTypeIn, cookieParentIn, pcszNameIn, &cookie ) );
  302. if ( FAILED( hr ) )
  303. {
  304. goto Cleanup;
  305. }
  306. if ( hr == S_FALSE )
  307. {
  308. hr = THR( HrCreateNewCookie( rclsidTypeIn, cookieParentIn, pcszNameIn, &cookie ) );
  309. if ( FAILED( hr ) )
  310. {
  311. goto Cleanup;
  312. }
  313. pcsi = m_pCookies[ cookie ];
  314. Assert( pcsi != NULL );
  315. }
  316. else if ( hr == S_OK )
  317. {
  318. //
  319. // Found an existing cookie.
  320. //
  321. if ( pcookieOut != NULL )
  322. {
  323. *pcookieOut = cookie;
  324. }
  325. if ( ppunkOut != NULL )
  326. {
  327. pcsi = m_pCookies[ cookie ];
  328. //
  329. // Is the object still in an failed state or still pending?
  330. //
  331. if ( FAILED( pcsi->m_hrStatus ) )
  332. {
  333. hr = pcsi->m_hrStatus;
  334. goto Cleanup;
  335. }
  336. //
  337. // Retrieve the requested format.
  338. //
  339. hr = THR( GetObject( rclsidFormatIn, cookie, ppunkOut ) );
  340. // we always jump to cleanup. No need to check hr here.
  341. goto Cleanup;
  342. }
  343. }
  344. else
  345. {
  346. //
  347. // Unexpected error_success - now what?
  348. //
  349. Assert( hr == S_OK );
  350. goto Cleanup;
  351. }
  352. } // if: named object
  353. else
  354. {
  355. Assert( pcsi == NULL );
  356. }
  357. //
  358. // Create a new object.
  359. //
  360. if ( IsEqualIID( rclsidFormatIn, IID_NULL )
  361. || ppunkOut == NULL
  362. )
  363. {
  364. //
  365. // No-op.
  366. //
  367. hr = S_OK;
  368. } // if: IID_NULL
  369. else if ( IsEqualIID( rclsidFormatIn, DFGUID_StandardInfo ) )
  370. {
  371. hr = THR( pcsi->QueryInterface( DFGUID_StandardInfo,
  372. reinterpret_cast< void ** >( ppunkOut )
  373. ) );
  374. if ( FAILED( hr ) )
  375. goto Cleanup;
  376. } // else if: standard info
  377. else if ( IsEqualIID( rclsidFormatIn, DFGUID_ConnectionInfoFormat ) )
  378. {
  379. if ( pcsi->m_pci != NULL )
  380. {
  381. *ppunkOut = TraceInterface( L"CConnectionInfo!ObjectManager", IConnectionInfo, pcsi->m_pci, 0 );
  382. (*ppunkOut)->AddRef();
  383. hr = S_OK;
  384. }
  385. else
  386. {
  387. hr = THR( CConnectionInfo::S_HrCreateInstance( &punk, pcsi->m_cookieParent ) );
  388. if ( FAILED( hr ) )
  389. {
  390. goto Cleanup;
  391. }
  392. hr = THR( punk->TypeSafeQI( IConnectionInfo,
  393. &pcsi->m_pci
  394. ) );
  395. if ( FAILED( hr ) )
  396. {
  397. goto Cleanup;
  398. }
  399. hr = THR( punk->QueryInterface( IID_IConnectionInfo,
  400. reinterpret_cast< void ** >( ppunkOut )
  401. ) );
  402. if ( FAILED( hr ) )
  403. {
  404. goto Cleanup;
  405. }
  406. } // else:
  407. } // else if: connection info
  408. else if ( IsEqualIID( rclsidFormatIn, DFGUID_EnumCookies ) )
  409. {
  410. ULONG cIter;
  411. //
  412. // Create a new cookie enumerator.
  413. //
  414. pcec = new CEnumCookies;
  415. if ( pcec == NULL )
  416. {
  417. hr = THR( E_OUTOFMEMORY );
  418. goto Cleanup;
  419. }
  420. //
  421. // Initialize the enumerator. This also causes an AddRef().
  422. //
  423. hr = THR( pcec->HrInit() );
  424. if ( FAILED( hr ) )
  425. {
  426. goto Cleanup;
  427. }
  428. //
  429. // See who matches our citeria.
  430. //
  431. pcec->m_cIter = 0;
  432. for( cIter = 1; cIter < m_cCurrentUsed; cIter ++ )
  433. {
  434. pcsi = m_pCookies[ cIter ];
  435. if ( pcsi != NULL )
  436. {
  437. if ( rclsidTypeIn == IID_NULL
  438. || pcsi->m_clsidType == rclsidTypeIn
  439. )
  440. {
  441. if ( cookieParentIn == NULL
  442. || pcsi->m_cookieParent == cookieParentIn
  443. )
  444. {
  445. if ( ( pcszNameIn == NULL )
  446. || ( ( pcsi->m_bstrName != NULL )
  447. && ( StrCmpI( pcsi->m_bstrName, pcszNameIn ) == 0 )
  448. )
  449. )
  450. {
  451. //
  452. // Match!
  453. //
  454. pcec->m_cIter ++;
  455. } // if: names match
  456. } // if: parents match
  457. } // if: match parent and type
  458. } // if: valid element
  459. } // for: cIter
  460. if ( pcec->m_cIter == 0 )
  461. {
  462. // The error text is better than the coding value.
  463. hr = HRESULT_FROM_WIN32( TW32( ERROR_NOT_FOUND ) );
  464. goto Cleanup;
  465. }
  466. //
  467. // Alloc an array to hold the cookies.
  468. //
  469. pcec->m_pList = (OBJECTCOOKIE*) TraceAlloc( HEAP_ZERO_MEMORY, pcec->m_cIter * sizeof(OBJECTCOOKIE) );
  470. if ( pcec->m_pList == NULL )
  471. {
  472. hr = THR( E_OUTOFMEMORY );
  473. goto Cleanup;
  474. }
  475. pcec->m_cAlloced = pcec->m_cIter;
  476. pcec->m_cIter = 0;
  477. for( cIter = 1; cIter < m_cCurrentUsed; cIter ++ )
  478. {
  479. pcsi = m_pCookies[ cIter ];
  480. if ( pcsi != NULL )
  481. {
  482. if ( rclsidTypeIn == IID_NULL
  483. || pcsi->m_clsidType == rclsidTypeIn
  484. )
  485. {
  486. if ( cookieParentIn == NULL
  487. || pcsi->m_cookieParent == cookieParentIn
  488. )
  489. {
  490. if ( ( pcszNameIn == NULL )
  491. || ( ( pcsi->m_bstrName != NULL )
  492. && ( StrCmpI( pcsi->m_bstrName, pcszNameIn ) == 0 )
  493. )
  494. )
  495. {
  496. //
  497. // Match!
  498. //
  499. pcec->m_pList[ pcec->m_cIter ] = cIter;
  500. pcec->m_cIter ++;
  501. } // if: names match
  502. } // if: parents match
  503. } // if: match parent and type
  504. } // if: valid element
  505. } // for: cIter
  506. Assert( pcec->m_cIter != 0 );
  507. pcec->m_cCookies = pcec->m_cIter;
  508. pcec->m_cIter = 0;
  509. //
  510. // Grab the inteface on the way out.
  511. //
  512. hr = THR( pcec->QueryInterface( IID_IEnumCookies,
  513. reinterpret_cast< void ** >( ppunkOut )
  514. ) );
  515. if ( FAILED( hr ) )
  516. {
  517. goto Cleanup;
  518. }
  519. } // else if: enum cookies
  520. else
  521. {
  522. //
  523. // Check for extension formats.
  524. //
  525. //
  526. // See if the format already exists for this cookie.
  527. //
  528. if ( punk != NULL )
  529. {
  530. punk->Release();
  531. punk = NULL;
  532. }
  533. if ( pcsi != NULL )
  534. {
  535. for( pentry = pcsi->m_pExtObjList; pentry != NULL; pentry = pentry->pNext )
  536. {
  537. if ( pentry->iid == rclsidFormatIn )
  538. {
  539. hr = THR( pentry->punk->QueryInterface( rclsidFormatIn,
  540. reinterpret_cast< void ** >( &punk )
  541. ) );
  542. if ( FAILED( hr ) )
  543. {
  544. goto Cleanup;
  545. }
  546. break; // exit loop
  547. }
  548. } // for: pentry
  549. } // if: have cookie
  550. else
  551. {
  552. //
  553. // Create a temporary cookie.
  554. //
  555. Assert( pcszNameIn == NULL );
  556. hr = THR( HrCreateNewCookie( IID_NULL, cookieParentIn, NULL, &cookie ) );
  557. if ( FAILED( hr ) )
  558. {
  559. goto Cleanup;
  560. }
  561. fTempCookie = TRUE;
  562. Assert( pcsi == NULL );
  563. } // else: need a temporary cookie
  564. if ( punk == NULL )
  565. {
  566. //
  567. // Possibly a new or externally object, try creating it and querying.
  568. //
  569. hr = THR( HrCoCreateInternalInstance( rclsidFormatIn,
  570. NULL,
  571. CLSCTX_ALL,
  572. TypeSafeParams( IExtendObjectManager, &peom )
  573. ) );
  574. if ( FAILED( hr ) )
  575. {
  576. goto Cleanup;
  577. }
  578. Assert( punk == NULL );
  579. // Can't wrap with THR because it can return E_PENDING.
  580. hr = peom->FindObject( cookie,
  581. rclsidTypeIn,
  582. pcszNameIn,
  583. &punk
  584. );
  585. if ( hr == E_PENDING )
  586. {
  587. // ignore
  588. }
  589. else if ( FAILED( hr ) )
  590. {
  591. THR( hr );
  592. goto Cleanup;
  593. }
  594. if ( fTempCookie )
  595. {
  596. (m_pCookies[ cookie ])->Release();
  597. m_pCookies[ cookie ] = NULL;
  598. }
  599. else
  600. {
  601. //
  602. // Keep track of the format (if extension wants)
  603. //
  604. if ( ( ( SUCCEEDED( hr )
  605. && hr != S_FALSE
  606. )
  607. || hr == E_PENDING
  608. )
  609. && punk != NULL
  610. && pcsi != NULL
  611. )
  612. {
  613. pentry = (ExtObjectEntry *) TraceAlloc( 0, sizeof( ExtObjectEntry ) );
  614. if ( pentry == NULL )
  615. {
  616. hr = THR( E_OUTOFMEMORY );
  617. goto Cleanup;
  618. }
  619. pentry->iid = rclsidFormatIn;
  620. pentry->pNext = pcsi->m_pExtObjList;
  621. pentry->punk = punk;
  622. pentry->punk->AddRef();
  623. pcsi->m_pExtObjList = pentry; // update header of list (LIFO)
  624. pcsi->m_hrStatus = hr; // update status
  625. }
  626. } // else: persistent cookie
  627. if ( SUCCEEDED( hr ) )
  628. {
  629. // Give up ownership
  630. *ppunkOut = punk;
  631. punk = NULL;
  632. }
  633. } // if: creating new object
  634. } // else: possible extension format
  635. //
  636. // Save stuff for the caller.
  637. //
  638. if ( pcookieOut != NULL )
  639. {
  640. *pcookieOut = cookie;
  641. }
  642. Cleanup:
  643. if ( punk != NULL )
  644. {
  645. punk->Release();
  646. }
  647. if ( peom != NULL )
  648. {
  649. peom->Release();
  650. }
  651. if ( pcec != NULL )
  652. {
  653. pcec->Release();
  654. }
  655. m_csInstanceGuard.Leave();
  656. HRETURN( hr );
  657. } //*** CObjectManager::FindObject
  658. //////////////////////////////////////////////////////////////////////////////
  659. //
  660. // STDMETHODIMP
  661. // CObjectManager::GetObject(
  662. // REFCLSID rclsidFormatIn,
  663. // OBJECTCOOKIE cookieIn,
  664. // LPUNKNOWN * ppunkOut
  665. // )
  666. //
  667. //////////////////////////////////////////////////////////////////////////////
  668. STDMETHODIMP
  669. CObjectManager::GetObject(
  670. REFCLSID rclsidFormatIn,
  671. OBJECTCOOKIE cookieIn,
  672. LPUNKNOWN * ppunkOut
  673. )
  674. {
  675. TraceFunc( "[IObjectManager]" );
  676. CStandardInfo * pcsi;
  677. ExtObjectEntry * pentry;
  678. HRESULT hr = HRESULT_FROM_WIN32( ERROR_OBJECT_NOT_FOUND );
  679. IUnknown * punk = NULL;
  680. IExtendObjectManager * peom = NULL;
  681. //
  682. // Check parameters
  683. //
  684. m_csInstanceGuard.Enter();
  685. if ( cookieIn == 0 || cookieIn >= m_cCurrentUsed )
  686. {
  687. hr = THR( E_INVALIDARG );
  688. goto Cleanup;
  689. }
  690. pcsi = m_pCookies[ cookieIn ];
  691. if ( pcsi == NULL )
  692. {
  693. hr = HRESULT_FROM_WIN32( TW32( ERROR_NOT_FOUND ) );
  694. goto Cleanup;
  695. }
  696. //
  697. // Create the request format object.
  698. //
  699. if ( IsEqualIID( rclsidFormatIn, IID_NULL )
  700. || ppunkOut == NULL
  701. )
  702. {
  703. //
  704. // No-op.
  705. //
  706. hr = S_OK;
  707. } // if: IID_NULL
  708. else if ( IsEqualIID( rclsidFormatIn, DFGUID_StandardInfo ) )
  709. {
  710. hr = THR( pcsi->QueryInterface( DFGUID_StandardInfo,
  711. reinterpret_cast< void ** >( ppunkOut )
  712. ) );
  713. if ( FAILED( hr ) )
  714. {
  715. goto Cleanup;
  716. }
  717. } // else if: Standard Info
  718. else if ( IsEqualIID( rclsidFormatIn, DFGUID_ConnectionInfoFormat ) )
  719. {
  720. if ( pcsi->m_pci != NULL )
  721. {
  722. *ppunkOut = pcsi->m_pci;
  723. (*ppunkOut)->AddRef();
  724. hr = S_OK;
  725. }
  726. else
  727. {
  728. hr = THR( CConnectionInfo::S_HrCreateInstance( &punk, pcsi->m_cookieParent ) );
  729. if ( FAILED( hr ) )
  730. {
  731. goto Cleanup;
  732. }
  733. hr = THR( punk->TypeSafeQI( IConnectionInfo,
  734. &pcsi->m_pci
  735. ) );
  736. if ( FAILED( hr ) )
  737. {
  738. goto Cleanup;
  739. }
  740. hr = THR( punk->QueryInterface( IID_IConnectionInfo,
  741. reinterpret_cast< void ** >( ppunkOut )
  742. ) );
  743. if ( FAILED( hr ) )
  744. {
  745. goto Cleanup;
  746. }
  747. }
  748. } // else if: Connection Info
  749. else
  750. {
  751. //
  752. // See if the format already exists for this cookie.
  753. //
  754. if ( punk != NULL )
  755. {
  756. punk->Release();
  757. punk = NULL;
  758. }
  759. for( pentry = pcsi->m_pExtObjList; pentry != NULL; pentry = pentry->pNext )
  760. {
  761. if ( pentry->iid == rclsidFormatIn )
  762. {
  763. hr = THR( pentry->punk->QueryInterface( rclsidFormatIn,
  764. reinterpret_cast< void ** >( &punk )
  765. ) );
  766. if ( FAILED( hr ) )
  767. {
  768. goto Cleanup;
  769. }
  770. break; // exit loop
  771. }
  772. } // for: pentry
  773. if ( punk == NULL )
  774. {
  775. hr = HRESULT_FROM_WIN32( TW32( ERROR_NOT_FOUND ) );
  776. goto Cleanup;
  777. }
  778. // Give up ownership
  779. *ppunkOut = punk;
  780. punk = NULL;
  781. } // else: external?
  782. Cleanup:
  783. if ( punk != NULL )
  784. {
  785. punk->Release();
  786. }
  787. if ( peom != NULL )
  788. {
  789. peom->Release();
  790. }
  791. m_csInstanceGuard.Leave();
  792. HRETURN( hr );
  793. } //*** CObjectManager::GetObject
  794. //////////////////////////////////////////////////////////////////////////////
  795. //
  796. // STDMETHODIMP
  797. // CObjectManager::RemoveObject(
  798. // OBJECTCOOKIE cookieIn
  799. // )
  800. //
  801. //////////////////////////////////////////////////////////////////////////////
  802. STDMETHODIMP
  803. CObjectManager::RemoveObject(
  804. OBJECTCOOKIE cookieIn
  805. )
  806. {
  807. TraceFunc( "[IObjectManager]" );
  808. HRESULT hr = S_FALSE;
  809. CStandardInfo * pcsi;
  810. //
  811. // Check parameters
  812. //
  813. m_csInstanceGuard.Enter();
  814. if ( cookieIn == 0 || cookieIn >= m_cCurrentUsed )
  815. {
  816. hr = THR( E_INVALIDARG );
  817. goto Cleanup;
  818. }
  819. pcsi = m_pCookies[ cookieIn ];
  820. if ( pcsi == NULL )
  821. {
  822. hr = HRESULT_FROM_WIN32( TW32( ERROR_NOT_FOUND ) );
  823. goto Cleanup;
  824. }
  825. hr = THR( HrDeleteInstanceAndChildren( cookieIn ) );
  826. if ( FAILED( hr ) )
  827. {
  828. goto Cleanup;
  829. }
  830. Cleanup:
  831. m_csInstanceGuard.Leave();
  832. HRETURN( hr );
  833. } //*** CObjectManager::RemoveObject
  834. //////////////////////////////////////////////////////////////////////////////
  835. //
  836. // STDMETHODIMP
  837. // CObjectManager::SetObjectStatus(
  838. // OBJECTCOOKIE cookieIn,
  839. // HRESULT hrIn
  840. // )
  841. //
  842. //////////////////////////////////////////////////////////////////////////////
  843. STDMETHODIMP
  844. CObjectManager::SetObjectStatus(
  845. OBJECTCOOKIE cookieIn,
  846. HRESULT hrIn
  847. )
  848. {
  849. TraceFunc( "[IObjectManager]" );
  850. HRESULT hr = S_OK;
  851. CStandardInfo * pcsi;
  852. //
  853. // Check parameters
  854. //
  855. m_csInstanceGuard.Enter();
  856. if ( cookieIn == 0 || cookieIn >= m_cCurrentUsed )
  857. {
  858. hr = THR( E_INVALIDARG );
  859. goto Cleanup;
  860. }
  861. pcsi = m_pCookies[ cookieIn ];
  862. if ( pcsi == NULL )
  863. {
  864. hr = HRESULT_FROM_WIN32( TW32( ERROR_NOT_FOUND ) );
  865. goto Cleanup;
  866. }
  867. //
  868. // Update the status.
  869. //
  870. pcsi->m_hrStatus = hrIn;
  871. Cleanup:
  872. m_csInstanceGuard.Leave();
  873. HRETURN( hr );
  874. } //*** CObjectManager::SetObjectStatus
  875. //****************************************************************************
  876. //
  877. // Privates
  878. //
  879. //****************************************************************************
  880. //////////////////////////////////////////////////////////////////////////////
  881. //
  882. // HRESULT
  883. // CObjectManager::HrDeleteCookie(
  884. // OBJECTCOOKIE cookieIn
  885. // )
  886. //
  887. //////////////////////////////////////////////////////////////////////////////
  888. HRESULT
  889. CObjectManager::HrDeleteCookie(
  890. OBJECTCOOKIE cookieIn
  891. )
  892. {
  893. TraceFunc1( "cookieIn = %#X", cookieIn );
  894. HRESULT hr = S_OK;
  895. CStandardInfo * pcsi;
  896. Assert( cookieIn != 0 && cookieIn < m_cCurrentUsed );
  897. pcsi = m_pCookies[ cookieIn ];
  898. Assert( pcsi != NULL );
  899. pcsi->Release();
  900. m_pCookies[ cookieIn ] = NULL;
  901. HRETURN( hr );
  902. } //*** CObjectManager::HrDeleteCookie
  903. //////////////////////////////////////////////////////////////////////////////
  904. //
  905. // HRESULT
  906. // CObjectManager::HrSearchForExistingCookie(
  907. // OBJECTCOOKIE cookieIn,
  908. // LPUNKNOWN ppunkOut
  909. // )
  910. //
  911. //////////////////////////////////////////////////////////////////////////////
  912. HRESULT
  913. CObjectManager::HrSearchForExistingCookie(
  914. REFCLSID rclsidTypeIn,
  915. OBJECTCOOKIE cookieParentIn,
  916. LPCWSTR pcszNameIn,
  917. OBJECTCOOKIE * pcookieOut
  918. )
  919. {
  920. TraceFunc( "" );
  921. Assert( pcszNameIn != NULL );
  922. Assert( pcookieOut != NULL );
  923. HRESULT hr = S_FALSE;
  924. ULONG idx;
  925. CStandardInfo * pcsi;
  926. //
  927. // Search the list.
  928. //
  929. for( idx = 1; idx < m_cCurrentUsed; idx ++ )
  930. {
  931. pcsi = m_pCookies[ idx ];
  932. if ( pcsi != NULL )
  933. {
  934. if ( pcsi->m_cookieParent == cookieParentIn // matching parents
  935. && IsEqualIID( pcsi->m_clsidType, rclsidTypeIn ) // matching types
  936. && StrCmpI( pcsi->m_bstrName, pcszNameIn ) == 0 // matching names
  937. )
  938. {
  939. //
  940. // Found a match.
  941. //
  942. *pcookieOut = idx;
  943. hr = S_OK;
  944. break; // exit loop
  945. } // if: match
  946. } // if: cookie exists
  947. } // while: pcsi
  948. HRETURN( hr );
  949. } //*** CObjectManager::HrSearchForExistingCookie
  950. //////////////////////////////////////////////////////////////////////////////
  951. //
  952. // HRESULT
  953. // CObjectManager::HrDeleteInstanceAndChildren(
  954. // OBJECTCOOKIE pcsiIn
  955. // )
  956. //
  957. // Notes:
  958. // This should be called while the ListLock is held!
  959. //
  960. //////////////////////////////////////////////////////////////////////////////
  961. HRESULT
  962. CObjectManager::HrDeleteInstanceAndChildren(
  963. OBJECTCOOKIE cookieIn
  964. )
  965. {
  966. TraceFunc1( "cookieIn = %#X", cookieIn );
  967. ULONG idx;
  968. CStandardInfo * pcsi;
  969. HRESULT hr = S_OK;
  970. hr = THR( HrDeleteCookie( cookieIn ) );
  971. if ( FAILED( hr ) )
  972. {
  973. goto Cleanup;
  974. }
  975. for ( idx = 1; idx < m_cCurrentUsed; idx ++ )
  976. {
  977. pcsi = m_pCookies[ idx ];
  978. if ( pcsi != NULL
  979. && pcsi->m_cookieParent == cookieIn )
  980. {
  981. hr = THR( HrDeleteInstanceAndChildren( idx ) );
  982. if ( FAILED( hr ) )
  983. {
  984. goto Cleanup;
  985. }
  986. } // if:
  987. } // while:
  988. Cleanup:
  989. HRETURN( hr );
  990. } //*** CObjectManager::HrDeleteInstanceAndChildren
  991. //////////////////////////////////////////////////////////////////////////////
  992. //
  993. // HRESULT
  994. // CObjectManager::HrCreateNewCookie(
  995. // REFCLSID rclsidTypeIn
  996. // OBJECTCOOKIE cookieParentIn,
  997. // BSTR pcszNameIn,
  998. // OBJECTCOOKIE * pcookieOut
  999. // )
  1000. //
  1001. //////////////////////////////////////////////////////////////////////////////
  1002. HRESULT
  1003. CObjectManager::HrCreateNewCookie(
  1004. REFCLSID rclsidTypeIn,
  1005. OBJECTCOOKIE cookieParentIn,
  1006. LPCWSTR pcszNameIn,
  1007. OBJECTCOOKIE * pcookieOut
  1008. )
  1009. {
  1010. TraceFunc( "" );
  1011. HRESULT hr = S_OK;
  1012. CStandardInfo * pcsi = NULL;
  1013. Assert( pcookieOut != NULL );
  1014. *pcookieOut = 0;
  1015. //
  1016. // Create some space for it.
  1017. //
  1018. if ( m_cCurrentUsed == m_cAllocSize )
  1019. {
  1020. CStandardInfo ** pnew = (CStandardInfo **) TraceAlloc( HEAP_ZERO_MEMORY, sizeof(CStandardInfo *) * ( m_cAllocSize + COOKIE_BUFFER_GROW_SIZE ) );
  1021. if ( pnew == NULL )
  1022. {
  1023. hr = THR( E_OUTOFMEMORY );
  1024. goto Cleanup;
  1025. }
  1026. if ( m_pCookies != NULL )
  1027. {
  1028. CopyMemory( pnew, m_pCookies, sizeof(CStandardInfo *) * m_cCurrentUsed );
  1029. TraceFree( m_pCookies );
  1030. }
  1031. m_pCookies = pnew;
  1032. m_cAllocSize += COOKIE_BUFFER_GROW_SIZE;
  1033. if ( m_cCurrentUsed == 0 )
  1034. {
  1035. //
  1036. // Always skip zero.
  1037. //
  1038. m_cCurrentUsed = 1;
  1039. }
  1040. }
  1041. pcsi = new CStandardInfo();
  1042. if ( pcsi == NULL )
  1043. {
  1044. hr = THR( E_OUTOFMEMORY );
  1045. goto Cleanup;
  1046. }
  1047. hr = THR( pcsi->HrInit() );
  1048. if ( FAILED( hr ) )
  1049. {
  1050. goto Cleanup;
  1051. }
  1052. m_pCookies[ m_cCurrentUsed ] = pcsi;
  1053. //
  1054. // Initialize the rest of the structure.
  1055. //
  1056. pcsi->m_cookieParent = cookieParentIn;
  1057. pcsi->m_hrStatus = E_PENDING;
  1058. CopyMemory( &pcsi->m_clsidType, &rclsidTypeIn, sizeof( pcsi->m_clsidType ) );
  1059. if ( pcszNameIn != NULL )
  1060. {
  1061. pcsi->m_bstrName = TraceSysAllocString( pcszNameIn );
  1062. if ( pcsi->m_bstrName == NULL )
  1063. {
  1064. m_cCurrentUsed --;
  1065. hr = THR( E_OUTOFMEMORY );
  1066. goto Cleanup;
  1067. } // if: out of memory
  1068. }
  1069. Assert( pcsi->m_pci == NULL );
  1070. Assert( pcsi->m_pExtObjList == NULL );
  1071. //
  1072. // Keep it around and return SUCCESS!
  1073. //
  1074. pcsi = NULL;
  1075. *pcookieOut = m_cCurrentUsed;
  1076. m_cCurrentUsed ++;
  1077. hr = S_OK;
  1078. Cleanup:
  1079. if ( pcsi != NULL )
  1080. {
  1081. pcsi->Release();
  1082. }
  1083. HRETURN( hr );
  1084. } //*** CObjectManager::HrCreateNewCookie