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.

585 lines
13 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 "nwcompat.hxx"
  15. #pragma hdrstop
  16. // Class CADsExtMgr
  17. CADsExtMgr::CADsExtMgr():
  18. _pClassEntry(NULL),
  19. _pDispMgr(NULL)
  20. {
  21. }
  22. HRESULT
  23. CADsExtMgr::CreateExtMgr(
  24. IUnknown FAR * pUnkOuter,
  25. CAggregatorDispMgr * pDispMgr,
  26. LPTSTR pszClassName,
  27. CADsExtMgr ** ppExtMgr
  28. )
  29. {
  30. PCLASS_ENTRY pClassEntry = NULL;
  31. CADsExtMgr FAR * pExtMgr = NULL;
  32. HRESULT hr = S_OK;
  33. hr = AllocateExtMgrObject(
  34. &pExtMgr
  35. );
  36. BAIL_ON_FAILURE(hr);
  37. //
  38. // Now store the DispatchMgr of the Aggregator
  39. //
  40. pExtMgr->_pDispMgr = pDispMgr;
  41. hr = ADSIGetExtensionList(
  42. pszClassName,
  43. &(pExtMgr->_pClassEntry)
  44. );
  45. if (pExtMgr->_pClassEntry) {
  46. hr = ADSILoadExtensions(
  47. pUnkOuter,
  48. pExtMgr->_pClassEntry
  49. );
  50. }
  51. *ppExtMgr = pExtMgr;
  52. RRETURN(hr);
  53. error:
  54. *ppExtMgr = NULL;
  55. delete pExtMgr;
  56. RRETURN(hr);
  57. }
  58. CADsExtMgr::~CADsExtMgr( )
  59. {
  60. //
  61. // Free the ClassEntry
  62. //
  63. if (_pClassEntry) {
  64. FreeClassEntry(_pClassEntry);
  65. }
  66. //
  67. // And do nothing with the DispMgr - we just keep a pointer
  68. //
  69. }
  70. STDMETHODIMP
  71. CADsExtMgr::QueryInterface(REFIID iid, LPVOID FAR* ppv)
  72. {
  73. PCLASS_ENTRY pClassEntry = _pClassEntry;
  74. IUnknown * pUnknown = NULL;
  75. PINTERFACE_ENTRY pIID = NULL;
  76. PEXTENSION_ENTRY pExtensionEntry = NULL;
  77. HRESULT hr = S_OK;
  78. if (!pClassEntry) {
  79. RRETURN(E_NOINTERFACE);
  80. }
  81. pExtensionEntry = pClassEntry->pExtensionHead;
  82. while (pExtensionEntry) {
  83. pUnknown = pExtensionEntry->pUnknown;
  84. pIID = pExtensionEntry->pIID;
  85. while (pIID) {
  86. if (IsEqualIID(pIID->iid, iid)) {
  87. if (!pUnknown) {
  88. RRETURN(E_NOINTERFACE);
  89. }
  90. hr = pUnknown->QueryInterface(
  91. iid,
  92. ppv
  93. );
  94. RRETURN(hr);
  95. }
  96. pIID = pIID->pNext;
  97. }
  98. pExtensionEntry = pExtensionEntry->pNext;
  99. }
  100. RRETURN(hr = E_NOINTERFACE);
  101. }
  102. HRESULT
  103. CADsExtMgr::AllocateExtMgrObject(
  104. CADsExtMgr ** ppExtMgr
  105. )
  106. {
  107. CADsExtMgr FAR * pExtMgr = NULL;
  108. HRESULT hr = S_OK;
  109. pExtMgr = new CADsExtMgr();
  110. if (pExtMgr == NULL) {
  111. hr = E_OUTOFMEMORY;
  112. }
  113. BAIL_ON_FAILURE(hr);
  114. *ppExtMgr = pExtMgr;
  115. RRETURN(hr);
  116. error:
  117. if (pExtMgr) {
  118. delete pExtMgr;
  119. }
  120. RRETURN(hr);
  121. }
  122. HRESULT
  123. ADSILoadExtensionManager(
  124. LPWSTR pszClassName,
  125. IUnknown * pUnkOuter,
  126. CAggregatorDispMgr * pDispMgr,
  127. CADsExtMgr ** ppExtMgr
  128. )
  129. {
  130. HRESULT hr = S_OK;
  131. hr = CADsExtMgr::CreateExtMgr(
  132. pUnkOuter,
  133. pDispMgr,
  134. pszClassName,
  135. ppExtMgr
  136. );
  137. RRETURN(hr);
  138. }
  139. STDMETHODIMP
  140. CADsExtMgr::GetTypeInfoCount(
  141. unsigned int FAR* pctinfo
  142. )
  143. {
  144. RRETURN(E_NOTIMPL);
  145. }
  146. STDMETHODIMP
  147. CADsExtMgr::GetTypeInfo(
  148. unsigned int itinfo,
  149. LCID lcid,
  150. ITypeInfo FAR* FAR* pptinfo
  151. )
  152. {
  153. RRETURN(E_NOTIMPL);
  154. }
  155. STDMETHODIMP
  156. CADsExtMgr::GetIDsOfNames(
  157. REFIID iid,
  158. LPWSTR FAR* rgszNames,
  159. unsigned int cNames,
  160. LCID lcid,
  161. DISPID FAR* rgdispid
  162. )
  163. {
  164. HRESULT hr = S_OK;
  165. PEXTENSION_ENTRY pExtension = NULL;
  166. IPrivateDispatch FAR * pPrivDisp = NULL;
  167. hr = _pDispMgr->GetIDsOfNames(
  168. iid,
  169. rgszNames,
  170. cNames,
  171. lcid,
  172. rgdispid
  173. );
  174. if (FAILED(hr)) {
  175. if (!_pClassEntry) {
  176. RRETURN(DISP_E_UNKNOWNNAME);
  177. }
  178. pExtension = _pClassEntry->pExtensionHead;
  179. while (pExtension) {
  180. if (pExtension->fDisp) {
  181. //
  182. // fDisp = TRUE indicates
  183. // 1) extension supports pADsExt AND
  184. // 2) either
  185. // a) PrivateGetIDsOfNames() does Not return E_NOTIMPL
  186. // OR
  187. // b) we don't know if a) is true or not yet
  188. //
  189. ASSERT(pExtension->pADsExt);
  190. hr = (pExtension->pADsExt)->PrivateGetIDsOfNames(
  191. iid,
  192. rgszNames,
  193. cNames,
  194. lcid,
  195. rgdispid
  196. );
  197. if (SUCCEEDED(hr)) {
  198. //
  199. // check & prefix extension id to dispid(s) returned
  200. // by extension
  201. //
  202. hr = CheckAndPrefixExtIDArray(
  203. pExtension->dwExtensionID,
  204. cNames,
  205. rgdispid
  206. );
  207. if (SUCCEEDED(hr) )
  208. {
  209. RRETURN(hr);
  210. }
  211. //
  212. // if cannot prefix extension id because NOT ALL
  213. // dispids returned by PrivateGetIDsOfNames() are
  214. // valid, this extension does not support this property
  215. // or method -> try next extension
  216. //
  217. // If the extension returns ANY invalid dispids, then
  218. // we treat the extension as invalid. This way, we can
  219. // see if a later extension exists that supports this
  220. // property or method, instead of just bailing out.
  221. // This is important, since there
  222. // can be multiple extensions and we are supposed to
  223. // "find the first extension which implements a function"
  224. // (per ADSI SDK).
  225. //
  226. }
  227. else if (hr == E_NOTIMPL) {
  228. //
  229. // extension object does not support the optional
  230. // IADsExtension::PrivateGetIDsOfNames()/PrivateInvoke()
  231. // -> remember this in cache & try next extension object
  232. //
  233. pExtension->fDisp = FALSE;
  234. }
  235. else {
  236. //
  237. // extens'n object supports PrivateGetIDsOfNames()/Invoke()
  238. // but does not know about this property or method
  239. // -> try next extension object
  240. //
  241. }
  242. } // end "if (pExtension->pADs && pExtension->fDisp)"
  243. pExtension = pExtension->pNext;
  244. } // end while
  245. }
  246. //
  247. // Unify the final error code retuned to ADSI client to DISP_E_UNKNOWNNAME
  248. //
  249. if ( FAILED(hr) && hr!=E_OUTOFMEMORY) {
  250. hr = DISP_E_UNKNOWNNAME;
  251. }
  252. RRETURN(hr);
  253. }
  254. STDMETHODIMP
  255. CADsExtMgr::Invoke(
  256. DISPID dispidMember,
  257. REFIID iid,
  258. LCID lcid,
  259. unsigned short wFlags,
  260. DISPPARAMS FAR* pdispparams,
  261. VARIANT FAR* pvarResult,
  262. EXCEPINFO FAR* pexcepinfo,
  263. unsigned int FAR* puArgErr
  264. )
  265. {
  266. DWORD dwExtensionId = 0;
  267. HRESULT hr = S_OK;
  268. PEXTENSION_ENTRY pExtension = NULL;
  269. IPrivateDispatch * pPrivDisp = NULL;
  270. DISPID rgExtDispid = DISPID_UNKNOWN;
  271. //
  272. // This could be a special dispatch id - pass it to
  273. // the aggregator
  274. //
  275. if (dispidMember <= 0) {
  276. hr = _pDispMgr->Invoke(
  277. dispidMember,
  278. iid,
  279. lcid,
  280. wFlags,
  281. pdispparams,
  282. pvarResult,
  283. pexcepinfo,
  284. puArgErr
  285. );
  286. RRETURN(hr);
  287. }
  288. //
  289. // It is not a special dispatch id, so compute the extension
  290. // id and pass it to the appropriate dispatch manager
  291. //
  292. dwExtensionId = EXTRACT_EXTENSION_ID(dispidMember);
  293. if (!dwExtensionId) {
  294. hr = _pDispMgr->Invoke(
  295. dispidMember,
  296. iid,
  297. lcid,
  298. wFlags,
  299. pdispparams,
  300. pvarResult,
  301. pexcepinfo,
  302. puArgErr
  303. );
  304. RRETURN(hr);
  305. }
  306. if (!_pClassEntry) {
  307. RRETURN(DISP_E_MEMBERNOTFOUND);
  308. }
  309. pExtension = _pClassEntry->pExtensionHead;
  310. rgExtDispid = REMOVE_EXTENSION_ID(dispidMember);
  311. while (pExtension) {
  312. if (dwExtensionId == pExtension->dwExtensionID) {
  313. if (pExtension->fDisp) {
  314. //
  315. // fDisp = TRUE indicates
  316. // 1) extension supports pADsExt AND
  317. // 2) either
  318. // a) PrivateGetIDsOfNames() does Not return E_NOTIMPL
  319. // OR
  320. // b) we don't know if a) is true or not yet
  321. //
  322. ASSERT(pExtension->pADsExt);
  323. hr = (pExtension->pADsExt)->PrivateInvoke(
  324. rgExtDispid,
  325. iid,
  326. lcid,
  327. wFlags,
  328. pdispparams,
  329. pvarResult,
  330. pexcepinfo,
  331. puArgErr
  332. );
  333. RRETURN(hr);
  334. } else {
  335. //
  336. // A dwExtensionId match indicates THIS extens'n has returned
  337. // a valid dispid to clients thru' pADs->PrivateGetIDsOfNames.
  338. // Thus, fDisp should be TURE.
  339. //
  340. // But since dispid goes thru' clients before passed back to
  341. // PrivateInovke(), don't ASSERT in case of clients errors.
  342. //
  343. RRETURN(DISP_E_MEMBERNOTFOUND);
  344. }
  345. }
  346. pExtension = pExtension->pNext;
  347. } // end while
  348. RRETURN(DISP_E_MEMBERNOTFOUND);
  349. }
  350. HRESULT
  351. CADsExtMgr::CheckAndPrefixExtIDArray(
  352. IN DWORD dwExtensionID,
  353. IN unsigned int cDispids,
  354. IN OUT DISPID * rgDispids
  355. )
  356. {
  357. HRESULT hrEach = S_OK;
  358. HRESULT hrAll = S_OK;
  359. ASSERT_VALID_EXTENSION_ID(dwExtensionID);
  360. for (unsigned int i = 0; i<cDispids; i++)
  361. {
  362. hrEach = CheckAndPrefixExtID(
  363. dwExtensionID,
  364. rgDispids[i],
  365. rgDispids+i
  366. );
  367. if (FAILED(hrEach))
  368. {
  369. hrAll = E_FAIL;
  370. //
  371. // The entire operation is considered as failure as a whole.
  372. // But continue to get other dispid s.t. debugger or user knows
  373. // which dispid in the array is causing problem -> DISPID_UNKOWN
  374. //
  375. }
  376. }
  377. RRETURN(hrAll);
  378. }
  379. HRESULT
  380. CADsExtMgr::CheckAndPrefixExtID(
  381. IN DWORD dwExtensionID,
  382. IN DISPID dispid,
  383. IN OUT DISPID * pNewDispid
  384. )
  385. {
  386. ASSERT(pNewDispid);
  387. if ( (dispid>= ADS_EXT_MINEXTDISPID) &&
  388. (dispid<= ADS_EXT_MAXEXTDISPID) )
  389. {
  390. *pNewDispid = PREFIX_EXTENSION_ID(dwExtensionID, dispid) ;
  391. RRETURN(S_OK);
  392. }
  393. else
  394. {
  395. *pNewDispid = DISPID_UNKNOWN;
  396. RRETURN(E_FAIL);
  397. }
  398. }
  399. //+------------------------------------------------------------------------
  400. //
  401. // Function: CADsExtMgr::FinalInitializeExtensions
  402. //
  403. // Synopsis: At this point we call Operate on all the extensions
  404. // so that they can do initialization stuff that
  405. //
  406. //
  407. //
  408. // Arguments: None
  409. //
  410. // AjayR - added on 1-30-99.
  411. //-------------------------------------------------------------------------
  412. HRESULT
  413. CADsExtMgr::FinalInitializeExtensions()
  414. {
  415. HRESULT hr = S_OK;
  416. PEXTENSION_ENTRY pExtEntry = NULL;
  417. VARIANT varDummy;
  418. VariantInit(&varDummy);
  419. if (!_pClassEntry || !(pExtEntry=_pClassEntry->pExtensionHead) ) {
  420. RRETURN(S_OK);
  421. }
  422. while (pExtEntry) {
  423. //
  424. // Call operate only if the extension supports the interface
  425. //
  426. if (pExtEntry->pADsExt) {
  427. pExtEntry->pADsExt->Operate(
  428. ADS_EXT_INITIALIZE_COMPLETE,
  429. varDummy,
  430. varDummy,
  431. varDummy
  432. );
  433. }
  434. //
  435. // we cannot really do much if there is a failure here
  436. //
  437. pExtEntry = pExtEntry->pNext;
  438. } // end while
  439. //
  440. // Cannot fail because of one bad extension.
  441. //
  442. RRETURN(S_OK); // "okay" error if any, optional support
  443. }