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.

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