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
);