2 * Implementation of a generic ConnectionPoint object.
4 * Copyright 2000 Huw D M Davies for CodeWeavers
6 * See one exported function here is CreateConnectionPoint, see
7 * comments just above that function for information.
17 #include "wine/obj_base.h"
18 #include "wine/obj_connection.h"
21 #include "debugtools.h"
23 DEFAULT_DEBUG_CHANNEL(ole);
27 /************************************************************************
28 * Implementation of IConnectionPoint
30 typedef struct ConnectionPointImpl {
32 ICOM_VTABLE(IConnectionPoint) *lpvtbl;
34 /* IUnknown of our main object*/
40 /* IID of sink interface */
43 /* Array of sink IUnknowns */
48 } ConnectionPointImpl;
50 static ICOM_VTABLE(IConnectionPoint) ConnectionPointImpl_VTable;
53 /************************************************************************
54 * Implementation of IEnumConnections
56 typedef struct EnumConnectionsImpl {
58 ICOM_VTABLE(IEnumConnections) *lpvtbl;
62 /* IUnknown of ConnectionPoint, used for ref counting */
69 /* Next connection to enumerate from */
72 } EnumConnectionsImpl;
74 static EnumConnectionsImpl *EnumConnectionsImpl_Construct(IUnknown *pUnk,
79 /************************************************************************
80 * ConnectionPointImpl_Construct
82 static ConnectionPointImpl *ConnectionPointImpl_Construct(IUnknown *pUnk,
85 ConnectionPointImpl *Obj;
87 Obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*Obj));
88 Obj->lpvtbl = &ConnectionPointImpl_VTable;
92 Obj->maxSinks = MAXSINKS;
93 Obj->sinks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
94 sizeof(IUnknown*) * MAXSINKS);
99 /************************************************************************
100 * ConnectionPointImpl_Destroy
102 static void ConnectionPointImpl_Destroy(ConnectionPointImpl *Obj)
105 for(i = 0; i < Obj->maxSinks; i++) {
107 IUnknown_Release(Obj->sinks[i]);
108 Obj->sinks[i] = NULL;
111 HeapFree(GetProcessHeap(), 0, Obj->sinks);
112 HeapFree(GetProcessHeap(), 0, Obj);
116 static ULONG WINAPI ConnectionPointImpl_AddRef(IConnectionPoint* iface);
117 /************************************************************************
118 * ConnectionPointImpl_QueryInterface (IUnknown)
120 * See Windows documentation for more details on IUnknown methods.
122 static HRESULT WINAPI ConnectionPointImpl_QueryInterface(
123 IConnectionPoint* iface,
127 ICOM_THIS(ConnectionPointImpl, iface);
128 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
131 * Perform a sanity check on the parameters.
133 if ( (This==0) || (ppvObject==0) )
137 * Initialize the return parameter.
142 * Compare the riid with the interface IDs implemented by this object.
144 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
146 *ppvObject = (IConnectionPoint*)This;
148 else if (memcmp(&IID_IConnectionPoint, riid, sizeof(IID_IConnectionPoint)) == 0)
150 *ppvObject = (IConnectionPoint*)This;
154 * Check that we obtained an interface.
158 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
159 return E_NOINTERFACE;
163 * Query Interface always increases the reference count by one when it is
166 ConnectionPointImpl_AddRef((IConnectionPoint*)This);
172 /************************************************************************
173 * ConnectionPointImpl_AddRef (IUnknown)
175 * See Windows documentation for more details on IUnknown methods.
177 static ULONG WINAPI ConnectionPointImpl_AddRef(IConnectionPoint* iface)
179 ICOM_THIS(ConnectionPointImpl, iface);
180 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
186 /************************************************************************
187 * ConnectionPointImpl_Release (IUnknown)
189 * See Windows documentation for more details on IUnknown methods.
191 static ULONG WINAPI ConnectionPointImpl_Release(
192 IConnectionPoint* iface)
194 ICOM_THIS(ConnectionPointImpl, iface);
195 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
198 * Decrease the reference count on this object.
203 * If the reference count goes down to 0, perform suicide.
207 ConnectionPointImpl_Destroy(This);
215 /************************************************************************
216 * ConnectionPointImpl_GetConnectionInterface (IConnectionPoint)
219 static HRESULT WINAPI ConnectionPointImpl_GetConnectionInterface(
220 IConnectionPoint *iface,
223 ICOM_THIS(ConnectionPointImpl, iface);
224 TRACE("(%p)->(%p) returning %s\n", This, piid, debugstr_guid(&(This->iid)));
229 /************************************************************************
230 * ConnectionPointImpl_GetConnectionPointContainer (IConnectionPoint)
233 static HRESULT WINAPI ConnectionPointImpl_GetConnectionPointContainer(
234 IConnectionPoint *iface,
235 IConnectionPointContainer **ppCPC)
237 ICOM_THIS(ConnectionPointImpl, iface);
238 TRACE("(%p)->(%p)\n", This, ppCPC);
240 return IUnknown_QueryInterface(This->Obj,
241 &IID_IConnectionPointContainer,
245 /************************************************************************
246 * ConnectionPointImpl_Advise (IConnectionPoint)
249 static HRESULT WINAPI ConnectionPointImpl_Advise(IConnectionPoint *iface,
254 ICOM_THIS(ConnectionPointImpl, iface);
256 TRACE("(%p)->(%p, %p)\n", This, lpUnk, pdwCookie);
259 if(FAILED(IUnknown_QueryInterface(lpUnk, &This->iid, (LPVOID)&lpSink)))
260 return CONNECT_E_CANNOTCONNECT;
262 for(i = 0; i < This->maxSinks; i++) {
263 if(This->sinks[i] == NULL)
266 if(i == This->maxSinks) {
267 This->maxSinks += MAXSINKS;
268 This->sinks = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->sinks,
269 This->maxSinks * sizeof(IUnknown *));
271 This->sinks[i] = lpSink;
278 /************************************************************************
279 * ConnectionPointImpl_Unadvise (IConnectionPoint)
282 static HRESULT WINAPI ConnectionPointImpl_Unadvise(IConnectionPoint *iface,
285 ICOM_THIS(ConnectionPointImpl, iface);
286 TRACE("(%p)->(%ld)\n", This, dwCookie);
288 if(dwCookie == 0 || dwCookie > This->maxSinks) return E_INVALIDARG;
290 if(This->sinks[dwCookie-1] == NULL) return CONNECT_E_NOCONNECTION;
292 IUnknown_Release(This->sinks[dwCookie-1]);
293 This->sinks[dwCookie-1] = NULL;
298 /************************************************************************
299 * ConnectionPointImpl_EnumConnections (IConnectionPoint)
302 static HRESULT WINAPI ConnectionPointImpl_EnumConnections(
303 IConnectionPoint *iface,
304 LPENUMCONNECTIONS *ppEnum)
306 ICOM_THIS(ConnectionPointImpl, iface);
309 EnumConnectionsImpl *EnumObj;
312 TRACE("(%p)->(%p)\n", This, ppEnum);
316 if(This->nSinks == 0) return OLE_E_NOCONNECTION;
318 pCD = HeapAlloc(GetProcessHeap(), 0, sizeof(CONNECTDATA) * This->nSinks);
320 for(i = 0, nextslot = 0; i < This->maxSinks; i++) {
321 if(This->sinks[i] != NULL) {
322 pCD[nextslot].pUnk = This->sinks[i];
323 pCD[nextslot].dwCookie = i + 1;
327 assert(nextslot == This->nSinks);
329 /* Bump the ref count of this object up by one. It gets Released in
330 IEnumConnections_Release */
331 IUnknown_AddRef((IUnknown*)This);
333 EnumObj = EnumConnectionsImpl_Construct((IUnknown*)This, This->nSinks, pCD);
334 hr = IEnumConnections_QueryInterface((IEnumConnections*)EnumObj,
335 &IID_IEnumConnections, (LPVOID)ppEnum);
336 IEnumConnections_Release((IEnumConnections*)EnumObj);
338 HeapFree(GetProcessHeap(), 0, pCD);
342 static ICOM_VTABLE(IConnectionPoint) ConnectionPointImpl_VTable =
344 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
345 ConnectionPointImpl_QueryInterface,
346 ConnectionPointImpl_AddRef,
347 ConnectionPointImpl_Release,
348 ConnectionPointImpl_GetConnectionInterface,
349 ConnectionPointImpl_GetConnectionPointContainer,
350 ConnectionPointImpl_Advise,
351 ConnectionPointImpl_Unadvise,
352 ConnectionPointImpl_EnumConnections
356 static ICOM_VTABLE(IEnumConnections) EnumConnectionsImpl_VTable;
357 static ULONG WINAPI EnumConnectionsImpl_AddRef(IEnumConnections* iface);
359 /************************************************************************
360 * EnumConnectionsImpl_Construct
362 static EnumConnectionsImpl *EnumConnectionsImpl_Construct(IUnknown *pUnk,
366 EnumConnectionsImpl *Obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*Obj));
369 Obj->lpvtbl = &EnumConnectionsImpl_VTable;
372 Obj->pCD = HeapAlloc(GetProcessHeap(), 0, nSinks * sizeof(CONNECTDATA));
373 Obj->nConns = nSinks;
376 for(i = 0; i < nSinks; i++) {
377 Obj->pCD[i] = pCD[i];
378 IUnknown_AddRef(Obj->pCD[i].pUnk);
383 /************************************************************************
384 * EnumConnectionsImpl_Destroy
386 static void EnumConnectionsImpl_Destroy(EnumConnectionsImpl *Obj)
390 for(i = 0; i < Obj->nConns; i++)
391 IUnknown_Release(Obj->pCD[i].pUnk);
393 HeapFree(GetProcessHeap(), 0, Obj->pCD);
394 HeapFree(GetProcessHeap(), 0, Obj);
398 /************************************************************************
399 * EnumConnectionsImpl_QueryInterface (IUnknown)
401 * See Windows documentation for more details on IUnknown methods.
403 static HRESULT WINAPI EnumConnectionsImpl_QueryInterface(
404 IEnumConnections* iface,
408 ICOM_THIS(ConnectionPointImpl, iface);
409 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
412 * Perform a sanity check on the parameters.
414 if ( (This==0) || (ppvObject==0) )
418 * Initialize the return parameter.
423 * Compare the riid with the interface IDs implemented by this object.
425 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
427 *ppvObject = (IEnumConnections*)This;
429 else if (memcmp(&IID_IEnumConnections, riid, sizeof(IID_IEnumConnections)) == 0)
431 *ppvObject = (IEnumConnections*)This;
435 * Check that we obtained an interface.
439 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
440 return E_NOINTERFACE;
444 * Query Interface always increases the reference count by one when it is
447 EnumConnectionsImpl_AddRef((IEnumConnections*)This);
453 /************************************************************************
454 * EnumConnectionsImpl_AddRef (IUnknown)
456 * See Windows documentation for more details on IUnknown methods.
458 static ULONG WINAPI EnumConnectionsImpl_AddRef(IEnumConnections* iface)
460 ICOM_THIS(EnumConnectionsImpl, iface);
461 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
463 IUnknown_AddRef(This->pUnk);
467 /************************************************************************
468 * EnumConnectionsImpl_Release (IUnknown)
470 * See Windows documentation for more details on IUnknown methods.
472 static ULONG WINAPI EnumConnectionsImpl_Release(IEnumConnections* iface)
474 ICOM_THIS(EnumConnectionsImpl, iface);
475 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
477 IUnknown_Release(This->pUnk);
480 * Decrease the reference count on this object.
485 * If the reference count goes down to 0, perform suicide.
489 EnumConnectionsImpl_Destroy(This);
497 /************************************************************************
498 * EnumConnectionsImpl_Next (IEnumConnections)
501 static HRESULT WINAPI EnumConnectionsImpl_Next(IEnumConnections* iface,
502 ULONG cConn, LPCONNECTDATA pCD,
505 ICOM_THIS(EnumConnectionsImpl, iface);
507 TRACE("(%p)->(%ld, %p, %p)\n", This, cConn, pCD, pEnum);
515 if(This->nCur >= This->nConns)
518 while(This->nCur < This->nConns && cConn) {
519 *pCD++ = This->pCD[This->nCur];
520 IUnknown_AddRef(This->pCD[This->nCur].pUnk);
533 /************************************************************************
534 * EnumConnectionsImpl_Skip (IEnumConnections)
537 static HRESULT WINAPI EnumConnectionsImpl_Skip(IEnumConnections* iface,
540 ICOM_THIS(EnumConnectionsImpl, iface);
541 TRACE("(%p)->(%ld)\n", This, cSkip);
543 if(This->nCur + cSkip >= This->nConns)
552 /************************************************************************
553 * EnumConnectionsImpl_Reset (IEnumConnections)
556 static HRESULT WINAPI EnumConnectionsImpl_Reset(IEnumConnections* iface)
558 ICOM_THIS(EnumConnectionsImpl, iface);
559 TRACE("(%p)\n", This);
567 /************************************************************************
568 * EnumConnectionsImpl_Clone (IEnumConnections)
571 static HRESULT WINAPI EnumConnectionsImpl_Clone(IEnumConnections* iface,
572 LPENUMCONNECTIONS *ppEnum)
574 ICOM_THIS(EnumConnectionsImpl, iface);
575 EnumConnectionsImpl *newObj;
576 TRACE("(%p)->(%p)\n", This, ppEnum);
578 newObj = EnumConnectionsImpl_Construct(This->pUnk, This->nConns, This->pCD);
579 newObj->nCur = This->nCur;
580 *ppEnum = (LPENUMCONNECTIONS)newObj;
581 IUnknown_AddRef(This->pUnk);
585 static ICOM_VTABLE(IEnumConnections) EnumConnectionsImpl_VTable =
587 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
588 EnumConnectionsImpl_QueryInterface,
589 EnumConnectionsImpl_AddRef,
590 EnumConnectionsImpl_Release,
591 EnumConnectionsImpl_Next,
592 EnumConnectionsImpl_Skip,
593 EnumConnectionsImpl_Reset,
594 EnumConnectionsImpl_Clone
597 /************************************************************************
599 * The exported function to create the connection point.
600 * NB not a windows API
603 * pUnk [in] IUnknown of object to which the ConnectionPoint is associated.
604 * Needed to access IConnectionPointContainer.
606 * riid [in] IID of sink interface that this ConnectionPoint manages
608 * pCP [out] returns IConnectionPoint
611 HRESULT CreateConnectionPoint(IUnknown *pUnk, REFIID riid,
612 IConnectionPoint **pCP)
614 ConnectionPointImpl *Obj;
617 Obj = ConnectionPointImpl_Construct(pUnk, riid);
618 if(!Obj) return E_OUTOFMEMORY;
620 hr = IConnectionPoint_QueryInterface((IConnectionPoint *)Obj,
621 &IID_IConnectionPoint, (LPVOID)pCP);
622 IConnectionPoint_Release((IConnectionPoint *)Obj);