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.
18 #include "wine/obj_base.h"
19 #include "wine/obj_connection.h"
22 #include "debugtools.h"
24 DEFAULT_DEBUG_CHANNEL(ole);
28 /************************************************************************
29 * Implementation of IConnectionPoint
31 typedef struct ConnectionPointImpl {
33 ICOM_VTABLE(IConnectionPoint) *lpvtbl;
35 /* IUnknown of our main object*/
41 /* IID of sink interface */
44 /* Array of sink IUnknowns */
49 } ConnectionPointImpl;
51 static ICOM_VTABLE(IConnectionPoint) ConnectionPointImpl_VTable;
54 /************************************************************************
55 * Implementation of IEnumConnections
57 typedef struct EnumConnectionsImpl {
59 ICOM_VTABLE(IEnumConnections) *lpvtbl;
63 /* IUnknown of ConnectionPoint, used for ref counting */
70 /* Next connection to enumerate from */
73 } EnumConnectionsImpl;
75 static EnumConnectionsImpl *EnumConnectionsImpl_Construct(IUnknown *pUnk,
80 /************************************************************************
81 * ConnectionPointImpl_Construct
83 static ConnectionPointImpl *ConnectionPointImpl_Construct(IUnknown *pUnk,
86 ConnectionPointImpl *Obj;
88 Obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*Obj));
89 Obj->lpvtbl = &ConnectionPointImpl_VTable;
93 Obj->maxSinks = MAXSINKS;
94 Obj->sinks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
95 sizeof(IUnknown*) * MAXSINKS);
100 /************************************************************************
101 * ConnectionPointImpl_Destroy
103 static void ConnectionPointImpl_Destroy(ConnectionPointImpl *Obj)
106 for(i = 0; i < Obj->maxSinks; i++) {
108 IUnknown_Release(Obj->sinks[i]);
109 Obj->sinks[i] = NULL;
112 HeapFree(GetProcessHeap(), 0, Obj->sinks);
113 HeapFree(GetProcessHeap(), 0, Obj);
117 static ULONG WINAPI ConnectionPointImpl_AddRef(IConnectionPoint* iface);
118 /************************************************************************
119 * ConnectionPointImpl_QueryInterface (IUnknown)
121 * See Windows documentation for more details on IUnknown methods.
123 static HRESULT WINAPI ConnectionPointImpl_QueryInterface(
124 IConnectionPoint* iface,
128 ICOM_THIS(ConnectionPointImpl, iface);
129 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
132 * Perform a sanity check on the parameters.
134 if ( (This==0) || (ppvObject==0) )
138 * Initialize the return parameter.
143 * Compare the riid with the interface IDs implemented by this object.
145 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
147 *ppvObject = (IConnectionPoint*)This;
149 else if (memcmp(&IID_IConnectionPoint, riid, sizeof(IID_IConnectionPoint)) == 0)
151 *ppvObject = (IConnectionPoint*)This;
155 * Check that we obtained an interface.
159 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
160 return E_NOINTERFACE;
164 * Query Interface always increases the reference count by one when it is
167 ConnectionPointImpl_AddRef((IConnectionPoint*)This);
173 /************************************************************************
174 * ConnectionPointImpl_AddRef (IUnknown)
176 * See Windows documentation for more details on IUnknown methods.
178 static ULONG WINAPI ConnectionPointImpl_AddRef(IConnectionPoint* iface)
180 ICOM_THIS(ConnectionPointImpl, iface);
181 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
187 /************************************************************************
188 * ConnectionPointImpl_Release (IUnknown)
190 * See Windows documentation for more details on IUnknown methods.
192 static ULONG WINAPI ConnectionPointImpl_Release(
193 IConnectionPoint* iface)
195 ICOM_THIS(ConnectionPointImpl, iface);
196 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
199 * Decrease the reference count on this object.
204 * If the reference count goes down to 0, perform suicide.
208 ConnectionPointImpl_Destroy(This);
216 /************************************************************************
217 * ConnectionPointImpl_GetConnectionInterface (IConnectionPoint)
220 static HRESULT WINAPI ConnectionPointImpl_GetConnectionInterface(
221 IConnectionPoint *iface,
224 ICOM_THIS(ConnectionPointImpl, iface);
225 TRACE("(%p)->(%p) returning %s\n", This, piid, debugstr_guid(&(This->iid)));
230 /************************************************************************
231 * ConnectionPointImpl_GetConnectionPointContainer (IConnectionPoint)
234 static HRESULT WINAPI ConnectionPointImpl_GetConnectionPointContainer(
235 IConnectionPoint *iface,
236 IConnectionPointContainer **ppCPC)
238 ICOM_THIS(ConnectionPointImpl, iface);
239 TRACE("(%p)->(%p)\n", This, ppCPC);
241 return IUnknown_QueryInterface(This->Obj,
242 &IID_IConnectionPointContainer,
246 /************************************************************************
247 * ConnectionPointImpl_Advise (IConnectionPoint)
250 static HRESULT WINAPI ConnectionPointImpl_Advise(IConnectionPoint *iface,
255 ICOM_THIS(ConnectionPointImpl, iface);
257 TRACE("(%p)->(%p, %p)\n", This, lpUnk, pdwCookie);
260 if(FAILED(IUnknown_QueryInterface(lpUnk, &This->iid, (LPVOID)&lpSink)))
261 return CONNECT_E_CANNOTCONNECT;
263 for(i = 0; i < This->maxSinks; i++) {
264 if(This->sinks[i] == NULL)
267 if(i == This->maxSinks) {
268 This->maxSinks += MAXSINKS;
269 This->sinks = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->sinks,
270 This->maxSinks * sizeof(IUnknown *));
272 This->sinks[i] = lpSink;
279 /************************************************************************
280 * ConnectionPointImpl_Unadvise (IConnectionPoint)
283 static HRESULT WINAPI ConnectionPointImpl_Unadvise(IConnectionPoint *iface,
286 ICOM_THIS(ConnectionPointImpl, iface);
287 TRACE("(%p)->(%ld)\n", This, dwCookie);
289 if(dwCookie == 0 || dwCookie > This->maxSinks) return E_INVALIDARG;
291 if(This->sinks[dwCookie-1] == NULL) return CONNECT_E_NOCONNECTION;
293 IUnknown_Release(This->sinks[dwCookie-1]);
294 This->sinks[dwCookie-1] = NULL;
299 /************************************************************************
300 * ConnectionPointImpl_EnumConnections (IConnectionPoint)
303 static HRESULT WINAPI ConnectionPointImpl_EnumConnections(
304 IConnectionPoint *iface,
305 LPENUMCONNECTIONS *ppEnum)
307 ICOM_THIS(ConnectionPointImpl, iface);
310 EnumConnectionsImpl *EnumObj;
313 TRACE("(%p)->(%p)\n", This, ppEnum);
317 if(This->nSinks == 0) return OLE_E_NOCONNECTION;
319 pCD = HeapAlloc(GetProcessHeap(), 0, sizeof(CONNECTDATA) * This->nSinks);
321 for(i = 0, nextslot = 0; i < This->maxSinks; i++) {
322 if(This->sinks[i] != NULL) {
323 pCD[nextslot].pUnk = This->sinks[i];
324 pCD[nextslot].dwCookie = i + 1;
328 assert(nextslot == This->nSinks);
330 /* Bump the ref count of this object up by one. It gets Released in
331 IEnumConnections_Release */
332 IUnknown_AddRef((IUnknown*)This);
334 EnumObj = EnumConnectionsImpl_Construct((IUnknown*)This, This->nSinks, pCD);
335 hr = IEnumConnections_QueryInterface((IEnumConnections*)EnumObj,
336 &IID_IEnumConnections, (LPVOID)ppEnum);
337 IEnumConnections_Release((IEnumConnections*)EnumObj);
339 HeapFree(GetProcessHeap(), 0, pCD);
343 static ICOM_VTABLE(IConnectionPoint) ConnectionPointImpl_VTable =
345 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
346 ConnectionPointImpl_QueryInterface,
347 ConnectionPointImpl_AddRef,
348 ConnectionPointImpl_Release,
349 ConnectionPointImpl_GetConnectionInterface,
350 ConnectionPointImpl_GetConnectionPointContainer,
351 ConnectionPointImpl_Advise,
352 ConnectionPointImpl_Unadvise,
353 ConnectionPointImpl_EnumConnections
357 static ICOM_VTABLE(IEnumConnections) EnumConnectionsImpl_VTable;
358 static ULONG WINAPI EnumConnectionsImpl_AddRef(IEnumConnections* iface);
360 /************************************************************************
361 * EnumConnectionsImpl_Construct
363 static EnumConnectionsImpl *EnumConnectionsImpl_Construct(IUnknown *pUnk,
367 EnumConnectionsImpl *Obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*Obj));
370 Obj->lpvtbl = &EnumConnectionsImpl_VTable;
373 Obj->pCD = HeapAlloc(GetProcessHeap(), 0, nSinks * sizeof(CONNECTDATA));
374 Obj->nConns = nSinks;
377 for(i = 0; i < nSinks; i++) {
378 Obj->pCD[i] = pCD[i];
379 IUnknown_AddRef(Obj->pCD[i].pUnk);
384 /************************************************************************
385 * EnumConnectionsImpl_Destroy
387 static void EnumConnectionsImpl_Destroy(EnumConnectionsImpl *Obj)
391 for(i = 0; i < Obj->nConns; i++)
392 IUnknown_Release(Obj->pCD[i].pUnk);
394 HeapFree(GetProcessHeap(), 0, Obj->pCD);
395 HeapFree(GetProcessHeap(), 0, Obj);
399 /************************************************************************
400 * EnumConnectionsImpl_QueryInterface (IUnknown)
402 * See Windows documentation for more details on IUnknown methods.
404 static HRESULT WINAPI EnumConnectionsImpl_QueryInterface(
405 IEnumConnections* iface,
409 ICOM_THIS(ConnectionPointImpl, iface);
410 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
413 * Perform a sanity check on the parameters.
415 if ( (This==0) || (ppvObject==0) )
419 * Initialize the return parameter.
424 * Compare the riid with the interface IDs implemented by this object.
426 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
428 *ppvObject = (IEnumConnections*)This;
430 else if (memcmp(&IID_IEnumConnections, riid, sizeof(IID_IEnumConnections)) == 0)
432 *ppvObject = (IEnumConnections*)This;
436 * Check that we obtained an interface.
440 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
441 return E_NOINTERFACE;
445 * Query Interface always increases the reference count by one when it is
448 EnumConnectionsImpl_AddRef((IEnumConnections*)This);
454 /************************************************************************
455 * EnumConnectionsImpl_AddRef (IUnknown)
457 * See Windows documentation for more details on IUnknown methods.
459 static ULONG WINAPI EnumConnectionsImpl_AddRef(IEnumConnections* iface)
461 ICOM_THIS(EnumConnectionsImpl, iface);
462 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
464 IUnknown_AddRef(This->pUnk);
468 /************************************************************************
469 * EnumConnectionsImpl_Release (IUnknown)
471 * See Windows documentation for more details on IUnknown methods.
473 static ULONG WINAPI EnumConnectionsImpl_Release(IEnumConnections* iface)
475 ICOM_THIS(EnumConnectionsImpl, iface);
476 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
478 IUnknown_Release(This->pUnk);
481 * Decrease the reference count on this object.
486 * If the reference count goes down to 0, perform suicide.
490 EnumConnectionsImpl_Destroy(This);
498 /************************************************************************
499 * EnumConnectionsImpl_Next (IEnumConnections)
502 static HRESULT WINAPI EnumConnectionsImpl_Next(IEnumConnections* iface,
503 ULONG cConn, LPCONNECTDATA pCD,
506 ICOM_THIS(EnumConnectionsImpl, iface);
508 TRACE("(%p)->(%ld, %p, %p)\n", This, cConn, pCD, pEnum);
516 if(This->nCur >= This->nConns)
519 while(This->nCur < This->nConns && cConn) {
520 *pCD++ = This->pCD[This->nCur];
521 IUnknown_AddRef(This->pCD[This->nCur].pUnk);
534 /************************************************************************
535 * EnumConnectionsImpl_Skip (IEnumConnections)
538 static HRESULT WINAPI EnumConnectionsImpl_Skip(IEnumConnections* iface,
541 ICOM_THIS(EnumConnectionsImpl, iface);
542 TRACE("(%p)->(%ld)\n", This, cSkip);
544 if(This->nCur + cSkip >= This->nConns)
553 /************************************************************************
554 * EnumConnectionsImpl_Reset (IEnumConnections)
557 static HRESULT WINAPI EnumConnectionsImpl_Reset(IEnumConnections* iface)
559 ICOM_THIS(EnumConnectionsImpl, iface);
560 TRACE("(%p)\n", This);
568 /************************************************************************
569 * EnumConnectionsImpl_Clone (IEnumConnections)
572 static HRESULT WINAPI EnumConnectionsImpl_Clone(IEnumConnections* iface,
573 LPENUMCONNECTIONS *ppEnum)
575 ICOM_THIS(EnumConnectionsImpl, iface);
576 EnumConnectionsImpl *newObj;
577 TRACE("(%p)->(%p)\n", This, ppEnum);
579 newObj = EnumConnectionsImpl_Construct(This->pUnk, This->nConns, This->pCD);
580 newObj->nCur = This->nCur;
581 *ppEnum = (LPENUMCONNECTIONS)newObj;
582 IUnknown_AddRef(This->pUnk);
586 static ICOM_VTABLE(IEnumConnections) EnumConnectionsImpl_VTable =
588 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
589 EnumConnectionsImpl_QueryInterface,
590 EnumConnectionsImpl_AddRef,
591 EnumConnectionsImpl_Release,
592 EnumConnectionsImpl_Next,
593 EnumConnectionsImpl_Skip,
594 EnumConnectionsImpl_Reset,
595 EnumConnectionsImpl_Clone
598 /************************************************************************
600 * The exported function to create the connection point.
601 * NB not a windows API
604 * pUnk [in] IUnknown of object to which the ConnectionPoint is associated.
605 * Needed to access IConnectionPointContainer.
607 * riid [in] IID of sink interface that this ConnectionPoint manages
609 * pCP [out] returns IConnectionPoint
612 HRESULT CreateConnectionPoint(IUnknown *pUnk, REFIID riid,
613 IConnectionPoint **pCP)
615 ConnectionPointImpl *Obj;
618 Obj = ConnectionPointImpl_Construct(pUnk, riid);
619 if(!Obj) return E_OUTOFMEMORY;
621 hr = IConnectionPoint_QueryInterface((IConnectionPoint *)Obj,
622 &IID_IConnectionPoint, (LPVOID)pCP);
623 IConnectionPoint_Release((IConnectionPoint *)Obj);