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.
13 #include "wine/obj_base.h"
14 #include "wine/obj_connection.h"
17 #include "debugtools.h"
19 DEFAULT_DEBUG_CHANNEL(ole
)
23 /************************************************************************
24 * Implementation of IConnectionPoint
26 typedef struct ConnectionPointImpl
{
28 ICOM_VTABLE(IConnectionPoint
) *lpvtbl
;
30 /* IUnknown of our main object*/
36 /* IID of sink interface */
39 /* Array of sink IUnknowns */
44 } ConnectionPointImpl
;
46 static ICOM_VTABLE(IConnectionPoint
) ConnectionPointImpl_VTable
;
49 /************************************************************************
50 * Implementation of IEnumConnections
52 typedef struct EnumConnectionsImpl
{
54 ICOM_VTABLE(IEnumConnections
) *lpvtbl
;
58 /* IUnknown of ConnectionPoint, used for ref counting */
65 /* Next connection to enumerate from */
68 } EnumConnectionsImpl
;
70 static EnumConnectionsImpl
*EnumConnectionsImpl_Construct(IUnknown
*pUnk
,
75 /************************************************************************
76 * ConnectionPointImpl_Construct
78 static ConnectionPointImpl
*ConnectionPointImpl_Construct(IUnknown
*pUnk
,
81 ConnectionPointImpl
*Obj
;
83 Obj
= HeapAlloc(GetProcessHeap(), 0, sizeof(*Obj
));
84 Obj
->lpvtbl
= &ConnectionPointImpl_VTable
;
88 Obj
->maxSinks
= MAXSINKS
;
89 Obj
->sinks
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
90 sizeof(IUnknown
*) * MAXSINKS
);
95 /************************************************************************
96 * ConnectionPointImpl_Destroy
98 static void ConnectionPointImpl_Destroy(ConnectionPointImpl
*Obj
)
101 for(i
= 0; i
< Obj
->maxSinks
; i
++) {
103 IUnknown_Release(Obj
->sinks
[i
]);
104 Obj
->sinks
[i
] = NULL
;
107 HeapFree(GetProcessHeap(), 0, Obj
->sinks
);
108 HeapFree(GetProcessHeap(), 0, Obj
);
112 static ULONG WINAPI
ConnectionPointImpl_AddRef(IConnectionPoint
* iface
);
113 /************************************************************************
114 * ConnectionPointImpl_QueryInterface (IUnknown)
116 * See Windows documentation for more details on IUnknown methods.
118 static HRESULT WINAPI
ConnectionPointImpl_QueryInterface(
119 IConnectionPoint
* iface
,
123 ICOM_THIS(ConnectionPointImpl
, iface
);
124 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
127 * Perform a sanity check on the parameters.
129 if ( (This
==0) || (ppvObject
==0) )
133 * Initialize the return parameter.
138 * Compare the riid with the interface IDs implemented by this object.
140 if (memcmp(&IID_IUnknown
, riid
, sizeof(IID_IUnknown
)) == 0)
142 *ppvObject
= (IConnectionPoint
*)This
;
144 else if (memcmp(&IID_IConnectionPoint
, riid
, sizeof(IID_IConnectionPoint
)) == 0)
146 *ppvObject
= (IConnectionPoint
*)This
;
150 * Check that we obtained an interface.
154 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid
));
155 return E_NOINTERFACE
;
159 * Query Interface always increases the reference count by one when it is
162 ConnectionPointImpl_AddRef((IConnectionPoint
*)This
);
168 /************************************************************************
169 * ConnectionPointImpl_AddRef (IUnknown)
171 * See Windows documentation for more details on IUnknown methods.
173 static ULONG WINAPI
ConnectionPointImpl_AddRef(IConnectionPoint
* iface
)
175 ICOM_THIS(ConnectionPointImpl
, iface
);
176 TRACE("(%p)->(ref=%ld)\n", This
, This
->ref
);
182 /************************************************************************
183 * ConnectionPointImpl_Release (IUnknown)
185 * See Windows documentation for more details on IUnknown methods.
187 static ULONG WINAPI
ConnectionPointImpl_Release(
188 IConnectionPoint
* iface
)
190 ICOM_THIS(ConnectionPointImpl
, iface
);
191 TRACE("(%p)->(ref=%ld)\n", This
, This
->ref
);
194 * Decrease the reference count on this object.
199 * If the reference count goes down to 0, perform suicide.
203 ConnectionPointImpl_Destroy(This
);
211 /************************************************************************
212 * ConnectionPointImpl_GetConnectionInterface (IConnectionPoint)
215 static HRESULT WINAPI
ConnectionPointImpl_GetConnectionInterface(
216 IConnectionPoint
*iface
,
219 ICOM_THIS(ConnectionPointImpl
, iface
);
220 TRACE("(%p)->(%p) returning %s\n", This
, piid
, debugstr_guid(&(This
->iid
)));
225 /************************************************************************
226 * ConnectionPointImpl_GetConnectionPointContainer (IConnectionPoint)
229 static HRESULT WINAPI
ConnectionPointImpl_GetConnectionPointContainer(
230 IConnectionPoint
*iface
,
231 IConnectionPointContainer
**ppCPC
)
233 ICOM_THIS(ConnectionPointImpl
, iface
);
234 TRACE("(%p)->(%p)\n", This
, ppCPC
);
236 return IUnknown_QueryInterface(This
->Obj
,
237 &IID_IConnectionPointContainer
,
241 /************************************************************************
242 * ConnectionPointImpl_Advise (IConnectionPoint)
245 static HRESULT WINAPI
ConnectionPointImpl_Advise(IConnectionPoint
*iface
,
250 ICOM_THIS(ConnectionPointImpl
, iface
);
252 TRACE("(%p)->(%p, %p)\n", This
, lpUnk
, pdwCookie
);
255 if(FAILED(IUnknown_QueryInterface(lpUnk
, &This
->iid
, (LPVOID
)&lpSink
)))
256 return CONNECT_E_CANNOTCONNECT
;
258 for(i
= 0; i
< This
->maxSinks
; i
++) {
259 if(This
->sinks
[i
] == NULL
)
262 if(i
== This
->maxSinks
) {
263 This
->maxSinks
+= MAXSINKS
;
264 This
->sinks
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->sinks
,
265 This
->maxSinks
* sizeof(IUnknown
*));
267 This
->sinks
[i
] = lpSink
;
274 /************************************************************************
275 * ConnectionPointImpl_Unadvise (IConnectionPoint)
278 static HRESULT WINAPI
ConnectionPointImpl_Unadvise(IConnectionPoint
*iface
,
281 ICOM_THIS(ConnectionPointImpl
, iface
);
282 TRACE("(%p)->(%ld)\n", This
, dwCookie
);
284 if(dwCookie
== 0 || dwCookie
> This
->maxSinks
) return E_INVALIDARG
;
286 if(This
->sinks
[dwCookie
-1] == NULL
) return CONNECT_E_NOCONNECTION
;
288 IUnknown_Release(This
->sinks
[dwCookie
-1]);
289 This
->sinks
[dwCookie
-1] = NULL
;
294 /************************************************************************
295 * ConnectionPointImpl_EnumConnections (IConnectionPoint)
298 static HRESULT WINAPI
ConnectionPointImpl_EnumConnections(
299 IConnectionPoint
*iface
,
300 LPENUMCONNECTIONS
*ppEnum
)
302 ICOM_THIS(ConnectionPointImpl
, iface
);
305 EnumConnectionsImpl
*EnumObj
;
308 TRACE("(%p)->(%p)\n", This
, ppEnum
);
312 if(This
->nSinks
== 0) return OLE_E_NOCONNECTION
;
314 pCD
= HeapAlloc(GetProcessHeap(), 0, sizeof(CONNECTDATA
) * This
->nSinks
);
316 for(i
= 0, nextslot
= 0; i
< This
->maxSinks
; i
++) {
317 if(This
->sinks
[i
] != NULL
) {
318 pCD
[nextslot
].pUnk
= This
->sinks
[i
];
319 pCD
[nextslot
].dwCookie
= i
+ 1;
323 assert(nextslot
== This
->nSinks
);
325 /* Bump the ref count of this object up by one. It gets Released in
326 IEnumConnections_Release */
327 IUnknown_AddRef((IUnknown
*)This
);
329 EnumObj
= EnumConnectionsImpl_Construct((IUnknown
*)This
, This
->nSinks
, pCD
);
330 hr
= IEnumConnections_QueryInterface((IEnumConnections
*)EnumObj
,
331 &IID_IEnumConnections
, (LPVOID
)ppEnum
);
332 IEnumConnections_Release((IEnumConnections
*)EnumObj
);
334 HeapFree(GetProcessHeap(), 0, pCD
);
338 static ICOM_VTABLE(IConnectionPoint
) ConnectionPointImpl_VTable
=
340 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
341 ConnectionPointImpl_QueryInterface
,
342 ConnectionPointImpl_AddRef
,
343 ConnectionPointImpl_Release
,
344 ConnectionPointImpl_GetConnectionInterface
,
345 ConnectionPointImpl_GetConnectionPointContainer
,
346 ConnectionPointImpl_Advise
,
347 ConnectionPointImpl_Unadvise
,
348 ConnectionPointImpl_EnumConnections
352 static ICOM_VTABLE(IEnumConnections
) EnumConnectionsImpl_VTable
;
353 static ULONG WINAPI
EnumConnectionsImpl_AddRef(IEnumConnections
* iface
);
355 /************************************************************************
356 * EnumConnectionsImpl_Construct
358 static EnumConnectionsImpl
*EnumConnectionsImpl_Construct(IUnknown
*pUnk
,
362 EnumConnectionsImpl
*Obj
= HeapAlloc(GetProcessHeap(), 0, sizeof(*Obj
));
365 Obj
->lpvtbl
= &EnumConnectionsImpl_VTable
;
368 Obj
->pCD
= HeapAlloc(GetProcessHeap(), 0, nSinks
* sizeof(CONNECTDATA
));
369 Obj
->nConns
= nSinks
;
372 for(i
= 0; i
< nSinks
; i
++) {
373 Obj
->pCD
[i
] = pCD
[i
];
374 IUnknown_AddRef(Obj
->pCD
[i
].pUnk
);
379 /************************************************************************
380 * EnumConnectionsImpl_Destroy
382 static void EnumConnectionsImpl_Destroy(EnumConnectionsImpl
*Obj
)
386 for(i
= 0; i
< Obj
->nConns
; i
++)
387 IUnknown_Release(Obj
->pCD
[i
].pUnk
);
389 HeapFree(GetProcessHeap(), 0, Obj
->pCD
);
390 HeapFree(GetProcessHeap(), 0, Obj
);
394 /************************************************************************
395 * EnumConnectionsImpl_QueryInterface (IUnknown)
397 * See Windows documentation for more details on IUnknown methods.
399 static HRESULT WINAPI
EnumConnectionsImpl_QueryInterface(
400 IEnumConnections
* iface
,
404 ICOM_THIS(ConnectionPointImpl
, iface
);
405 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
408 * Perform a sanity check on the parameters.
410 if ( (This
==0) || (ppvObject
==0) )
414 * Initialize the return parameter.
419 * Compare the riid with the interface IDs implemented by this object.
421 if (memcmp(&IID_IUnknown
, riid
, sizeof(IID_IUnknown
)) == 0)
423 *ppvObject
= (IEnumConnections
*)This
;
425 else if (memcmp(&IID_IEnumConnections
, riid
, sizeof(IID_IEnumConnections
)) == 0)
427 *ppvObject
= (IEnumConnections
*)This
;
431 * Check that we obtained an interface.
435 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid
));
436 return E_NOINTERFACE
;
440 * Query Interface always increases the reference count by one when it is
443 EnumConnectionsImpl_AddRef((IEnumConnections
*)This
);
449 /************************************************************************
450 * EnumConnectionsImpl_AddRef (IUnknown)
452 * See Windows documentation for more details on IUnknown methods.
454 static ULONG WINAPI
EnumConnectionsImpl_AddRef(IEnumConnections
* iface
)
456 ICOM_THIS(EnumConnectionsImpl
, iface
);
457 TRACE("(%p)->(ref=%ld)\n", This
, This
->ref
);
459 IUnknown_AddRef(This
->pUnk
);
463 /************************************************************************
464 * EnumConnectionsImpl_Release (IUnknown)
466 * See Windows documentation for more details on IUnknown methods.
468 static ULONG WINAPI
EnumConnectionsImpl_Release(IEnumConnections
* iface
)
470 ICOM_THIS(EnumConnectionsImpl
, iface
);
471 TRACE("(%p)->(ref=%ld)\n", This
, This
->ref
);
473 IUnknown_Release(This
->pUnk
);
476 * Decrease the reference count on this object.
481 * If the reference count goes down to 0, perform suicide.
485 EnumConnectionsImpl_Destroy(This
);
493 /************************************************************************
494 * EnumConnectionsImpl_Next (IEnumConnections)
497 static HRESULT WINAPI
EnumConnectionsImpl_Next(IEnumConnections
* iface
,
498 ULONG cConn
, LPCONNECTDATA pCD
,
501 ICOM_THIS(EnumConnectionsImpl
, iface
);
503 TRACE("(%p)->(%ld, %p, %p)\n", This
, cConn
, pCD
, pEnum
);
511 if(This
->nCur
>= This
->nConns
)
514 while(This
->nCur
< This
->nConns
&& cConn
) {
515 *pCD
++ = This
->pCD
[This
->nCur
];
516 IUnknown_AddRef(This
->pCD
[This
->nCur
].pUnk
);
529 /************************************************************************
530 * EnumConnectionsImpl_Skip (IEnumConnections)
533 static HRESULT WINAPI
EnumConnectionsImpl_Skip(IEnumConnections
* iface
,
536 ICOM_THIS(EnumConnectionsImpl
, iface
);
537 TRACE("(%p)->(%ld)\n", This
, cSkip
);
539 if(This
->nCur
+ cSkip
>= This
->nConns
)
548 /************************************************************************
549 * EnumConnectionsImpl_Reset (IEnumConnections)
552 static HRESULT WINAPI
EnumConnectionsImpl_Reset(IEnumConnections
* iface
)
554 ICOM_THIS(EnumConnectionsImpl
, iface
);
555 TRACE("(%p)\n", This
);
563 /************************************************************************
564 * EnumConnectionsImpl_Clone (IEnumConnections)
567 static HRESULT WINAPI
EnumConnectionsImpl_Clone(IEnumConnections
* iface
,
568 LPENUMCONNECTIONS
*ppEnum
)
570 ICOM_THIS(EnumConnectionsImpl
, iface
);
571 EnumConnectionsImpl
*newObj
;
572 TRACE("(%p)->(%p)\n", This
, ppEnum
);
574 newObj
= EnumConnectionsImpl_Construct(This
->pUnk
, This
->nConns
, This
->pCD
);
575 newObj
->nCur
= This
->nCur
;
576 *ppEnum
= (LPENUMCONNECTIONS
)newObj
;
577 IUnknown_AddRef(This
->pUnk
);
581 static ICOM_VTABLE(IEnumConnections
) EnumConnectionsImpl_VTable
=
583 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
584 EnumConnectionsImpl_QueryInterface
,
585 EnumConnectionsImpl_AddRef
,
586 EnumConnectionsImpl_Release
,
587 EnumConnectionsImpl_Next
,
588 EnumConnectionsImpl_Skip
,
589 EnumConnectionsImpl_Reset
,
590 EnumConnectionsImpl_Clone
593 /************************************************************************
595 * The exported function to create the connection point.
596 * NB not a windows API
599 * pUnk [in] IUnknown of object to which the ConnectionPoint is associated.
600 * Needed to access IConnectionPointContainer.
602 * riid [in] IID of sink interface that this ConnectionPoint manages
604 * pCP [out] returns IConnectionPoint
607 HRESULT
CreateConnectionPoint(IUnknown
*pUnk
, REFIID riid
,
608 IConnectionPoint
**pCP
)
610 ConnectionPointImpl
*Obj
;
613 Obj
= ConnectionPointImpl_Construct(pUnk
, riid
);
614 if(!Obj
) return E_OUTOFMEMORY
;
616 hr
= IConnectionPoint_QueryInterface((IConnectionPoint
*)Obj
,
617 &IID_IConnectionPoint
, (LPVOID
)pCP
);
618 IConnectionPoint_Release((IConnectionPoint
*)Obj
);