2 * Implementation of a generic ConnectionPoint object.
4 * Copyright 2000 Huw D M Davies for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * See one exported function here is CreateConnectionPoint, see
22 * comments just above that function for information.
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
43 /************************************************************************
44 * Implementation of IConnectionPoint
46 typedef struct ConnectionPointImpl
{
48 ICOM_VTABLE(IConnectionPoint
) *lpvtbl
;
50 /* IUnknown of our main object*/
56 /* IID of sink interface */
59 /* Array of sink IUnknowns */
64 } ConnectionPointImpl
;
66 static ICOM_VTABLE(IConnectionPoint
) ConnectionPointImpl_VTable
;
69 /************************************************************************
70 * Implementation of IEnumConnections
72 typedef struct EnumConnectionsImpl
{
74 ICOM_VTABLE(IEnumConnections
) *lpvtbl
;
78 /* IUnknown of ConnectionPoint, used for ref counting */
85 /* Next connection to enumerate from */
88 } EnumConnectionsImpl
;
90 static EnumConnectionsImpl
*EnumConnectionsImpl_Construct(IUnknown
*pUnk
,
95 /************************************************************************
96 * ConnectionPointImpl_Construct
98 static ConnectionPointImpl
*ConnectionPointImpl_Construct(IUnknown
*pUnk
,
101 ConnectionPointImpl
*Obj
;
103 Obj
= HeapAlloc(GetProcessHeap(), 0, sizeof(*Obj
));
104 Obj
->lpvtbl
= &ConnectionPointImpl_VTable
;
108 Obj
->maxSinks
= MAXSINKS
;
109 Obj
->sinks
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
110 sizeof(IUnknown
*) * MAXSINKS
);
115 /************************************************************************
116 * ConnectionPointImpl_Destroy
118 static void ConnectionPointImpl_Destroy(ConnectionPointImpl
*Obj
)
121 for(i
= 0; i
< Obj
->maxSinks
; i
++) {
123 IUnknown_Release(Obj
->sinks
[i
]);
124 Obj
->sinks
[i
] = NULL
;
127 HeapFree(GetProcessHeap(), 0, Obj
->sinks
);
128 HeapFree(GetProcessHeap(), 0, Obj
);
132 static ULONG WINAPI
ConnectionPointImpl_AddRef(IConnectionPoint
* iface
);
133 /************************************************************************
134 * ConnectionPointImpl_QueryInterface (IUnknown)
136 * See Windows documentation for more details on IUnknown methods.
138 static HRESULT WINAPI
ConnectionPointImpl_QueryInterface(
139 IConnectionPoint
* iface
,
143 ICOM_THIS(ConnectionPointImpl
, iface
);
144 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
147 * Perform a sanity check on the parameters.
149 if ( (This
==0) || (ppvObject
==0) )
153 * Initialize the return parameter.
158 * Compare the riid with the interface IDs implemented by this object.
160 if (memcmp(&IID_IUnknown
, riid
, sizeof(IID_IUnknown
)) == 0)
162 *ppvObject
= (IConnectionPoint
*)This
;
164 else if (memcmp(&IID_IConnectionPoint
, riid
, sizeof(IID_IConnectionPoint
)) == 0)
166 *ppvObject
= (IConnectionPoint
*)This
;
170 * Check that we obtained an interface.
174 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid
));
175 return E_NOINTERFACE
;
179 * Query Interface always increases the reference count by one when it is
182 ConnectionPointImpl_AddRef((IConnectionPoint
*)This
);
188 /************************************************************************
189 * ConnectionPointImpl_AddRef (IUnknown)
191 * See Windows documentation for more details on IUnknown methods.
193 static ULONG WINAPI
ConnectionPointImpl_AddRef(IConnectionPoint
* iface
)
195 ICOM_THIS(ConnectionPointImpl
, iface
);
196 TRACE("(%p)->(ref=%ld)\n", This
, This
->ref
);
202 /************************************************************************
203 * ConnectionPointImpl_Release (IUnknown)
205 * See Windows documentation for more details on IUnknown methods.
207 static ULONG WINAPI
ConnectionPointImpl_Release(
208 IConnectionPoint
* iface
)
210 ICOM_THIS(ConnectionPointImpl
, iface
);
211 TRACE("(%p)->(ref=%ld)\n", This
, This
->ref
);
214 * Decrease the reference count on this object.
219 * If the reference count goes down to 0, perform suicide.
223 ConnectionPointImpl_Destroy(This
);
231 /************************************************************************
232 * ConnectionPointImpl_GetConnectionInterface (IConnectionPoint)
235 static HRESULT WINAPI
ConnectionPointImpl_GetConnectionInterface(
236 IConnectionPoint
*iface
,
239 ICOM_THIS(ConnectionPointImpl
, iface
);
240 TRACE("(%p)->(%p) returning %s\n", This
, piid
, debugstr_guid(&(This
->iid
)));
245 /************************************************************************
246 * ConnectionPointImpl_GetConnectionPointContainer (IConnectionPoint)
249 static HRESULT WINAPI
ConnectionPointImpl_GetConnectionPointContainer(
250 IConnectionPoint
*iface
,
251 IConnectionPointContainer
**ppCPC
)
253 ICOM_THIS(ConnectionPointImpl
, iface
);
254 TRACE("(%p)->(%p)\n", This
, ppCPC
);
256 return IUnknown_QueryInterface(This
->Obj
,
257 &IID_IConnectionPointContainer
,
261 /************************************************************************
262 * ConnectionPointImpl_Advise (IConnectionPoint)
265 static HRESULT WINAPI
ConnectionPointImpl_Advise(IConnectionPoint
*iface
,
270 ICOM_THIS(ConnectionPointImpl
, iface
);
272 TRACE("(%p)->(%p, %p)\n", This
, lpUnk
, pdwCookie
);
275 if(FAILED(IUnknown_QueryInterface(lpUnk
, &This
->iid
, (LPVOID
)&lpSink
)))
276 return CONNECT_E_CANNOTCONNECT
;
278 for(i
= 0; i
< This
->maxSinks
; i
++) {
279 if(This
->sinks
[i
] == NULL
)
282 if(i
== This
->maxSinks
) {
283 This
->maxSinks
+= MAXSINKS
;
284 This
->sinks
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->sinks
,
285 This
->maxSinks
* sizeof(IUnknown
*));
287 This
->sinks
[i
] = lpSink
;
294 /************************************************************************
295 * ConnectionPointImpl_Unadvise (IConnectionPoint)
298 static HRESULT WINAPI
ConnectionPointImpl_Unadvise(IConnectionPoint
*iface
,
301 ICOM_THIS(ConnectionPointImpl
, iface
);
302 TRACE("(%p)->(%ld)\n", This
, dwCookie
);
304 if(dwCookie
== 0 || dwCookie
> This
->maxSinks
) return E_INVALIDARG
;
306 if(This
->sinks
[dwCookie
-1] == NULL
) return CONNECT_E_NOCONNECTION
;
308 IUnknown_Release(This
->sinks
[dwCookie
-1]);
309 This
->sinks
[dwCookie
-1] = NULL
;
314 /************************************************************************
315 * ConnectionPointImpl_EnumConnections (IConnectionPoint)
318 static HRESULT WINAPI
ConnectionPointImpl_EnumConnections(
319 IConnectionPoint
*iface
,
320 LPENUMCONNECTIONS
*ppEnum
)
322 ICOM_THIS(ConnectionPointImpl
, iface
);
325 EnumConnectionsImpl
*EnumObj
;
328 TRACE("(%p)->(%p)\n", This
, ppEnum
);
332 if(This
->nSinks
== 0) return OLE_E_NOCONNECTION
;
334 pCD
= HeapAlloc(GetProcessHeap(), 0, sizeof(CONNECTDATA
) * This
->nSinks
);
336 for(i
= 0, nextslot
= 0; i
< This
->maxSinks
; i
++) {
337 if(This
->sinks
[i
] != NULL
) {
338 pCD
[nextslot
].pUnk
= This
->sinks
[i
];
339 pCD
[nextslot
].dwCookie
= i
+ 1;
343 assert(nextslot
== This
->nSinks
);
345 /* Bump the ref count of this object up by one. It gets Released in
346 IEnumConnections_Release */
347 IUnknown_AddRef((IUnknown
*)This
);
349 EnumObj
= EnumConnectionsImpl_Construct((IUnknown
*)This
, This
->nSinks
, pCD
);
350 hr
= IEnumConnections_QueryInterface((IEnumConnections
*)EnumObj
,
351 &IID_IEnumConnections
, (LPVOID
)ppEnum
);
352 IEnumConnections_Release((IEnumConnections
*)EnumObj
);
354 HeapFree(GetProcessHeap(), 0, pCD
);
358 static ICOM_VTABLE(IConnectionPoint
) ConnectionPointImpl_VTable
=
360 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
361 ConnectionPointImpl_QueryInterface
,
362 ConnectionPointImpl_AddRef
,
363 ConnectionPointImpl_Release
,
364 ConnectionPointImpl_GetConnectionInterface
,
365 ConnectionPointImpl_GetConnectionPointContainer
,
366 ConnectionPointImpl_Advise
,
367 ConnectionPointImpl_Unadvise
,
368 ConnectionPointImpl_EnumConnections
372 static ICOM_VTABLE(IEnumConnections
) EnumConnectionsImpl_VTable
;
373 static ULONG WINAPI
EnumConnectionsImpl_AddRef(IEnumConnections
* iface
);
375 /************************************************************************
376 * EnumConnectionsImpl_Construct
378 static EnumConnectionsImpl
*EnumConnectionsImpl_Construct(IUnknown
*pUnk
,
382 EnumConnectionsImpl
*Obj
= HeapAlloc(GetProcessHeap(), 0, sizeof(*Obj
));
385 Obj
->lpvtbl
= &EnumConnectionsImpl_VTable
;
388 Obj
->pCD
= HeapAlloc(GetProcessHeap(), 0, nSinks
* sizeof(CONNECTDATA
));
389 Obj
->nConns
= nSinks
;
392 for(i
= 0; i
< nSinks
; i
++) {
393 Obj
->pCD
[i
] = pCD
[i
];
394 IUnknown_AddRef(Obj
->pCD
[i
].pUnk
);
399 /************************************************************************
400 * EnumConnectionsImpl_Destroy
402 static void EnumConnectionsImpl_Destroy(EnumConnectionsImpl
*Obj
)
406 for(i
= 0; i
< Obj
->nConns
; i
++)
407 IUnknown_Release(Obj
->pCD
[i
].pUnk
);
409 HeapFree(GetProcessHeap(), 0, Obj
->pCD
);
410 HeapFree(GetProcessHeap(), 0, Obj
);
414 /************************************************************************
415 * EnumConnectionsImpl_QueryInterface (IUnknown)
417 * See Windows documentation for more details on IUnknown methods.
419 static HRESULT WINAPI
EnumConnectionsImpl_QueryInterface(
420 IEnumConnections
* iface
,
424 ICOM_THIS(ConnectionPointImpl
, iface
);
425 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
428 * Perform a sanity check on the parameters.
430 if ( (This
==0) || (ppvObject
==0) )
434 * Initialize the return parameter.
439 * Compare the riid with the interface IDs implemented by this object.
441 if (memcmp(&IID_IUnknown
, riid
, sizeof(IID_IUnknown
)) == 0)
443 *ppvObject
= (IEnumConnections
*)This
;
445 else if (memcmp(&IID_IEnumConnections
, riid
, sizeof(IID_IEnumConnections
)) == 0)
447 *ppvObject
= (IEnumConnections
*)This
;
451 * Check that we obtained an interface.
455 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid
));
456 return E_NOINTERFACE
;
460 * Query Interface always increases the reference count by one when it is
463 EnumConnectionsImpl_AddRef((IEnumConnections
*)This
);
469 /************************************************************************
470 * EnumConnectionsImpl_AddRef (IUnknown)
472 * See Windows documentation for more details on IUnknown methods.
474 static ULONG WINAPI
EnumConnectionsImpl_AddRef(IEnumConnections
* iface
)
476 ICOM_THIS(EnumConnectionsImpl
, iface
);
477 TRACE("(%p)->(ref=%ld)\n", This
, This
->ref
);
479 IUnknown_AddRef(This
->pUnk
);
483 /************************************************************************
484 * EnumConnectionsImpl_Release (IUnknown)
486 * See Windows documentation for more details on IUnknown methods.
488 static ULONG WINAPI
EnumConnectionsImpl_Release(IEnumConnections
* iface
)
490 ICOM_THIS(EnumConnectionsImpl
, iface
);
491 TRACE("(%p)->(ref=%ld)\n", This
, This
->ref
);
493 IUnknown_Release(This
->pUnk
);
496 * Decrease the reference count on this object.
501 * If the reference count goes down to 0, perform suicide.
505 EnumConnectionsImpl_Destroy(This
);
513 /************************************************************************
514 * EnumConnectionsImpl_Next (IEnumConnections)
517 static HRESULT WINAPI
EnumConnectionsImpl_Next(IEnumConnections
* iface
,
518 ULONG cConn
, LPCONNECTDATA pCD
,
521 ICOM_THIS(EnumConnectionsImpl
, iface
);
523 TRACE("(%p)->(%ld, %p, %p)\n", This
, cConn
, pCD
, pEnum
);
531 if(This
->nCur
>= This
->nConns
)
534 while(This
->nCur
< This
->nConns
&& cConn
) {
535 *pCD
++ = This
->pCD
[This
->nCur
];
536 IUnknown_AddRef(This
->pCD
[This
->nCur
].pUnk
);
549 /************************************************************************
550 * EnumConnectionsImpl_Skip (IEnumConnections)
553 static HRESULT WINAPI
EnumConnectionsImpl_Skip(IEnumConnections
* iface
,
556 ICOM_THIS(EnumConnectionsImpl
, iface
);
557 TRACE("(%p)->(%ld)\n", This
, cSkip
);
559 if(This
->nCur
+ cSkip
>= This
->nConns
)
568 /************************************************************************
569 * EnumConnectionsImpl_Reset (IEnumConnections)
572 static HRESULT WINAPI
EnumConnectionsImpl_Reset(IEnumConnections
* iface
)
574 ICOM_THIS(EnumConnectionsImpl
, iface
);
575 TRACE("(%p)\n", This
);
583 /************************************************************************
584 * EnumConnectionsImpl_Clone (IEnumConnections)
587 static HRESULT WINAPI
EnumConnectionsImpl_Clone(IEnumConnections
* iface
,
588 LPENUMCONNECTIONS
*ppEnum
)
590 ICOM_THIS(EnumConnectionsImpl
, iface
);
591 EnumConnectionsImpl
*newObj
;
592 TRACE("(%p)->(%p)\n", This
, ppEnum
);
594 newObj
= EnumConnectionsImpl_Construct(This
->pUnk
, This
->nConns
, This
->pCD
);
595 newObj
->nCur
= This
->nCur
;
596 *ppEnum
= (LPENUMCONNECTIONS
)newObj
;
597 IUnknown_AddRef(This
->pUnk
);
601 static ICOM_VTABLE(IEnumConnections
) EnumConnectionsImpl_VTable
=
603 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
604 EnumConnectionsImpl_QueryInterface
,
605 EnumConnectionsImpl_AddRef
,
606 EnumConnectionsImpl_Release
,
607 EnumConnectionsImpl_Next
,
608 EnumConnectionsImpl_Skip
,
609 EnumConnectionsImpl_Reset
,
610 EnumConnectionsImpl_Clone
613 /************************************************************************
615 * The exported function to create the connection point.
616 * NB not a windows API
619 * pUnk [in] IUnknown of object to which the ConnectionPoint is associated.
620 * Needed to access IConnectionPointContainer.
622 * riid [in] IID of sink interface that this ConnectionPoint manages
624 * pCP [out] returns IConnectionPoint
627 HRESULT
CreateConnectionPoint(IUnknown
*pUnk
, REFIID riid
,
628 IConnectionPoint
**pCP
)
630 ConnectionPointImpl
*Obj
;
633 Obj
= ConnectionPointImpl_Construct(pUnk
, riid
);
634 if(!Obj
) return E_OUTOFMEMORY
;
636 hr
= IConnectionPoint_QueryInterface((IConnectionPoint
*)Obj
,
637 &IID_IConnectionPoint
, (LPVOID
)pCP
);
638 IConnectionPoint_Release((IConnectionPoint
*)Obj
);