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.
15 #include "wine/obj_base.h"
16 #include "wine/obj_connection.h"
19 #include "debugtools.h"
21 DEFAULT_DEBUG_CHANNEL(ole)
25 /************************************************************************
26 * Implementation of IConnectionPoint
28 typedef struct ConnectionPointImpl {
30 ICOM_VTABLE(IConnectionPoint) *lpvtbl;
32 /* IUnknown of our main object*/
38 /* IID of sink interface */
41 /* Array of sink IUnknowns */
46 } ConnectionPointImpl;
48 static ICOM_VTABLE(IConnectionPoint) ConnectionPointImpl_VTable;
51 /************************************************************************
52 * Implementation of IEnumConnections
54 typedef struct EnumConnectionsImpl {
56 ICOM_VTABLE(IEnumConnections) *lpvtbl;
60 /* IUnknown of ConnectionPoint, used for ref counting */
67 /* Next connection to enumerate from */
70 } EnumConnectionsImpl;
72 static EnumConnectionsImpl *EnumConnectionsImpl_Construct(IUnknown *pUnk,
77 /************************************************************************
78 * ConnectionPointImpl_Construct
80 static ConnectionPointImpl *ConnectionPointImpl_Construct(IUnknown *pUnk,
83 ConnectionPointImpl *Obj;
85 Obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*Obj));
86 Obj->lpvtbl = &ConnectionPointImpl_VTable;
90 Obj->maxSinks = MAXSINKS;
91 Obj->sinks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
92 sizeof(IUnknown*) * MAXSINKS);
97 /************************************************************************
98 * ConnectionPointImpl_Destroy
100 static void ConnectionPointImpl_Destroy(ConnectionPointImpl *Obj)
103 for(i = 0; i < Obj->maxSinks; i++) {
105 IUnknown_Release(Obj->sinks[i]);
106 Obj->sinks[i] = NULL;
109 HeapFree(GetProcessHeap(), 0, Obj->sinks);
110 HeapFree(GetProcessHeap(), 0, Obj);
114 static ULONG WINAPI ConnectionPointImpl_AddRef(IConnectionPoint* iface);
115 /************************************************************************
116 * ConnectionPointImpl_QueryInterface (IUnknown)
118 * See Windows documentation for more details on IUnknown methods.
120 static HRESULT WINAPI ConnectionPointImpl_QueryInterface(
121 IConnectionPoint* iface,
125 ICOM_THIS(ConnectionPointImpl, iface);
126 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
129 * Perform a sanity check on the parameters.
131 if ( (This==0) || (ppvObject==0) )
135 * Initialize the return parameter.
140 * Compare the riid with the interface IDs implemented by this object.
142 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
144 *ppvObject = (IConnectionPoint*)This;
146 else if (memcmp(&IID_IConnectionPoint, riid, sizeof(IID_IConnectionPoint)) == 0)
148 *ppvObject = (IConnectionPoint*)This;
152 * Check that we obtained an interface.
156 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
157 return E_NOINTERFACE;
161 * Query Interface always increases the reference count by one when it is
164 ConnectionPointImpl_AddRef((IConnectionPoint*)This);
170 /************************************************************************
171 * ConnectionPointImpl_AddRef (IUnknown)
173 * See Windows documentation for more details on IUnknown methods.
175 static ULONG WINAPI ConnectionPointImpl_AddRef(IConnectionPoint* iface)
177 ICOM_THIS(ConnectionPointImpl, iface);
178 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
184 /************************************************************************
185 * ConnectionPointImpl_Release (IUnknown)
187 * See Windows documentation for more details on IUnknown methods.
189 static ULONG WINAPI ConnectionPointImpl_Release(
190 IConnectionPoint* iface)
192 ICOM_THIS(ConnectionPointImpl, iface);
193 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
196 * Decrease the reference count on this object.
201 * If the reference count goes down to 0, perform suicide.
205 ConnectionPointImpl_Destroy(This);
213 /************************************************************************
214 * ConnectionPointImpl_GetConnectionInterface (IConnectionPoint)
217 static HRESULT WINAPI ConnectionPointImpl_GetConnectionInterface(
218 IConnectionPoint *iface,
221 ICOM_THIS(ConnectionPointImpl, iface);
222 TRACE("(%p)->(%p) returning %s\n", This, piid, debugstr_guid(&(This->iid)));
227 /************************************************************************
228 * ConnectionPointImpl_GetConnectionPointContainer (IConnectionPoint)
231 static HRESULT WINAPI ConnectionPointImpl_GetConnectionPointContainer(
232 IConnectionPoint *iface,
233 IConnectionPointContainer **ppCPC)
235 ICOM_THIS(ConnectionPointImpl, iface);
236 TRACE("(%p)->(%p)\n", This, ppCPC);
238 return IUnknown_QueryInterface(This->Obj,
239 &IID_IConnectionPointContainer,
243 /************************************************************************
244 * ConnectionPointImpl_Advise (IConnectionPoint)
247 static HRESULT WINAPI ConnectionPointImpl_Advise(IConnectionPoint *iface,
252 ICOM_THIS(ConnectionPointImpl, iface);
254 TRACE("(%p)->(%p, %p)\n", This, lpUnk, pdwCookie);
257 if(FAILED(IUnknown_QueryInterface(lpUnk, &This->iid, (LPVOID)&lpSink)))
258 return CONNECT_E_CANNOTCONNECT;
260 for(i = 0; i < This->maxSinks; i++) {
261 if(This->sinks[i] == NULL)
264 if(i == This->maxSinks) {
265 This->maxSinks += MAXSINKS;
266 This->sinks = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->sinks,
267 This->maxSinks * sizeof(IUnknown *));
269 This->sinks[i] = lpSink;
276 /************************************************************************
277 * ConnectionPointImpl_Unadvise (IConnectionPoint)
280 static HRESULT WINAPI ConnectionPointImpl_Unadvise(IConnectionPoint *iface,
283 ICOM_THIS(ConnectionPointImpl, iface);
284 TRACE("(%p)->(%ld)\n", This, dwCookie);
286 if(dwCookie == 0 || dwCookie > This->maxSinks) return E_INVALIDARG;
288 if(This->sinks[dwCookie-1] == NULL) return CONNECT_E_NOCONNECTION;
290 IUnknown_Release(This->sinks[dwCookie-1]);
291 This->sinks[dwCookie-1] = NULL;
296 /************************************************************************
297 * ConnectionPointImpl_EnumConnections (IConnectionPoint)
300 static HRESULT WINAPI ConnectionPointImpl_EnumConnections(
301 IConnectionPoint *iface,
302 LPENUMCONNECTIONS *ppEnum)
304 ICOM_THIS(ConnectionPointImpl, iface);
307 EnumConnectionsImpl *EnumObj;
310 TRACE("(%p)->(%p)\n", This, ppEnum);
314 if(This->nSinks == 0) return OLE_E_NOCONNECTION;
316 pCD = HeapAlloc(GetProcessHeap(), 0, sizeof(CONNECTDATA) * This->nSinks);
318 for(i = 0, nextslot = 0; i < This->maxSinks; i++) {
319 if(This->sinks[i] != NULL) {
320 pCD[nextslot].pUnk = This->sinks[i];
321 pCD[nextslot].dwCookie = i + 1;
325 assert(nextslot == This->nSinks);
327 /* Bump the ref count of this object up by one. It gets Released in
328 IEnumConnections_Release */
329 IUnknown_AddRef((IUnknown*)This);
331 EnumObj = EnumConnectionsImpl_Construct((IUnknown*)This, This->nSinks, pCD);
332 hr = IEnumConnections_QueryInterface((IEnumConnections*)EnumObj,
333 &IID_IEnumConnections, (LPVOID)ppEnum);
334 IEnumConnections_Release((IEnumConnections*)EnumObj);
336 HeapFree(GetProcessHeap(), 0, pCD);
340 static ICOM_VTABLE(IConnectionPoint) ConnectionPointImpl_VTable =
342 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
343 ConnectionPointImpl_QueryInterface,
344 ConnectionPointImpl_AddRef,
345 ConnectionPointImpl_Release,
346 ConnectionPointImpl_GetConnectionInterface,
347 ConnectionPointImpl_GetConnectionPointContainer,
348 ConnectionPointImpl_Advise,
349 ConnectionPointImpl_Unadvise,
350 ConnectionPointImpl_EnumConnections
354 static ICOM_VTABLE(IEnumConnections) EnumConnectionsImpl_VTable;
355 static ULONG WINAPI EnumConnectionsImpl_AddRef(IEnumConnections* iface);
357 /************************************************************************
358 * EnumConnectionsImpl_Construct
360 static EnumConnectionsImpl *EnumConnectionsImpl_Construct(IUnknown *pUnk,
364 EnumConnectionsImpl *Obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*Obj));
367 Obj->lpvtbl = &EnumConnectionsImpl_VTable;
370 Obj->pCD = HeapAlloc(GetProcessHeap(), 0, nSinks * sizeof(CONNECTDATA));
371 Obj->nConns = nSinks;
374 for(i = 0; i < nSinks; i++) {
375 Obj->pCD[i] = pCD[i];
376 IUnknown_AddRef(Obj->pCD[i].pUnk);
381 /************************************************************************
382 * EnumConnectionsImpl_Destroy
384 static void EnumConnectionsImpl_Destroy(EnumConnectionsImpl *Obj)
388 for(i = 0; i < Obj->nConns; i++)
389 IUnknown_Release(Obj->pCD[i].pUnk);
391 HeapFree(GetProcessHeap(), 0, Obj->pCD);
392 HeapFree(GetProcessHeap(), 0, Obj);
396 /************************************************************************
397 * EnumConnectionsImpl_QueryInterface (IUnknown)
399 * See Windows documentation for more details on IUnknown methods.
401 static HRESULT WINAPI EnumConnectionsImpl_QueryInterface(
402 IEnumConnections* iface,
406 ICOM_THIS(ConnectionPointImpl, iface);
407 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
410 * Perform a sanity check on the parameters.
412 if ( (This==0) || (ppvObject==0) )
416 * Initialize the return parameter.
421 * Compare the riid with the interface IDs implemented by this object.
423 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
425 *ppvObject = (IEnumConnections*)This;
427 else if (memcmp(&IID_IEnumConnections, riid, sizeof(IID_IEnumConnections)) == 0)
429 *ppvObject = (IEnumConnections*)This;
433 * Check that we obtained an interface.
437 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
438 return E_NOINTERFACE;
442 * Query Interface always increases the reference count by one when it is
445 EnumConnectionsImpl_AddRef((IEnumConnections*)This);
451 /************************************************************************
452 * EnumConnectionsImpl_AddRef (IUnknown)
454 * See Windows documentation for more details on IUnknown methods.
456 static ULONG WINAPI EnumConnectionsImpl_AddRef(IEnumConnections* iface)
458 ICOM_THIS(EnumConnectionsImpl, iface);
459 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
461 IUnknown_AddRef(This->pUnk);
465 /************************************************************************
466 * EnumConnectionsImpl_Release (IUnknown)
468 * See Windows documentation for more details on IUnknown methods.
470 static ULONG WINAPI EnumConnectionsImpl_Release(IEnumConnections* iface)
472 ICOM_THIS(EnumConnectionsImpl, iface);
473 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
475 IUnknown_Release(This->pUnk);
478 * Decrease the reference count on this object.
483 * If the reference count goes down to 0, perform suicide.
487 EnumConnectionsImpl_Destroy(This);
495 /************************************************************************
496 * EnumConnectionsImpl_Next (IEnumConnections)
499 static HRESULT WINAPI EnumConnectionsImpl_Next(IEnumConnections* iface,
500 ULONG cConn, LPCONNECTDATA pCD,
503 ICOM_THIS(EnumConnectionsImpl, iface);
505 TRACE("(%p)->(%ld, %p, %p)\n", This, cConn, pCD, pEnum);
513 if(This->nCur >= This->nConns)
516 while(This->nCur < This->nConns && cConn) {
517 *pCD++ = This->pCD[This->nCur];
518 IUnknown_AddRef(This->pCD[This->nCur].pUnk);
531 /************************************************************************
532 * EnumConnectionsImpl_Skip (IEnumConnections)
535 static HRESULT WINAPI EnumConnectionsImpl_Skip(IEnumConnections* iface,
538 ICOM_THIS(EnumConnectionsImpl, iface);
539 TRACE("(%p)->(%ld)\n", This, cSkip);
541 if(This->nCur + cSkip >= This->nConns)
550 /************************************************************************
551 * EnumConnectionsImpl_Reset (IEnumConnections)
554 static HRESULT WINAPI EnumConnectionsImpl_Reset(IEnumConnections* iface)
556 ICOM_THIS(EnumConnectionsImpl, iface);
557 TRACE("(%p)\n", This);
565 /************************************************************************
566 * EnumConnectionsImpl_Clone (IEnumConnections)
569 static HRESULT WINAPI EnumConnectionsImpl_Clone(IEnumConnections* iface,
570 LPENUMCONNECTIONS *ppEnum)
572 ICOM_THIS(EnumConnectionsImpl, iface);
573 EnumConnectionsImpl *newObj;
574 TRACE("(%p)->(%p)\n", This, ppEnum);
576 newObj = EnumConnectionsImpl_Construct(This->pUnk, This->nConns, This->pCD);
577 newObj->nCur = This->nCur;
578 *ppEnum = (LPENUMCONNECTIONS)newObj;
579 IUnknown_AddRef(This->pUnk);
583 static ICOM_VTABLE(IEnumConnections) EnumConnectionsImpl_VTable =
585 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
586 EnumConnectionsImpl_QueryInterface,
587 EnumConnectionsImpl_AddRef,
588 EnumConnectionsImpl_Release,
589 EnumConnectionsImpl_Next,
590 EnumConnectionsImpl_Skip,
591 EnumConnectionsImpl_Reset,
592 EnumConnectionsImpl_Clone
595 /************************************************************************
597 * The exported function to create the connection point.
598 * NB not a windows API
601 * pUnk [in] IUnknown of object to which the ConnectionPoint is associated.
602 * Needed to access IConnectionPointContainer.
604 * riid [in] IID of sink interface that this ConnectionPoint manages
606 * pCP [out] returns IConnectionPoint
609 HRESULT CreateConnectionPoint(IUnknown *pUnk, REFIID riid,
610 IConnectionPoint **pCP)
612 ConnectionPointImpl *Obj;
615 Obj = ConnectionPointImpl_Construct(pUnk, riid);
616 if(!Obj) return E_OUTOFMEMORY;
618 hr = IConnectionPoint_QueryInterface((IConnectionPoint *)Obj,
619 &IID_IConnectionPoint, (LPVOID)pCP);
620 IConnectionPoint_Release((IConnectionPoint *)Obj);