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.

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