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.

262 lines
6.8 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995
  5. //
  6. // File: evtsink.cxx
  7. //
  8. // Contents: Implementation of the CScriptEventSink class
  9. //
  10. //----------------------------------------------------------------------------
  11. #include "headers.hxx"
  12. CScriptEventSink::CScriptEventSink(CScriptHost *pSH)
  13. {
  14. _pSH = pSH;
  15. _ulRefs = 1;
  16. Assert(_dwSinkCookie == 0);
  17. }
  18. CScriptEventSink::~CScriptEventSink()
  19. {
  20. Disconnect();
  21. }
  22. //+---------------------------------------------------------------------------
  23. //
  24. // Member: CScriptEventSink::Connect, public
  25. //
  26. // Synopsis: Connects to event interface on the source object
  27. //
  28. // Arguments: [pSource] -- Object to sink events from
  29. //
  30. // Returns: HRESULT
  31. //
  32. // TODO: This method should be more generic and walk through
  33. // the object's typeinfo looking for the default source
  34. // interface.
  35. //
  36. //----------------------------------------------------------------------------
  37. HRESULT
  38. CScriptEventSink::Connect(IDispatch *pSource, BSTR bstrProgID)
  39. {
  40. HRESULT hr = S_OK;
  41. IConnectionPointContainer *pCPC;
  42. IConnectionPoint *pCP = 0;
  43. _pDispSource = pSource;
  44. pSource->AddRef();
  45. hr = _pDispSource->QueryInterface(IID_IConnectionPointContainer,
  46. (LPVOID*)&pCPC);
  47. if (!hr)
  48. {
  49. if (bstrProgID && SysStringLen(bstrProgID) > 0)
  50. hr = CLSIDFromProgID(bstrProgID, &_clsidEvents);
  51. else
  52. _clsidEvents = DIID_DRemoteMTScriptEvents;
  53. if (hr == S_OK)
  54. hr = pCPC->FindConnectionPoint(_clsidEvents, &pCP);
  55. if (!hr)
  56. {
  57. hr = pCP->Advise(this, &_dwSinkCookie);
  58. ReleaseInterface(pCP);
  59. }
  60. ReleaseInterface(pCPC);
  61. #if DBG == 1
  62. if (hr)
  63. TraceTag((tagError, "Hookup to event sink returned %x", hr));
  64. #endif
  65. }
  66. return hr;
  67. }
  68. //+---------------------------------------------------------------------------
  69. //
  70. // Member: CScriptEventSink::Disconnect, public
  71. //
  72. // Synopsis: Disconnects from a machine we connected to via Connect().
  73. //
  74. // Arguments: (none)
  75. //
  76. //----------------------------------------------------------------------------
  77. void
  78. CScriptEventSink::Disconnect()
  79. {
  80. HRESULT hr = S_OK;
  81. if (_dwSinkCookie && _pDispSource)
  82. {
  83. IConnectionPointContainer *pCPC;
  84. IConnectionPoint *pCP;
  85. hr = _pDispSource->QueryInterface(IID_IConnectionPointContainer, (LPVOID*)&pCPC);
  86. if (!hr)
  87. {
  88. hr = pCPC->FindConnectionPoint(DIID_DRemoteMTScriptEvents,
  89. &pCP);
  90. if (!hr)
  91. {
  92. pCP->Unadvise(_dwSinkCookie);
  93. ReleaseInterface(pCP);
  94. }
  95. ReleaseInterface(pCPC);
  96. #if DBG == 1
  97. if (hr)
  98. TraceTag((tagError, "Unadvise from event sink returned %x", hr));
  99. #endif
  100. }
  101. _dwSinkCookie = 0;
  102. }
  103. ClearInterface(&_pDispSource);
  104. _pSH = NULL;
  105. }
  106. // *************************************************************************
  107. //
  108. // CScriptEventSink
  109. //
  110. // Class which implements the event sink for the remote object. We only pay
  111. // attention to Invoke calls.
  112. //
  113. // *************************************************************************
  114. HRESULT
  115. CScriptEventSink::QueryInterface(REFIID iid, void **ppv)
  116. {
  117. if (iid == IID_IUnknown ||
  118. iid == IID_IDispatch ||
  119. iid == _clsidEvents)
  120. {
  121. *ppv = (IDispatch *)this;
  122. }
  123. else
  124. {
  125. *ppv = NULL;
  126. return E_NOINTERFACE;
  127. }
  128. ((IUnknown *)*ppv)->AddRef();
  129. return S_OK;
  130. }
  131. //---------------------------------------------------------------------------
  132. //
  133. // Member: CScriptEventSink::GetTypeInfo, IDispatch
  134. //
  135. //---------------------------------------------------------------------------
  136. HRESULT
  137. CScriptEventSink::GetTypeInfo(UINT itinfo, ULONG lcid, ITypeInfo ** pptinfo)
  138. {
  139. return E_NOTIMPL;
  140. }
  141. //---------------------------------------------------------------------------
  142. //
  143. // Member: CScriptEventSink::GetTypeInfoCount, IDispatch
  144. //
  145. //---------------------------------------------------------------------------
  146. HRESULT
  147. CScriptEventSink::GetTypeInfoCount(UINT * pctinfo)
  148. {
  149. *pctinfo = 0;
  150. return S_OK;
  151. }
  152. //---------------------------------------------------------------------------
  153. //
  154. // Member: CScriptEventSink::GetIDsOfNames, IDispatch
  155. //
  156. //---------------------------------------------------------------------------
  157. HRESULT
  158. CScriptEventSink::GetIDsOfNames(REFIID riid,
  159. LPOLESTR * rgszNames,
  160. UINT cNames,
  161. LCID lcid,
  162. DISPID * rgdispid)
  163. {
  164. return E_NOTIMPL;
  165. }
  166. //---------------------------------------------------------------------------
  167. //
  168. // Member: CScriptEventSink::Invoke, IDispatch
  169. //
  170. //---------------------------------------------------------------------------
  171. HRESULT
  172. CScriptEventSink::Invoke(DISPID dispidMember,
  173. REFIID riid,
  174. LCID lcid,
  175. WORD wFlags,
  176. DISPPARAMS * pdispparams,
  177. VARIANT * pvarResult,
  178. EXCEPINFO * pexcepinfo,
  179. UINT * puArgErr)
  180. {
  181. if (_pSH && _pSH->GetSite() && _pSH->GetSite()->_pDispSink)
  182. {
  183. DISPPARAMS dp;
  184. VARIANTARG varg[20];
  185. // We need to tack on 2 parameters to the call. First is the object
  186. // that is firing the event. Second is the dispatch ID.
  187. // We put them on the end of the list, which means they become
  188. // the first and second parameters to the event.
  189. if (pdispparams->cArgs > ARRAY_SIZE(varg) - 2)
  190. {
  191. AssertSz(FALSE, "NONFATAL: Too many parameters to event (max==18)!");
  192. return E_FAIL;
  193. }
  194. dp.cArgs = pdispparams->cArgs + 2;
  195. dp.cNamedArgs = pdispparams->cNamedArgs;
  196. dp.rgdispidNamedArgs = pdispparams->rgdispidNamedArgs;
  197. memcpy(varg, pdispparams->rgvarg, pdispparams->cArgs * sizeof(VARIANTARG));
  198. V_VT(&varg[dp.cArgs-1]) = VT_DISPATCH;
  199. V_DISPATCH(&varg[dp.cArgs-1]) = _pDispSource;
  200. V_VT(&varg[dp.cArgs-2]) = VT_I4;
  201. V_I4(&varg[dp.cArgs-2]) = dispidMember;
  202. dp.rgvarg = varg;
  203. return _pSH->GetSite()->_pDispSink->Invoke(
  204. DISPID_MTScript_OnEventSourceEvent,
  205. IID_NULL,
  206. lcid,
  207. DISPATCH_METHOD,
  208. &dp,
  209. pvarResult,
  210. pexcepinfo,
  211. puArgErr);
  212. }
  213. return S_OK;
  214. }