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.

225 lines
6.5 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1999
  5. //
  6. // File: scriptevents.cpp
  7. //
  8. // Contents: Implementation of script events thru connection points
  9. //
  10. // History: 11-Feb-99 AudriusZ Created
  11. //
  12. //--------------------------------------------------------------------------
  13. #include "stdafx.h"
  14. #include "scriptevents.h"
  15. // Traces
  16. #ifdef DBG
  17. CTraceTag tagComEvents(_T("Events"), _T("COM events"));
  18. #endif
  19. /***************************************************************************\
  20. *
  21. * METHOD: CEventDispatcherBase::SetContainer
  22. *
  23. * PURPOSE: Accesory function. Sets Connection point container
  24. * to be used for getting the sinks
  25. *
  26. * PARAMETERS:
  27. * LPUNKNOWN pComObject - pointer to COM object - event source (NULL is OK)
  28. *
  29. * RETURNS:
  30. * SC - result code
  31. *
  32. \***************************************************************************/
  33. void CEventDispatcherBase::SetContainer(LPUNKNOWN pComObject)
  34. {
  35. // It makes difference to us if the object pointer is NULL
  36. // (that means there are no com object , and that's OK)
  37. // Or QI for IConnectionPointContainer will fail
  38. // (that means an error)
  39. m_bEventSourceExists = !(pComObject == NULL);
  40. if (!m_bEventSourceExists)
  41. return;
  42. // note it's not guaranteed here m_spContainer won't be NULL
  43. m_spContainer = pComObject;
  44. }
  45. /***************************************************************************\
  46. *
  47. * METHOD: CEventDispatcherBase::ScInvokeOnConnections
  48. *
  49. * PURPOSE: This method will iterate thu sinks and invoke
  50. * same method on each ot them
  51. *
  52. * PARAMETERS:
  53. * REFIID riid - GUID of disp interface
  54. * DISPID dispid - disp id
  55. * CComVariant *pVar - array of parameters (may be NULL)
  56. * int count - count of items in pVar
  57. *
  58. * RETURNS:
  59. * SC - result code
  60. *
  61. \***************************************************************************/
  62. SC CEventDispatcherBase::ScInvokeOnConnections(REFIID riid, DISPID dispid, CComVariant *pVar, int count, CEventBuffer& buffer) const
  63. {
  64. DECLARE_SC(sc, TEXT("CEventDispatcherBase::ScInvokeOnConnections"));
  65. // the pointer to event source passed is NULL,
  66. // that means there is no event source - and no event sinks connected
  67. // thus we are done at this point
  68. if (!m_bEventSourceExists)
  69. return sc;
  70. // check if com object supports IConnectionPointContainer;
  71. // Bad pointer ( or to bad object ) if it does not
  72. sc = ScCheckPointers(m_spContainer, E_NOINTERFACE);
  73. if (sc)
  74. return sc;
  75. // get connection point
  76. IConnectionPointPtr spConnectionPoint;
  77. sc = m_spContainer->FindConnectionPoint(riid, &spConnectionPoint);
  78. if (sc)
  79. return sc;
  80. // recheck the pointer
  81. sc = ScCheckPointers(spConnectionPoint, E_UNEXPECTED);
  82. if (sc)
  83. return sc;
  84. // get connections
  85. IEnumConnectionsPtr spEnumConnections;
  86. sc = spConnectionPoint->EnumConnections(&spEnumConnections);
  87. if (sc)
  88. return sc;
  89. // recheck the pointer
  90. sc = ScCheckPointers(spEnumConnections, E_UNEXPECTED);
  91. if (sc)
  92. return sc;
  93. // reset iterator
  94. sc = spEnumConnections->Reset();
  95. if (sc)
  96. return sc;
  97. // iterate thru sinks until Next returns S_FALSE.
  98. CONNECTDATA connectdata;
  99. SC sc_last_error;
  100. while (1) // will use <break> to exit
  101. {
  102. // get the next sink
  103. ZeroMemory(&connectdata, sizeof(connectdata));
  104. sc = spEnumConnections->Next( 1, &connectdata, NULL );
  105. if (sc)
  106. return sc;
  107. // done if no more sinks
  108. if (sc == SC(S_FALSE))
  109. break;
  110. // recheck the pointer
  111. sc = ScCheckPointers(connectdata.pUnk, E_UNEXPECTED);
  112. if (sc)
  113. return sc;
  114. // QI for IDispatch
  115. IDispatchPtr spDispatch = connectdata.pUnk;
  116. connectdata.pUnk->Release();
  117. // recheck the pointer
  118. sc = ScCheckPointers(spDispatch, E_UNEXPECTED);
  119. if (sc)
  120. return sc;
  121. // if events are locked by now, we need to postpone the call
  122. // else - emit it
  123. sc = buffer.ScEmitOrPostpone(spDispatch, dispid, pVar, count);
  124. if (sc)
  125. {
  126. sc_last_error = sc; // continue even if some calls failed
  127. sc.TraceAndClear();
  128. }
  129. }
  130. // we succeeded, but sinks may not,
  131. // report the error (if one happened)
  132. return sc_last_error;
  133. }
  134. /***************************************************************************\
  135. *
  136. * METHOD: CEventDispatcherBase::ScHaveSinksRegisteredForInterface
  137. *
  138. * PURPOSE: Checks if there are any sinks registered with interface
  139. * Function allows perform early check to skip com object creation
  140. * fo event parameters if event will go nowere anyway
  141. *
  142. * PARAMETERS:
  143. * const REFIID riid - interface id
  144. *
  145. * RETURNS:
  146. * SC - result code
  147. *
  148. \***************************************************************************/
  149. SC CEventDispatcherBase::ScHaveSinksRegisteredForInterface(const REFIID riid)
  150. {
  151. DECLARE_SC(sc, TEXT("CEventDispatcherBase::ScHaveSinksRegisteredForInterface"));
  152. // the pointer to event source passed is NULL,
  153. // that means there is no event source - and no event sinks connected
  154. if (!m_bEventSourceExists)
  155. return sc = S_FALSE;
  156. // check if com object supports IConnectionPointContainer;
  157. // Bad pointer ( or to bad object ) if it does not
  158. sc = ScCheckPointers(m_spContainer, E_NOINTERFACE);
  159. if (sc)
  160. return sc;
  161. // get connection point
  162. IConnectionPointPtr spConnectionPoint;
  163. sc = m_spContainer->FindConnectionPoint(riid, &spConnectionPoint);
  164. if (sc)
  165. return sc;
  166. // recheck the pointer
  167. sc = ScCheckPointers(spConnectionPoint, E_UNEXPECTED);
  168. if (sc)
  169. return sc;
  170. // get connections
  171. IEnumConnectionsPtr spEnumConnections;
  172. sc = spConnectionPoint->EnumConnections(&spEnumConnections);
  173. if (sc)
  174. return sc;
  175. // recheck the pointer
  176. sc = ScCheckPointers(spEnumConnections, E_UNEXPECTED);
  177. if (sc)
  178. return sc;
  179. // reset iterator
  180. sc = spEnumConnections->Reset();
  181. if (sc)
  182. return sc;
  183. // get first member. Will return S_FALSE if no items in collection
  184. CONNECTDATA connectdata;
  185. ZeroMemory(&connectdata, sizeof(connectdata));
  186. sc = spEnumConnections->Next( 1, &connectdata, NULL );
  187. if (sc)
  188. return sc;
  189. // release the data
  190. if (connectdata.pUnk)
  191. connectdata.pUnk->Release();
  192. return sc;
  193. }