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.

355 lines
9.0 KiB

  1. /*===================================================================
  2. Microsoft Denali
  3. Microsoft Confidential.
  4. Copyright 1997 Microsoft Corporation. All Rights Reserved.
  5. Component: IConnectionPoint implementation
  6. File: ConnPt.h
  7. Owner: DGottner
  8. This file contains our implementation of IConnectionPoint
  9. ===================================================================*/
  10. #include "denpre.h"
  11. #pragma hdrstop
  12. #include "ConnPt.h"
  13. #include "memchk.h"
  14. /*------------------------------------------------------------------
  15. * C C o n n e c t i o n P o i n t
  16. */
  17. /*===================================================================
  18. CConnectionPoint::CConnectionPoint
  19. CConnectionPoint::~CConnectionPoint
  20. Parameters (Constructor):
  21. pUnkObj pointer to the object we're in.
  22. pUnkOuter LPUNKNOWN to which we delegate.
  23. NOTE: Code assumes connection point is contained DIRECTLY in the
  24. container (and thus, does not AddRef 'm_pContainer'
  25. If not the case, we may be in trouble.
  26. ===================================================================*/
  27. CConnectionPoint::CConnectionPoint(IUnknown *pUnkContainer, const GUID &uidEvent)
  28. {
  29. m_pUnkContainer = pUnkContainer;
  30. m_uidEvent = uidEvent;
  31. m_dwCookieNext = 0xA5B; // Looks like "ASP"!
  32. Assert (m_pUnkContainer != NULL);
  33. }
  34. CConnectionPoint::~CConnectionPoint()
  35. {
  36. while (! m_listSinks.FIsEmpty())
  37. delete m_listSinks.PNext();
  38. }
  39. /*===================================================================
  40. CConnectionPoint::GetConnectionInterface
  41. Returns the interface of the event source
  42. ===================================================================*/
  43. HRESULT
  44. CConnectionPoint::GetConnectionInterface(GUID *puidReturn)
  45. {
  46. *puidReturn = m_uidEvent;
  47. return S_OK;
  48. }
  49. /*===================================================================
  50. CConnectionPoint::GetConnectionPointContainer
  51. Returns the interface of the event source
  52. ===================================================================*/
  53. HRESULT
  54. CConnectionPoint::GetConnectionPointContainer(IConnectionPointContainer **ppContainer)
  55. {
  56. return m_pUnkContainer->QueryInterface(IID_IConnectionPointContainer, reinterpret_cast<void **>(ppContainer));
  57. }
  58. /*===================================================================
  59. CConnectionPoint::Advise
  60. Purpose:
  61. Provides this connection point with a notification sink to
  62. call whenever the appropriate outgoing function/event occurs.
  63. Parameters:
  64. pUnkSink IUnknown to the sink to notify. The connection
  65. point must QueryInterface on this pointer to obtain
  66. the proper interface to call. The connection
  67. point must also insure that any pointer held has
  68. a reference count (QueryInterface will do it).
  69. pdwCookie DWORD * in which to store the connection key for
  70. later calls to Unadvise.
  71. ===================================================================*/
  72. HRESULT
  73. CConnectionPoint::Advise(IUnknown *pUnkSink, DWORD *pdwCookie)
  74. {
  75. // Make sure they store the correct interface pointer!
  76. // NOTE: Storing into the list will AddRef, to we need to Release the
  77. // QueryInterface pointer right away.
  78. //
  79. void *pvT;
  80. if (FAILED(pUnkSink->QueryInterface(m_uidEvent, &pvT)))
  81. return CONNECT_E_CANNOTCONNECT;
  82. pUnkSink->Release();
  83. CSinkElem *pSinkElem = new CSinkElem(*pdwCookie = m_dwCookieNext++, pUnkSink);
  84. if (pSinkElem == NULL)
  85. return E_OUTOFMEMORY;
  86. pSinkElem->AppendTo(m_listSinks);
  87. return S_OK;
  88. }
  89. /*===================================================================
  90. CConnectionPoint::Unadvise
  91. Purpose:
  92. Terminates the connection to the notification sink identified
  93. with dwCookie (that was returned from Advise). The connection
  94. point has to Release any held pointers for that sink.
  95. Parameters:
  96. dwCookie DWORD connection key from Advise.
  97. ===================================================================*/
  98. HRESULT
  99. CConnectionPoint::Unadvise(DWORD dwCookie)
  100. {
  101. // Search for the cookie
  102. for (CSinkElem *pSinkElem = static_cast<CSinkElem *>(m_listSinks.PNext());
  103. pSinkElem != &m_listSinks;
  104. pSinkElem = static_cast<CSinkElem *>(pSinkElem->PNext()))
  105. {
  106. if (dwCookie == pSinkElem->m_dwCookie)
  107. {
  108. delete pSinkElem;
  109. return S_OK;
  110. }
  111. }
  112. return CONNECT_E_NOCONNECTION;
  113. }
  114. /*===================================================================
  115. CConnectionPoint::EnumConnections
  116. Purpose:
  117. Creates and returns an enumerator object with the
  118. IEnumConnections interface that will enumerate the IUnknown
  119. pointers of each connected sink.
  120. Parameters:
  121. ppEnum Output enumerator object
  122. ===================================================================*/
  123. HRESULT
  124. CConnectionPoint::EnumConnections(IEnumConnections **ppEnum)
  125. {
  126. if ((*ppEnum = new CEnumConnections(this)) == NULL)
  127. return E_OUTOFMEMORY;
  128. return S_OK;
  129. }
  130. /*------------------------------------------------------------------
  131. * C E n u m C o n n e c t i o n s
  132. */
  133. /*===================================================================
  134. CEnumConnections::CEnumConnections
  135. CEnumConnections::~CEnumConnections
  136. Parameters (Constructor):
  137. pCP pointer to object we're in.
  138. ===================================================================*/
  139. CEnumConnections::CEnumConnections(CConnectionPoint *pCP)
  140. {
  141. Assert (pCP != NULL);
  142. m_cRefs = 1;
  143. m_pCP = pCP;
  144. m_pCP->AddRef();
  145. Reset();
  146. }
  147. CEnumConnections::~CEnumConnections()
  148. {
  149. m_pCP->Release();
  150. }
  151. /*===================================================================
  152. CEnumConnections::QueryInterface
  153. CEnumConnections::AddRef
  154. CEnumConnections::Release
  155. IUnknown members for CEnumConnections object.
  156. ===================================================================*/
  157. HRESULT CEnumConnections::QueryInterface(const GUID &iid, void **ppvObj)
  158. {
  159. if (iid == IID_IUnknown || iid == IID_IEnumConnections)
  160. {
  161. AddRef();
  162. *ppvObj = this;
  163. return S_OK;
  164. }
  165. *ppvObj = NULL;
  166. return E_NOINTERFACE;
  167. }
  168. ULONG CEnumConnections::AddRef()
  169. {
  170. return ++m_cRefs;
  171. }
  172. ULONG CEnumConnections::Release()
  173. {
  174. if (--m_cRefs > 0)
  175. return m_cRefs;
  176. delete this;
  177. return 0;
  178. }
  179. /*===================================================================
  180. CEnumConnections::Clone
  181. Clone this iterator (standard method)
  182. ===================================================================*/
  183. HRESULT CEnumConnections::Clone(IEnumConnections **ppEnumReturn)
  184. {
  185. CEnumConnections *pNewIterator = new CEnumConnections(m_pCP);
  186. if (pNewIterator == NULL)
  187. return E_OUTOFMEMORY;
  188. // new iterator should point to same location as this.
  189. pNewIterator->m_pElemCurr = m_pElemCurr;
  190. *ppEnumReturn = pNewIterator;
  191. return S_OK;
  192. }
  193. /*===================================================================
  194. CEnumConnections::Next
  195. Get next value (standard method)
  196. To rehash standard OLE semantics:
  197. We get the next "cElements" from the collection and store them
  198. in "rgVariant" which holds at least "cElements" items. On
  199. return "*pcElementsFetched" contains the actual number of elements
  200. stored. Returns S_FALSE if less than "cElements" were stored, S_OK
  201. otherwise.
  202. ===================================================================*/
  203. HRESULT CEnumConnections::Next(unsigned long cElementsRequested, CONNECTDATA *rgConnectData, unsigned long *pcElementsFetched)
  204. {
  205. // give a valid pointer value to 'pcElementsFetched'
  206. //
  207. unsigned long cElementsFetched;
  208. if (pcElementsFetched == NULL)
  209. pcElementsFetched = &cElementsFetched;
  210. // Loop through the collection until either we reach the end or
  211. // cElements becomes zero
  212. //
  213. unsigned long cElements = cElementsRequested;
  214. *pcElementsFetched = 0;
  215. while (cElements > 0 && m_pElemCurr != &m_pCP->m_listSinks)
  216. {
  217. rgConnectData->dwCookie = static_cast<CConnectionPoint::CSinkElem *>(m_pElemCurr)->m_dwCookie;
  218. rgConnectData->pUnk = static_cast<CConnectionPoint::CSinkElem *>(m_pElemCurr)->m_pUnkObj;
  219. rgConnectData->pUnk->AddRef();
  220. ++rgConnectData;
  221. --cElements;
  222. ++*pcElementsFetched;
  223. m_pElemCurr = m_pElemCurr->PNext();
  224. }
  225. // initialize the remaining structures
  226. //
  227. while (cElements-- > 0)
  228. (rgConnectData++)->pUnk = NULL;
  229. return (*pcElementsFetched == cElementsRequested)? S_OK : S_FALSE;
  230. }
  231. /*===================================================================
  232. CEnumConnections::Skip
  233. Skip items (standard method)
  234. To rehash standard OLE semantics:
  235. We skip over the next "cElements" from the collection.
  236. Returns S_FALSE if less than "cElements" were skipped, S_OK
  237. otherwise.
  238. ===================================================================*/
  239. HRESULT CEnumConnections::Skip(unsigned long cElements)
  240. {
  241. /* Loop through the collection until either we reach the end or
  242. * cElements becomes zero
  243. */
  244. while (cElements > 0 && m_pElemCurr != &m_pCP->m_listSinks)
  245. {
  246. m_pElemCurr = m_pElemCurr->PNext();
  247. --cElements;
  248. }
  249. return (cElements == 0)? S_OK : S_FALSE;
  250. }
  251. /*===================================================================
  252. CEnumConnections::Reset
  253. Reset the iterator (standard method)
  254. ===================================================================*/
  255. HRESULT CEnumConnections::Reset()
  256. {
  257. m_pElemCurr = m_pCP->m_listSinks.PNext();
  258. return S_OK;
  259. }