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.

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