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.

522 lines
12 KiB

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