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.

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