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.

1061 lines
25 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1996
  5. //
  6. // File: cextmgr.cxx
  7. //
  8. // Contents: LDAP ExtMgr Object
  9. //
  10. //
  11. // History: 06-15-96 yihsins Created.
  12. //
  13. //----------------------------------------------------------------------------
  14. #include "ldap.hxx"
  15. #pragma hdrstop
  16. // Class CADsExtMgr
  17. CADsExtMgr::CADsExtMgr(
  18. IUnknown FAR * pUnkOuter
  19. ):
  20. _pUnkOuter(pUnkOuter),
  21. _pClassEntry(NULL),
  22. _pDispMgr(NULL),
  23. _pCreds(NULL),
  24. _fExtensionsLoaded(FALSE)
  25. {
  26. }
  27. //
  28. // Static create to handle multiple classes
  29. //
  30. HRESULT
  31. CADsExtMgr::CreateExtMgr(
  32. IUnknown FAR * pUnkOuter,
  33. CAggregatorDispMgr * pDispMgr,
  34. LPWSTR pszClassNames[],
  35. long lnNumClasses,
  36. CCredentials *pCreds,
  37. CADsExtMgr ** ppExtMgr
  38. )
  39. {
  40. long lnCtr = 0;
  41. long lnInc = 1;
  42. PCLASS_ENTRY pClassEntry = NULL;
  43. CADsExtMgr FAR * pExtMgr = NULL;
  44. HRESULT hr = S_OK;
  45. pExtMgr = new CADsExtMgr(pUnkOuter);
  46. if (!pExtMgr)
  47. RRETURN(E_OUTOFMEMORY);
  48. //
  49. // Now store the DispatchMgr of the Aggregator
  50. //
  51. pExtMgr->_pDispMgr = pDispMgr;
  52. pExtMgr->_pCreds = pCreds;
  53. if (_tcsicmp(pszClassNames[lnNumClasses-1], TEXT("Top")) == 0)
  54. lnCtr = 0;
  55. else
  56. lnCtr = lnNumClasses - 1;
  57. lnInc = lnCtr ? -1 : 1;
  58. //
  59. // Read the list of extension object of the same class from registry
  60. //
  61. hr = ADSIGetExtensionList(
  62. pszClassNames[lnCtr],
  63. &(pExtMgr->_pClassEntry)
  64. );
  65. BAIL_ON_FAILURE(hr);
  66. lnCtr += lnInc;
  67. for (;
  68. (lnInc == -1) ? (lnCtr > -1) : (lnCtr < lnNumClasses);
  69. lnCtr += lnInc) {
  70. hr = ADSIAppendToExtensionList(
  71. pszClassNames[lnCtr],
  72. &(pExtMgr->_pClassEntry)
  73. );
  74. BAIL_ON_FAILURE(hr);
  75. }
  76. *ppExtMgr = pExtMgr;
  77. RRETURN(hr);
  78. error:
  79. *ppExtMgr = NULL;
  80. delete pExtMgr;
  81. RRETURN(hr);
  82. }
  83. CADsExtMgr::~CADsExtMgr( )
  84. {
  85. //
  86. // Free the ClassEntry
  87. //
  88. if (_pClassEntry) {
  89. FreeClassEntry(_pClassEntry);
  90. }
  91. //
  92. // And do nothing with the DispMgr, pCreds - we just keep pointers
  93. //
  94. }
  95. //
  96. // Instantiate extension objects listed in _pClassEntry as aggregates of
  97. // aggregator _pUnkOuter. Initialize extensions with <Credentials>.
  98. //
  99. // Max Load 127 extensions. Extensions > 127 are silently ignored.
  100. //
  101. HRESULT
  102. CADsExtMgr::LoadExtensions(
  103. CCredentials &Credentials
  104. )
  105. {
  106. HRESULT hr = S_OK;
  107. PEXTENSION_ENTRY pExtEntry = NULL;
  108. DWORD dwExtensionID = MIN_EXTENSION_ID;
  109. IPrivateDispatch * pPrivDisp = NULL;
  110. LPWSTR pszUserName = NULL;
  111. LPWSTR pszPassword = NULL;
  112. DWORD dwAuthFlags = 0;
  113. VARIANT varUserName;
  114. VARIANT varPassword;
  115. VARIANT varAuthFlags;
  116. PVARIANT pvarUserName = &varUserName;
  117. PVARIANT pvarPassword = &varPassword;
  118. PVARIANT pvarAuthFlags = &varAuthFlags;
  119. BOOL fReturnError = FALSE;
  120. //
  121. // Extensions (ext mgr) do(es) not exist on its own without an aggregator
  122. //
  123. ADsAssert(_pUnkOuter);
  124. //
  125. // If _pClassEntry!=NULL, pClassEntry->pExtensionHead should not
  126. // be NULL either. But just in case a user removes all extension entries
  127. // under a class key without removing the class key itself in the registry,
  128. // we will let it pass and just return S_OK here.
  129. //
  130. if (!_pClassEntry || !(pExtEntry=_pClassEntry->pExtensionHead) ) {
  131. RRETURN(S_OK);
  132. }
  133. VariantInit(pvarUserName);
  134. VariantInit(pvarPassword);
  135. VariantInit(pvarAuthFlags);
  136. hr = Credentials.GetUserName(&pszUserName);
  137. if (FAILED(hr)) {
  138. RRETURN(S_OK);
  139. }
  140. hr = Credentials.GetPassword(&pszPassword);
  141. if (FAILED(hr)) {
  142. RRETURN(S_OK);
  143. }
  144. dwAuthFlags = Credentials.GetAuthFlags();
  145. while (pExtEntry) {
  146. //
  147. // Max # of extension have been loaded, cannot load more
  148. //
  149. if (dwExtensionID>MAX_EXTENSION_ID) {
  150. //
  151. // Terminate loading extensions.
  152. //
  153. break;
  154. }
  155. //
  156. // create extension object (aggregatee) and ask for Non-delegating
  157. // IUnknown. Ref count on extension object = 1.
  158. //
  159. hr = CoCreateInstance(
  160. pExtEntry->ExtCLSID,
  161. _pUnkOuter,
  162. CLSCTX_INPROC_SERVER,
  163. IID_IUnknown,
  164. (void **)&(pExtEntry->pUnknown)
  165. );
  166. //
  167. // if fail, go to next extesion entry s.t. bad individual extension
  168. // cannot block other extensions from loading (no clean up needed)
  169. //
  170. if (SUCCEEDED(hr)) {
  171. pExtEntry->dwExtensionID = dwExtensionID;
  172. hr = (pExtEntry->pUnknown)->QueryInterface(
  173. IID_IADsExtension,
  174. (void **) &(pExtEntry->pADsExt)
  175. );
  176. if (FAILED(hr)) {
  177. //
  178. // extension does not support the optioanl IADsExtension -> OK.
  179. // (no clean up needed)
  180. //
  181. pExtEntry->pADsExt=NULL;
  182. pExtEntry->fDisp = FALSE;
  183. } else {
  184. //
  185. // Cache the interface ptr but call Release() immediately to
  186. // avoid aggregator having a ref count on itself
  187. // since IADsExtension inherits from delegating IUnknown.
  188. //
  189. // Note: codes still works if inherit from NonDelegatingIUknown
  190. //
  191. (pExtEntry->pADsExt)->Release() ;
  192. //
  193. // For efficiency, set this flag to FALSE on FIRST encounter of
  194. // pADsExt->PrivateGetIDsOfNames()/Invoke() returning E_NOTIMPL.
  195. // Set as TRUE now s.t. at least first encounter will happen.
  196. //
  197. pExtEntry->fDisp = TRUE;
  198. //
  199. // Pass its own credentials to extension. Ignore error if any.
  200. //
  201. hr = ADsAllocString(
  202. pszUserName,
  203. &(pvarUserName->bstrVal)
  204. );
  205. if (FAILED(hr)) {
  206. fReturnError = TRUE;
  207. BAIL_ON_FAILURE(hr);
  208. }
  209. V_VT(pvarUserName) = VT_BSTR;
  210. hr = ADsAllocString(
  211. pszPassword,
  212. &(pvarPassword->bstrVal)
  213. );
  214. if (FAILED(hr)) {
  215. fReturnError = TRUE;
  216. BAIL_ON_FAILURE(hr);
  217. }
  218. V_VT(pvarPassword) = VT_BSTR;
  219. V_I4(pvarAuthFlags) = dwAuthFlags;
  220. V_VT(pvarAuthFlags) = VT_I4;
  221. hr = (pExtEntry->pADsExt)->Operate(
  222. ADS_EXT_INITCREDENTIALS,
  223. varUserName,
  224. varPassword,
  225. varAuthFlags
  226. );
  227. //
  228. // Free them as they are reused
  229. //
  230. VariantClear(pvarUserName);
  231. VariantClear(pvarPassword);
  232. }
  233. } // end if CoCreateInstance() succeeded
  234. pExtEntry = pExtEntry->pNext;
  235. //
  236. // ++ extension ID even if creat'n of extension fails just to be safe
  237. // - chuck's stuff :)
  238. //
  239. dwExtensionID++;
  240. } // end while
  241. error:
  242. if (pszUserName) {
  243. FreeADsStr(pszUserName);
  244. }
  245. if (pszPassword) {
  246. FreeADsStr(pszPassword);
  247. }
  248. VariantClear(pvarUserName);
  249. VariantClear(pvarPassword);
  250. VariantClear(pvarAuthFlags);
  251. if (fReturnError) {
  252. RRETURN(hr); // fatal error,
  253. }
  254. else {
  255. RRETURN(S_OK); // "okay" error if any, optional support
  256. }
  257. }
  258. HRESULT
  259. CADsExtMgr::LoadExtensionsIfReqd()
  260. {
  261. HRESULT hr = S_OK;
  262. if(!_fExtensionsLoaded) {
  263. hr = LoadExtensions(*_pCreds);
  264. BAIL_ON_FAILURE(hr);
  265. hr = FinalInitializeExtensions(); // this call never fails
  266. BAIL_ON_FAILURE(hr);
  267. _fExtensionsLoaded = TRUE;
  268. }
  269. RRETURN(S_OK);
  270. error:
  271. RRETURN(hr);
  272. }
  273. STDMETHODIMP
  274. CADsExtMgr::QueryInterface(REFIID iid, LPVOID FAR* ppv)
  275. {
  276. PCLASS_ENTRY pClassEntry = _pClassEntry;
  277. IUnknown * pUnknown = NULL;
  278. PINTERFACE_ENTRY pIID = NULL;
  279. PEXTENSION_ENTRY pExtensionEntry = NULL;
  280. HRESULT hr = S_OK;
  281. if (!pClassEntry) {
  282. RRETURN(E_NOINTERFACE);
  283. }
  284. pExtensionEntry = pClassEntry->pExtensionHead;
  285. while (pExtensionEntry) {
  286. pIID = pExtensionEntry->pIID;
  287. while (pIID) {
  288. if (IsEqualIID(pIID->iid, iid)) {
  289. hr = LoadExtensionsIfReqd();
  290. if (FAILED(hr)) {
  291. RRETURN(E_NOINTERFACE);
  292. }
  293. pUnknown = pExtensionEntry->pUnknown;
  294. if (!pUnknown) {
  295. RRETURN(E_NOINTERFACE);
  296. }
  297. hr = pUnknown->QueryInterface(
  298. iid,
  299. ppv
  300. );
  301. RRETURN(hr);
  302. }
  303. pIID = pIID->pNext;
  304. }
  305. pExtensionEntry = pExtensionEntry->pNext;
  306. }
  307. RRETURN(hr = E_NOINTERFACE);
  308. }
  309. STDMETHODIMP
  310. CADsExtMgr::GetTypeInfoCount(
  311. unsigned int FAR* pctinfo
  312. )
  313. {
  314. RRETURN(E_NOTIMPL);
  315. }
  316. STDMETHODIMP
  317. CADsExtMgr::GetTypeInfo(
  318. unsigned int itinfo,
  319. LCID lcid,
  320. ITypeInfo FAR* FAR* pptinfo
  321. )
  322. {
  323. RRETURN(E_NOTIMPL);
  324. }
  325. STDMETHODIMP
  326. CADsExtMgr::GetIDsOfNames(
  327. REFIID iid,
  328. LPWSTR FAR* rgszNames,
  329. unsigned int cNames,
  330. LCID lcid,
  331. DISPID FAR* rgdispid
  332. )
  333. {
  334. HRESULT hr = S_OK;
  335. PEXTENSION_ENTRY pExtension = NULL;
  336. IPrivateDispatch FAR * pPrivDisp = NULL;
  337. hr = _pDispMgr->GetIDsOfNames(
  338. iid,
  339. rgszNames,
  340. cNames,
  341. lcid,
  342. rgdispid
  343. );
  344. if (FAILED(hr)) {
  345. if (!_pClassEntry) {
  346. RRETURN(DISP_E_UNKNOWNNAME);
  347. }
  348. hr = LoadExtensionsIfReqd();
  349. if (FAILED(hr)) {
  350. RRETURN(DISP_E_UNKNOWNNAME);
  351. }
  352. pExtension = _pClassEntry->pExtensionHead;
  353. while (pExtension) {
  354. if (pExtension->fDisp) {
  355. //
  356. // fDisp = TRUE indicates
  357. // 1) extension supports pADsExt AND
  358. // 2) either
  359. // a) PrivateGetIDsOfNames() does Not return E_NOTIMPL
  360. // OR
  361. // b) we don't know if a) is true or not yet
  362. //
  363. ADsAssert(pExtension->pADsExt);
  364. hr = (pExtension->pADsExt)->PrivateGetIDsOfNames(
  365. iid,
  366. rgszNames,
  367. cNames,
  368. lcid,
  369. rgdispid
  370. );
  371. if (SUCCEEDED(hr)) {
  372. //
  373. // check & prefix extension id to dispid(s) returned
  374. // by extension
  375. //
  376. hr = CheckAndPrefixExtIDArray(
  377. pExtension->dwExtensionID,
  378. cNames,
  379. rgdispid
  380. );
  381. if (SUCCEEDED(hr) )
  382. {
  383. RRETURN(hr);
  384. }
  385. //
  386. // if cannot prefix extension id because NOT ALL
  387. // dispids returned by PrivateGetIDsOfNames() are
  388. // valid, this extension does not support this property
  389. // or method -> try next extension
  390. //
  391. }
  392. else if (hr == E_NOTIMPL) {
  393. //
  394. // extension object does not support the optional
  395. // IADsExtension::PrivateGetIDsOfNames()/PrivateInvoke()
  396. // -> remember this in cache & try next extension object
  397. //
  398. pExtension->fDisp = FALSE;
  399. }
  400. else {
  401. //
  402. // extens'n object supports PrivateGetIDsOfNames()/Invoke()
  403. // but does not know about this property or method
  404. // -> try next extension object
  405. //
  406. }
  407. } // end "if (pExtension->pADs && pExtension->fDisp)"
  408. pExtension = pExtension->pNext;
  409. } // end while
  410. }
  411. //
  412. // Unify the final error code retuned to ADSI client to DISP_E_UNKNOWNNAME
  413. //
  414. if ( FAILED(hr) && hr!=E_OUTOFMEMORY) {
  415. hr = DISP_E_UNKNOWNNAME;
  416. }
  417. RRETURN(hr);
  418. }
  419. STDMETHODIMP
  420. CADsExtMgr::Invoke(
  421. DISPID dispidMember,
  422. REFIID iid,
  423. LCID lcid,
  424. unsigned short wFlags,
  425. DISPPARAMS FAR* pdispparams,
  426. VARIANT FAR* pvarResult,
  427. EXCEPINFO FAR* pexcepinfo,
  428. unsigned int FAR* puArgErr
  429. )
  430. {
  431. DWORD dwExtensionId = 0;
  432. HRESULT hr = S_OK;
  433. PEXTENSION_ENTRY pExtension = NULL;
  434. IPrivateDispatch * pPrivDisp = NULL;
  435. DISPID rgExtDispid = DISPID_UNKNOWN;
  436. //
  437. // This could be a special dispatch id - pass it to
  438. // the aggregator
  439. //
  440. if (dispidMember <= 0) {
  441. hr = _pDispMgr->Invoke(
  442. dispidMember,
  443. iid,
  444. lcid,
  445. wFlags,
  446. pdispparams,
  447. pvarResult,
  448. pexcepinfo,
  449. puArgErr
  450. );
  451. RRETURN(hr);
  452. }
  453. //
  454. // It is not a special dispatch id, so compute the extension
  455. // id and pass it to the appropriate dispatch manager
  456. //
  457. dwExtensionId = EXTRACT_EXTENSION_ID(dispidMember);
  458. if (!dwExtensionId) {
  459. hr = _pDispMgr->Invoke(
  460. dispidMember,
  461. iid,
  462. lcid,
  463. wFlags,
  464. pdispparams,
  465. pvarResult,
  466. pexcepinfo,
  467. puArgErr
  468. );
  469. RRETURN(hr);
  470. }
  471. if (!_pClassEntry) {
  472. RRETURN(DISP_E_MEMBERNOTFOUND);
  473. }
  474. //
  475. // Not really neede but just in case.
  476. //
  477. hr = LoadExtensionsIfReqd();
  478. if (FAILED(hr)) {
  479. RRETURN(DISP_E_MEMBERNOTFOUND);
  480. }
  481. pExtension = _pClassEntry->pExtensionHead;
  482. rgExtDispid = REMOVE_EXTENSION_ID(dispidMember);
  483. while (pExtension) {
  484. if (dwExtensionId == pExtension->dwExtensionID) {
  485. if (pExtension->fDisp) {
  486. //
  487. // fDisp = TRUE indicates
  488. // 1) extension supports pADsExt AND
  489. // 2) either
  490. // a) PrivateGetIDsOfNames() does Not return E_NOTIMPL
  491. // OR
  492. // b) we don't know if a) is true or not yet (client bug)
  493. //
  494. ADsAssert(pExtension->pADsExt);
  495. hr = (pExtension->pADsExt)->PrivateInvoke(
  496. rgExtDispid,
  497. iid,
  498. lcid,
  499. wFlags,
  500. pdispparams,
  501. pvarResult,
  502. pexcepinfo,
  503. puArgErr
  504. );
  505. RRETURN(hr);
  506. } else {
  507. //
  508. // A dwExtensionId match indicates THIS extens'n has returned
  509. // a valid dispid to clients thru' pADs->PrivateGetIDsOfNames.
  510. // Thus, fDisp should be TURE.
  511. //
  512. // But since dispid goes thru' clients before passed back to
  513. // PrivateInovke(), don't ASSERT in case of clients errors.
  514. //
  515. RRETURN(DISP_E_MEMBERNOTFOUND);
  516. }
  517. }
  518. pExtension = pExtension->pNext;
  519. } // end while
  520. RRETURN(DISP_E_MEMBERNOTFOUND);
  521. }
  522. HRESULT
  523. CADsExtMgr::CheckAndPrefixExtIDArray(
  524. IN DWORD dwExtensionID,
  525. IN unsigned int cDispids,
  526. IN OUT DISPID * rgDispids
  527. )
  528. {
  529. HRESULT hrEach = S_OK;
  530. HRESULT hrAll = S_OK;
  531. ASSERT_VALID_EXTENSION_ID(dwExtensionID);
  532. for (unsigned int i = 0; i<cDispids; i++)
  533. {
  534. hrEach = CheckAndPrefixExtID(
  535. dwExtensionID,
  536. rgDispids[i],
  537. rgDispids+i
  538. );
  539. if (FAILED(hrEach))
  540. {
  541. hrAll = E_FAIL;
  542. //
  543. // The entire operation is considered as failure as a whole.
  544. // But continue to get other dispid s.t. debugger or user knows
  545. // which dispid in the array is causing problem -> DISPID_UNKOWN
  546. //
  547. }
  548. }
  549. RRETURN(hrAll);
  550. }
  551. HRESULT
  552. CADsExtMgr::CheckAndPrefixExtID(
  553. IN DWORD dwExtensionID,
  554. IN DISPID dispid,
  555. IN OUT DISPID * pNewDispid
  556. )
  557. {
  558. ADsAssert(pNewDispid);
  559. if ( (dispid>= ADS_EXT_MINEXTDISPID) &&
  560. (dispid<= ADS_EXT_MAXEXTDISPID) )
  561. {
  562. *pNewDispid = PREFIX_EXTENSION_ID(dwExtensionID, dispid) ;
  563. RRETURN(S_OK);
  564. }
  565. else
  566. {
  567. *pNewDispid = DISPID_UNKNOWN;
  568. RRETURN(E_FAIL);
  569. }
  570. }
  571. //+------------------------------------------------------------------------
  572. //
  573. // Function: CADsExtMgr::FinalInitializeExtensions
  574. //
  575. // Synopsis: At this point we call Operate on all the extensions
  576. // so that they can do initialization stuff that
  577. //
  578. //
  579. //
  580. // Arguments: None
  581. //
  582. // AjayR - added on 1-27-99.
  583. //-------------------------------------------------------------------------
  584. HRESULT
  585. CADsExtMgr::FinalInitializeExtensions()
  586. {
  587. HRESULT hr = S_OK;
  588. PEXTENSION_ENTRY pExtEntry = NULL;
  589. VARIANT vDummy;
  590. VariantInit(&vDummy);
  591. //
  592. // Extensions (ext mgr) does not exist on its own without an aggregator
  593. //
  594. ADsAssert(_pUnkOuter);
  595. //
  596. // If _pClassEntry!=NULL, pClassEntry->pExtensionHead should not
  597. // be NULL either. But just in case a user removes all extension entries
  598. // under a class key without removing the class key itself in the registry,
  599. // we will let it pass and just return S_OK here.
  600. //
  601. if (!_pClassEntry || !(pExtEntry=_pClassEntry->pExtensionHead) ) {
  602. RRETURN(S_OK);
  603. }
  604. while (pExtEntry) {
  605. //
  606. // Call operate only if the extension supports the interface
  607. //
  608. if (pExtEntry->pADsExt) {
  609. hr = (pExtEntry->pADsExt)->Operate(
  610. ADS_EXT_INITIALIZE_COMPLETE,
  611. vDummy,
  612. vDummy,
  613. vDummy
  614. );
  615. }
  616. //
  617. // we cannot really do much if there is a failure here
  618. //
  619. pExtEntry = pExtEntry->pNext;
  620. } // end while
  621. //
  622. // We need to return S_OK here as otherwise just because
  623. // the final initialization of one extension failed - we
  624. // will hold up the entire lot.
  625. //
  626. RRETURN(S_OK);
  627. }
  628. //+---------------------------------------------------------------------------
  629. // Function: GetCLSIDForIID --- used in supporting ICustomInterfaceFactory
  630. //
  631. // Synopsis: Returns the CLSID corresponding to a given interface IID.
  632. // If the IID is one of the interfaces implemented by the
  633. // extension manager, then the extension's CLSID is returned.
  634. //
  635. // Arguments: riid - Interface ID for which we want to find the CLSID
  636. // lFlags - Reserved. Must be 0.
  637. // pCLSID - Returns the CLSID corresponding to the IID.
  638. //
  639. // Returns: S_OK on success. Error code otherwise.
  640. //
  641. // Modifies: *pCLSID to return CLSID.
  642. //
  643. //----------------------------------------------------------------------------
  644. STDMETHODIMP
  645. CADsExtMgr::GetCLSIDForIID(
  646. REFIID riid,
  647. long lFlags,
  648. CLSID *pCLSID
  649. )
  650. {
  651. PCLASS_ENTRY pClassEntry = _pClassEntry;
  652. PEXTENSION_ENTRY pExtensionEntry = NULL;
  653. PINTERFACE_ENTRY pIID = NULL;
  654. HRESULT hr = S_OK;
  655. ADsAssert(!lFlags && pCLSID);
  656. if (!pClassEntry) {
  657. RRETURN(UMI_E_NOT_FOUND);
  658. }
  659. pExtensionEntry = pClassEntry->pExtensionHead;
  660. while (pExtensionEntry) {
  661. pIID = pExtensionEntry->pIID;
  662. while (pIID) {
  663. if (IsEqualIID(pIID->iid, riid)) {
  664. *pCLSID = pExtensionEntry->ExtCLSID;
  665. RRETURN(S_OK);
  666. }
  667. pIID = pIID->pNext;
  668. }
  669. pExtensionEntry = pExtensionEntry->pNext;
  670. }
  671. RRETURN(hr = UMI_E_NOT_FOUND);
  672. }
  673. //+---------------------------------------------------------------------------
  674. // Function: GetObjectByCLSID --- Used for ICustomInterfaceFactory support.
  675. //
  676. // Synopsis: Returns a pointer to a requested interface on the object
  677. // specified by a CLSID. The object specified by the CLSID is
  678. // aggregated by the specified outer unknown on return. The
  679. // interface returned is a non-delegating interface on the object.
  680. //
  681. // Arguments: clsid - CLSID of object on which interface
  682. // should be obtained
  683. // pUnkOuter - Aggregating outer unknown
  684. // riid - Interface requested
  685. // ppInterface - Returns requested interface
  686. //
  687. // Returns: UMI_S_NO_ERROR on success. Error code otherwise.
  688. //
  689. // Modifies: *ppInterface to return requested interface
  690. //
  691. //----------------------------------------------------------------------------
  692. STDMETHODIMP
  693. CADsExtMgr::GetObjectByCLSID(
  694. CLSID clsid,
  695. IUnknown *pUnkOuter,
  696. REFIID riid,
  697. void **ppInterface
  698. )
  699. {
  700. PCLASS_ENTRY pClassEntry = _pClassEntry;
  701. PEXTENSION_ENTRY pExtensionEntry = NULL;
  702. HRESULT hr = S_OK;
  703. IUnknown *pPrevUnk = NULL, *pUnknown = NULL;
  704. ADsAssert(ppInterface && pUnkOuter);
  705. if (!pClassEntry) {
  706. RRETURN(UMI_E_NOT_FOUND);
  707. }
  708. pExtensionEntry = pClassEntry->pExtensionHead;
  709. while (pExtensionEntry) {
  710. if (IsEqualCLSID(pExtensionEntry->ExtCLSID, clsid)) {
  711. pPrevUnk = _pUnkOuter;
  712. _pUnkOuter = pUnkOuter;
  713. hr = LoadExtensionsIfReqd();
  714. if (FAILED(hr)) {
  715. _pUnkOuter = pPrevUnk;
  716. BAIL_ON_FAILURE(hr = E_FAIL);
  717. }
  718. pUnknown = pExtensionEntry->pUnknown;
  719. if (!pUnknown) {
  720. BAIL_ON_FAILURE(hr = E_FAIL);
  721. }
  722. *ppInterface = pUnknown;
  723. pUnknown->AddRef();
  724. BAIL_ON_FAILURE(hr);
  725. RRETURN(S_OK);
  726. }
  727. pExtensionEntry = pExtensionEntry->pNext;
  728. }
  729. RRETURN(UMI_E_NOT_FOUND);
  730. error:
  731. RRETURN(hr);
  732. }
  733. //+---------------------------------------------------------------------------
  734. // Function: GetCLSIDForNames --- Used for ICustomInterfaceFactory support.
  735. //
  736. // Synopsis: Returns the CLSID of the object that supports a specified
  737. // method/property. Also returns DISPIDs for the property/method.
  738. //
  739. // Arguments: rgszNames - Names to be mapped
  740. // cNames - Number of names to be mapped
  741. // lcid - Locale in which to interpret the names
  742. // rgDispId - Returns DISPID
  743. // lFlags - Reserved. Must be 0.
  744. // pCLSID - Returns CLSID of object which supports this
  745. // property/method.
  746. //
  747. // Returns: S_OK on success. Error code otherwise.
  748. //
  749. // Modifies: *pCLSID to return the CLSID.
  750. // *rgDispId to return the DISPIDs.
  751. //
  752. //----------------------------------------------------------------------------
  753. STDMETHODIMP
  754. CADsExtMgr::GetCLSIDForNames(
  755. LPOLESTR *rgszNames,
  756. UINT cNames,
  757. LCID lcid,
  758. DISPID *rgDispId,
  759. long lFlags,
  760. CLSID *pCLSID
  761. )
  762. {
  763. HRESULT hr = S_OK;
  764. PEXTENSION_ENTRY pExtension = NULL;
  765. ADsAssert(pCLSID && !lFlags && rgszNames && rgDispId);
  766. if (!_pClassEntry) {
  767. RRETURN(DISP_E_UNKNOWNNAME);
  768. }
  769. hr = LoadExtensionsIfReqd();
  770. if (FAILED(hr)) {
  771. RRETURN(DISP_E_UNKNOWNNAME);
  772. }
  773. pExtension = _pClassEntry->pExtensionHead;
  774. while (pExtension) {
  775. if (pExtension->fDisp) {
  776. //
  777. // fDisp = TRUE indicates
  778. // 1) extension supports pADsExt AND
  779. // 2) either
  780. // a) PrivateGetIDsOfNames() does Not return E_NOTIMPL
  781. // OR
  782. // b) we don't know if a) is true or not yet
  783. //
  784. ADsAssert(pExtension->pADsExt);
  785. hr = (pExtension->pADsExt)->PrivateGetIDsOfNames(
  786. IID_NULL,
  787. rgszNames,
  788. cNames,
  789. lcid,
  790. rgDispId
  791. );
  792. if (SUCCEEDED(hr)) {
  793. *pCLSID = pExtension->ExtCLSID;
  794. RRETURN(S_OK);
  795. }
  796. else if (hr == E_NOTIMPL) {
  797. //
  798. // extension object does not support the optional
  799. // IADsExtension::PrivateGetIDsOfNames()/PrivateInvoke()
  800. // -> remember this in cache & try next extension object
  801. //
  802. pExtension->fDisp = FALSE;
  803. }
  804. }
  805. pExtension = pExtension->pNext;
  806. } // end while
  807. RRETURN(hr = DISP_E_UNKNOWNNAME);
  808. }