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.

576 lines
16 KiB

  1. /*===================================================================
  2. Microsoft Denali
  3. Microsoft Confidential.
  4. Copyright 1996 Microsoft Corporation. All Rights Reserved.
  5. Component: IDispatch implementation
  6. File: Dispatch.h
  7. Owner: DGottner
  8. This file contains our implementation of IDispatch
  9. ===================================================================*/
  10. #include "denpre.h"
  11. #pragma hdrstop
  12. #include "dispatch.h"
  13. #include "asptlb.h"
  14. #include "memchk.h"
  15. #ifdef USE_LOCALE
  16. extern DWORD g_dwTLS;
  17. #endif
  18. extern LONG g_nOOMErrors;
  19. CComTypeInfoHolder CDispatchImpl<IApplicationObject>::gm_tih = {&__uuidof(IApplicationObject), &LIBID_ASPTypeLibrary, 3, 0, NULL, 0, NULL, 0};
  20. CComTypeInfoHolder CDispatchImpl<IASPError>::gm_tih = {&__uuidof(IASPError), &LIBID_ASPTypeLibrary, 3, 0, NULL, 0, NULL, 0};
  21. CComTypeInfoHolder CDispatchImpl<IReadCookie>::gm_tih = {&__uuidof(IReadCookie), &LIBID_ASPTypeLibrary, 3, 0, NULL, 0, NULL, 0};
  22. CComTypeInfoHolder CDispatchImpl<IRequest>::gm_tih = {&__uuidof(IRequest), &LIBID_ASPTypeLibrary, 3, 0, NULL, 0, NULL, 0};
  23. CComTypeInfoHolder CDispatchImpl<IRequestDictionary>::gm_tih = {&__uuidof(IRequestDictionary), &LIBID_ASPTypeLibrary, 3, 0, NULL, 0, NULL, 0};
  24. CComTypeInfoHolder CDispatchImpl<IResponse>::gm_tih = {&__uuidof(IResponse), &LIBID_ASPTypeLibrary, 3, 0, NULL, 0, NULL, 0};
  25. CComTypeInfoHolder CDispatchImpl<IScriptingContext>::gm_tih = {&__uuidof(IScriptingContext), &LIBID_ASPTypeLibrary, 3, 0, NULL, 0, NULL, 0};
  26. CComTypeInfoHolder CDispatchImpl<IServer>::gm_tih = {&__uuidof(IServer), &LIBID_ASPTypeLibrary, 3, 0, NULL, 0, NULL, 0};
  27. CComTypeInfoHolder CDispatchImpl<ISessionObject>::gm_tih = {&__uuidof(ISessionObject), &LIBID_ASPTypeLibrary, 3, 0, NULL, 0, NULL, 0};
  28. CComTypeInfoHolder CDispatchImpl<IStringList>::gm_tih = {&__uuidof(IStringList), &LIBID_ASPTypeLibrary, 3, 0, NULL, 0, NULL, 0};
  29. CComTypeInfoHolder CDispatchImpl<IVariantDictionary>::gm_tih = {&__uuidof(IVariantDictionary), &LIBID_ASPTypeLibrary, 3, 0, NULL, 0, NULL, 0};
  30. CComTypeInfoHolder CDispatchImpl<IWriteCookie>::gm_tih = {&__uuidof(IWriteCookie), &LIBID_ASPTypeLibrary, 3, 0, NULL, 0, NULL, 0};
  31. CComTypeInfoHolder CDispatchImpl<IASPObjectContext>::gm_tih = {&__uuidof(IASPObjectContext), &LIBID_ASPObjectContextTypeLibrary, 3, 0, NULL, 0, NULL, 0};
  32. /*===================================================================
  33. CDispatch::CDispatch
  34. CDispatch::~CDispatch
  35. Parameters (Constructor):
  36. pUnkObj pointer to the object we're in.
  37. pUnkOuter LPUNKNOWN to which we delegate.
  38. ===================================================================*/
  39. CDispatch::CDispatch()
  40. {
  41. m_pITINeutral = NULL;
  42. m_pITypeLib = NULL;
  43. m_pGuidDispInterface = NULL;
  44. }
  45. void CDispatch::Init
  46. (
  47. const GUID &GuidDispInterface,
  48. const ITypeLib *pITypeLib // = NULL
  49. )
  50. {
  51. m_pGuidDispInterface = &GuidDispInterface;
  52. m_pITypeLib = const_cast<ITypeLib *>(pITypeLib);
  53. }
  54. CDispatch::~CDispatch(void)
  55. {
  56. ReleaseInterface(m_pITINeutral);
  57. return;
  58. }
  59. /*===================================================================
  60. CDispatch::GetTypeInfoCount
  61. Returns the number of type information (ITypeInfo) interfaces
  62. that the object provides (0 or 1).
  63. Parameters:
  64. pcInfo UINT * to the location to receive
  65. the count of interfaces.
  66. Return Value:
  67. HRESULT S_OK or a general error code.
  68. ===================================================================*/
  69. STDMETHODIMP CDispatch::GetTypeInfoCount(UINT *pcInfo)
  70. {
  71. // We implement GetTypeInfo so return 1
  72. *pcInfo = 1;
  73. return S_OK;
  74. }
  75. /*===================================================================
  76. CDispatch::GetTypeInfo
  77. Retrieves type information for the automation interface. This
  78. is used anywhere that the right ITypeInfo interface is needed
  79. for whatever LCID is applicable. Specifically, this is used
  80. from within GetIDsOfNames and Invoke.
  81. Parameters:
  82. itInfo UINT reserved. Must be zero.
  83. lcid LCID providing the locale for the type
  84. information. If the object does not support
  85. localization, this is ignored.
  86. ppITypeInfo ITypeInfo ** in which to store the ITypeInfo
  87. interface for the object.
  88. Return Value:
  89. HRESULT S_OK or a general error code.
  90. ===================================================================*/
  91. STDMETHODIMP CDispatch::GetTypeInfo(
  92. UINT itInfo,
  93. LCID lcid,
  94. ITypeInfo **ppITypeInfo
  95. )
  96. {
  97. HRESULT hr;
  98. ITypeInfo **ppITI = NULL;
  99. if (0 != itInfo)
  100. return ResultFromScode(TYPE_E_ELEMENTNOTFOUND);
  101. if (NULL == ppITypeInfo)
  102. return ResultFromScode(E_POINTER);
  103. *ppITypeInfo = NULL;
  104. // We don't internationalize the type library, so
  105. // we always return the same one, regardless of the locale.
  106. ppITI = &m_pITINeutral;
  107. //Load a type lib if we don't have the information already.
  108. if (NULL == *ppITI)
  109. {
  110. ITypeLib *pITL;
  111. // If a specific TypeLib was given at init time use that, otherwise default to the main one
  112. if (m_pITypeLib == NULL)
  113. pITL = Glob(pITypeLibDenali);
  114. else
  115. pITL = m_pITypeLib;
  116. Assert(pITL != NULL);
  117. hr = pITL->GetTypeInfoOfGuid(*m_pGuidDispInterface, ppITI);
  118. if (FAILED(hr))
  119. return hr;
  120. // Save the type info in a class member, so we don't have
  121. // go through all this work again;
  122. m_pITINeutral = *ppITI;
  123. }
  124. /*
  125. * Note: the type library is still loaded since we have
  126. * an ITypeInfo from it.
  127. */
  128. (*ppITI)->AddRef();
  129. *ppITypeInfo = *ppITI;
  130. return S_OK;
  131. }
  132. /*===================================================================
  133. CDispatch::GetIDsOfNames
  134. Converts text names into DISPIDs to pass to Invoke
  135. Parameters:
  136. riid REFIID reserved. Must be IID_NULL.
  137. rgszNames OLECHAR ** pointing to the array of names to be mapped.
  138. cNames UINT number of names to be mapped.
  139. lcid LCID of the locale.
  140. rgDispID DISPID * caller allocated array containing IDs
  141. corresponging to those names in rgszNames.
  142. Return Value:
  143. HRESULT S_OK or a general error code.
  144. ===================================================================*/
  145. STDMETHODIMP CDispatch::GetIDsOfNames
  146. (
  147. REFIID riid,
  148. OLECHAR **rgszNames,
  149. UINT cNames,
  150. LCID lcid,
  151. DISPID *rgDispID
  152. )
  153. {
  154. HRESULT hr;
  155. ITypeInfo *pTI;
  156. if (IID_NULL != riid)
  157. return ResultFromScode(DISP_E_UNKNOWNINTERFACE);
  158. //Get the right ITypeInfo for lcid.
  159. hr = GetTypeInfo(0, lcid, &pTI);
  160. if (SUCCEEDED(hr))
  161. {
  162. hr = DispGetIDsOfNames(pTI, rgszNames, cNames, rgDispID);
  163. pTI->Release();
  164. }
  165. return hr;
  166. }
  167. /*===================================================================
  168. CDispatch::Invoke
  169. Calls a method in the dispatch interface or manipulates a property.
  170. Parameters:
  171. dispID DISPID of the method or property of interest.
  172. riid REFIID reserved, must be IID_NULL.
  173. lcid LCID of the locale.
  174. wFlags USHORT describing the context of the invocation.
  175. pDispParams DISPPARAMS * to the array of arguments.
  176. pVarResult VARIANT * in which to store the result. Is
  177. NULL if the caller is not interested.
  178. pExcepInfo EXCEPINFO * to exception information.
  179. puArgErr UINT * in which to store the index of an
  180. invalid parameter if DISP_E_TYPEMISMATCH
  181. is returned.
  182. Return Value:
  183. HRESULT S_OK or a general error code.
  184. ===================================================================*/
  185. STDMETHODIMP CDispatch::Invoke
  186. (
  187. DISPID dispID,
  188. REFIID riid,
  189. LCID lcid,
  190. unsigned short wFlags,
  191. DISPPARAMS *pDispParams,
  192. VARIANT *pVarResult,
  193. EXCEPINFO *pExcepInfo,
  194. UINT *puArgErr
  195. )
  196. {
  197. HRESULT hr;
  198. ITypeInfo *pTI;
  199. LANGID langID = PRIMARYLANGID(lcid);
  200. // riid is supposed to be IID_NULL always
  201. if (IID_NULL != riid)
  202. return ResultFromScode(DISP_E_UNKNOWNINTERFACE);
  203. // Get the ITypeInfo for lcid
  204. hr = GetTypeInfo(0, lcid, &pTI);
  205. if (FAILED(hr))
  206. return hr;
  207. #ifdef USE_LOCALE
  208. // This saves the language ID for this thread
  209. TlsSetValue(g_dwTLS, &langID);
  210. #endif
  211. // Clear exceptions
  212. SetErrorInfo(0L, NULL);
  213. // VBScript does not distinguish between a propget and a method
  214. // implement that behavior for other languages.
  215. //
  216. if (wFlags & (DISPATCH_METHOD | DISPATCH_PROPERTYGET))
  217. wFlags |= DISPATCH_METHOD | DISPATCH_PROPERTYGET;
  218. // This is exactly what DispInvoke does--so skip the overhead.
  219. // With dual interface, "this" is the address of the object AND its dispinterface
  220. //
  221. hr = pTI->Invoke(this, dispID, wFlags,
  222. pDispParams, pVarResult, pExcepInfo, puArgErr);
  223. // Exception handling is done within ITypeInfo::Invoke
  224. pTI->Release();
  225. return hr;
  226. }
  227. /*===================================================================
  228. CSupportErrorInfo::CSupportErrorInfo
  229. Default constructor so that the Init method can be used.
  230. Parameters (Constructor):
  231. pObj PCResponse of the object we're in.
  232. pUnkOuter LPUNKNOWN to which we delegate.
  233. ===================================================================*/
  234. CSupportErrorInfo::CSupportErrorInfo(void)
  235. : m_pUnkObj(NULL),
  236. m_pUnkOuter(NULL)
  237. {
  238. }
  239. /*===================================================================
  240. CSupportErrorInfo::CSupportErrorInfo
  241. Parameters (Constructor):
  242. pObj PCResponse of the object we're in.
  243. pUnkOuter LPUNKNOWN to which we delegate.
  244. GuidDispInterface GUID of dispatch interface.
  245. ===================================================================*/
  246. CSupportErrorInfo::CSupportErrorInfo(IUnknown *pUnkObj, IUnknown *pUnkOuter, const GUID &GuidDispInterface)
  247. {
  248. m_pUnkObj = pUnkObj;
  249. m_pUnkOuter = (pUnkOuter == NULL)? pUnkObj : pUnkOuter;
  250. m_pGuidDispInterface = &GuidDispInterface;
  251. }
  252. /*===================================================================
  253. void CSupportErrorInfo::Init
  254. Parameters:
  255. pObj PCResponse of the object we're in.
  256. pUnkOuter LPUNKNOWN to which we delegate.
  257. GuidDispInterface GUID of dispatch interface.
  258. Returns:
  259. Nothing
  260. ===================================================================*/
  261. void CSupportErrorInfo::Init(IUnknown *pUnkObj, IUnknown *pUnkOuter, const GUID &GuidDispInterface)
  262. {
  263. m_pUnkObj = pUnkObj;
  264. m_pUnkOuter = (pUnkOuter == NULL)? pUnkObj : pUnkOuter;
  265. m_pGuidDispInterface = &GuidDispInterface;
  266. }
  267. /*===================================================================
  268. CSupportErrorInfo::QueryInterface
  269. CSupportErrorInfo::AddRef
  270. CSupportErrorInfo::Release
  271. IUnknown members for CSupportErrorInfo object.
  272. ===================================================================*/
  273. STDMETHODIMP CSupportErrorInfo::QueryInterface(const GUID &Iid, void **ppvObj)
  274. {
  275. return m_pUnkOuter->QueryInterface(Iid, ppvObj);
  276. }
  277. STDMETHODIMP_(ULONG) CSupportErrorInfo::AddRef(void)
  278. {
  279. return m_pUnkOuter->AddRef();
  280. }
  281. STDMETHODIMP_(ULONG) CSupportErrorInfo::Release(void)
  282. {
  283. return m_pUnkOuter->Release();
  284. }
  285. /*===================================================================
  286. CSupportErrorInfo::InterfaceSupportsErrorInfo
  287. Informs a caller whether or not a specific interface
  288. supports exceptions through the Set/GetErrorInfo mechanism.
  289. Parameters:
  290. riid REFIID of the interface in question.
  291. Return Value:
  292. HRESULT S_OK if a call to GetErrorInfo will succeed
  293. for callers of riid. S_FALSE if not.
  294. ===================================================================*/
  295. STDMETHODIMP CSupportErrorInfo::InterfaceSupportsErrorInfo
  296. (
  297. REFIID riid
  298. )
  299. {
  300. if (IID_IDispatch == riid || *m_pGuidDispInterface == riid)
  301. return S_OK;
  302. return ResultFromScode(S_FALSE);
  303. }
  304. /*===================================================================
  305. Exception
  306. Raises an exception using the CreateErrorInfo API and the
  307. ICreateErrorInfo interface.
  308. Note that this method doesn't allow for deferred filling
  309. of an EXCEPINFO structure.
  310. Parameters:
  311. strSource LPOLESTR the exception source
  312. strDescr LPOLESTR the exception description
  313. Returns:
  314. Nothing
  315. ===================================================================*/
  316. void Exception
  317. (
  318. REFIID ObjID,
  319. LPOLESTR strSource,
  320. LPOLESTR strDescr
  321. )
  322. {
  323. HRESULT hr;
  324. ICreateErrorInfo *pICreateErr;
  325. IErrorInfo *pIErr;
  326. LANGID langID = LANG_NEUTRAL;
  327. #ifdef USE_LOCALE
  328. LANGID *pLangID;
  329. pLangID = (LANGID *)TlsGetValue(g_dwTLS);
  330. if (NULL != pLangID)
  331. langID = *pLangID;
  332. #endif
  333. /*
  334. * Thread-safe exception handling means that we call
  335. * CreateErrorInfo which gives us an ICreateErrorInfo pointer
  336. * that we then use to set the error information (basically
  337. * to set the fields of an EXCEPINFO structure. We then
  338. * call SetErrorInfo to attach this error to the current
  339. * thread. ITypeInfo::Invoke will look for this when it
  340. * returns from whatever function was invokes by calling
  341. * GetErrorInfo.
  342. */
  343. //Not much we can do if this fails.
  344. if (FAILED(CreateErrorInfo(&pICreateErr)))
  345. return;
  346. /*
  347. * CONSIDER: Help file and help context?
  348. */
  349. pICreateErr->SetGUID(ObjID);
  350. pICreateErr->SetHelpFile(L"");
  351. pICreateErr->SetHelpContext(0L);
  352. pICreateErr->SetSource(strSource);
  353. pICreateErr->SetDescription(strDescr);
  354. hr = pICreateErr->QueryInterface(IID_IErrorInfo, (PPVOID)&pIErr);
  355. if (SUCCEEDED(hr))
  356. {
  357. SetErrorInfo(0L, pIErr);
  358. pIErr->Release();
  359. }
  360. //SetErrorInfo holds the object's IErrorInfo
  361. pICreateErr->Release();
  362. return;
  363. }
  364. /*===================================================================
  365. ExceptionId
  366. Raises an exception using the CreateErrorInfo API and the
  367. ICreateErrorInfo interface.
  368. Note that this method doesn't allow for deferred filling
  369. of an EXCEPINFO structure.
  370. Parameters:
  371. SourceID Resource ID for the source string
  372. DescrID Resource ID for the description string
  373. Returns:
  374. Nothing
  375. ===================================================================*/
  376. void ExceptionId
  377. (
  378. REFIID ObjID,
  379. UINT SourceID,
  380. UINT DescrID,
  381. HRESULT hrCode
  382. )
  383. {
  384. HRESULT hr;
  385. ICreateErrorInfo *pICreateErr;
  386. IErrorInfo *pIErr;
  387. LANGID langID = LANG_NEUTRAL;
  388. #ifdef USE_LOCALE
  389. LANGID *pLangID;
  390. pLangID = (LANGID *)TlsGetValue(g_dwTLS);
  391. if (NULL != pLangID)
  392. langID = *pLangID;
  393. #endif
  394. if (DescrID == IDE_OOM)
  395. InterlockedIncrement(&g_nOOMErrors);
  396. // let's bail out of here if an error info is already set. Note,
  397. // getting the ErrorInfo clears, so we need to restore it. The
  398. // AddRef/ownership model is that GetErrorInfo gives ownership
  399. // to the caller, while SetErrorInfo takes ownership. As such,
  400. // no additional AddRef/Releases should be required.
  401. if (GetErrorInfo(0, &pIErr) == S_OK) {
  402. SetErrorInfo(0, pIErr);
  403. return;
  404. }
  405. /*
  406. * Thread-safe exception handling means that we call
  407. * CreateErrorInfo which gives us an ICreateErrorInfo pointer
  408. * that we then use to set the error information (basically
  409. * to set the fields of an EXCEPINFO structure. We then
  410. * call SetErrorInfo to attach this error to the current
  411. * thread. ITypeInfo::Invoke will look for this when it
  412. * returns from whatever function was invokes by calling
  413. * GetErrorInfo.
  414. */
  415. //Not much we can do if this fails.
  416. if (FAILED(CreateErrorInfo(&pICreateErr)))
  417. return;
  418. /*
  419. * CONSIDER: Help file and help context?
  420. */
  421. DWORD cch;
  422. WCHAR strSource[MAX_RESSTRINGSIZE];
  423. WCHAR strDescr[MAX_RESSTRINGSIZE];
  424. WCHAR strHRESULTDescr[256];
  425. WCHAR strDescrWithHRESULT[MAX_RESSTRINGSIZE];
  426. pICreateErr->SetGUID(ObjID);
  427. pICreateErr->SetHelpFile(L"");
  428. pICreateErr->SetHelpContext(0L);
  429. cch = CwchLoadStringOfId(SourceID, strSource, MAX_RESSTRINGSIZE);
  430. if (cch > 0)
  431. pICreateErr->SetSource(strSource);
  432. cch = CwchLoadStringOfId(DescrID, strDescr, MAX_RESSTRINGSIZE);
  433. if (cch > 0)
  434. {
  435. //Bug Fix 91847 use a FormatMessage() based description
  436. HResultToWsz(hrCode, strHRESULTDescr, 256);
  437. _snwprintf(strDescrWithHRESULT, MAX_RESSTRINGSIZE, strDescr, strHRESULTDescr);
  438. strDescrWithHRESULT[MAX_RESSTRINGSIZE - 1] = L'\0';
  439. pICreateErr->SetDescription(strDescrWithHRESULT);
  440. }
  441. hr = pICreateErr->QueryInterface(IID_IErrorInfo, (PPVOID)&pIErr);
  442. if (SUCCEEDED(hr))
  443. {
  444. SetErrorInfo(0L, pIErr);
  445. pIErr->Release();
  446. }
  447. //SetErrorInfo holds the object's IErrorInfo
  448. pICreateErr->Release();
  449. return;
  450. }