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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 * See one exported function here is CreateConnectionPoint, see
22 * comments just above that function for information.
40 #include "wine/debug.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
46 /************************************************************************
47 * Implementation of IConnectionPoint
49 typedef struct ConnectionPointImpl
{
51 IConnectionPoint IConnectionPoint_iface
;
53 /* IUnknown of our main object*/
59 /* IID of sink interface */
62 /* Array of sink IUnknowns */
67 } ConnectionPointImpl
;
69 static const IConnectionPointVtbl ConnectionPointImpl_VTable
;
72 /************************************************************************
73 * Implementation of IEnumConnections
75 typedef struct EnumConnectionsImpl
{
77 IEnumConnections IEnumConnections_iface
;
81 /* IUnknown of ConnectionPoint, used for ref counting */
88 /* Next connection to enumerate from */
91 } EnumConnectionsImpl
;
93 static EnumConnectionsImpl
*EnumConnectionsImpl_Construct(IUnknown
*pUnk
,
97 static inline ConnectionPointImpl
*impl_from_IConnectionPoint(IConnectionPoint
*iface
)
99 return CONTAINING_RECORD(iface
, ConnectionPointImpl
, IConnectionPoint_iface
);
102 static inline EnumConnectionsImpl
*impl_from_IEnumConnections(IEnumConnections
*iface
)
104 return CONTAINING_RECORD(iface
, EnumConnectionsImpl
, IEnumConnections_iface
);
107 /************************************************************************
108 * ConnectionPointImpl_Construct
110 static ConnectionPointImpl
*ConnectionPointImpl_Construct(IUnknown
*pUnk
,
113 ConnectionPointImpl
*Obj
;
115 Obj
= HeapAlloc(GetProcessHeap(), 0, sizeof(*Obj
));
116 Obj
->IConnectionPoint_iface
.lpVtbl
= &ConnectionPointImpl_VTable
;
120 Obj
->maxSinks
= MAXSINKS
;
121 Obj
->sinks
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
122 sizeof(IUnknown
*) * MAXSINKS
);
127 /************************************************************************
128 * ConnectionPointImpl_Destroy
130 static void ConnectionPointImpl_Destroy(ConnectionPointImpl
*Obj
)
133 for(i
= 0; i
< Obj
->maxSinks
; i
++) {
135 IUnknown_Release(Obj
->sinks
[i
]);
136 Obj
->sinks
[i
] = NULL
;
139 HeapFree(GetProcessHeap(), 0, Obj
->sinks
);
140 HeapFree(GetProcessHeap(), 0, Obj
);
144 static ULONG WINAPI
ConnectionPointImpl_AddRef(IConnectionPoint
* iface
);
145 /************************************************************************
146 * ConnectionPointImpl_QueryInterface (IUnknown)
148 * See Windows documentation for more details on IUnknown methods.
150 static HRESULT WINAPI
ConnectionPointImpl_QueryInterface(
151 IConnectionPoint
* iface
,
155 ConnectionPointImpl
*This
= impl_from_IConnectionPoint(iface
);
156 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
159 * Perform a sanity check on the parameters.
161 if ( (This
==0) || (ppvObject
==0) )
165 * Initialize the return parameter.
170 * Compare the riid with the interface IDs implemented by this object.
172 if (IsEqualIID(&IID_IUnknown
, riid
))
174 else if (IsEqualIID(&IID_IConnectionPoint
, riid
))
178 * Check that we obtained an interface.
182 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid
));
183 return E_NOINTERFACE
;
187 * Query Interface always increases the reference count by one when it is
190 ConnectionPointImpl_AddRef(&This
->IConnectionPoint_iface
);
196 /************************************************************************
197 * ConnectionPointImpl_AddRef (IUnknown)
199 * See Windows documentation for more details on IUnknown methods.
201 static ULONG WINAPI
ConnectionPointImpl_AddRef(IConnectionPoint
* iface
)
203 ConnectionPointImpl
*This
= impl_from_IConnectionPoint(iface
);
204 ULONG refCount
= InterlockedIncrement(&This
->ref
);
206 TRACE("(%p)->(ref before=%d)\n", This
, refCount
- 1);
211 /************************************************************************
212 * ConnectionPointImpl_Release (IUnknown)
214 * See Windows documentation for more details on IUnknown methods.
216 static ULONG WINAPI
ConnectionPointImpl_Release(
217 IConnectionPoint
* iface
)
219 ConnectionPointImpl
*This
= impl_from_IConnectionPoint(iface
);
220 ULONG refCount
= InterlockedDecrement(&This
->ref
);
222 TRACE("(%p)->(ref before=%d)\n", This
, refCount
+ 1);
225 * If the reference count goes down to 0, perform suicide.
227 if (!refCount
) ConnectionPointImpl_Destroy(This
);
232 /************************************************************************
233 * ConnectionPointImpl_GetConnectionInterface (IConnectionPoint)
236 static HRESULT WINAPI
ConnectionPointImpl_GetConnectionInterface(
237 IConnectionPoint
*iface
,
240 ConnectionPointImpl
*This
= impl_from_IConnectionPoint(iface
);
241 TRACE("(%p)->(%p) returning %s\n", This
, piid
, debugstr_guid(&(This
->iid
)));
246 /************************************************************************
247 * ConnectionPointImpl_GetConnectionPointContainer (IConnectionPoint)
250 static HRESULT WINAPI
ConnectionPointImpl_GetConnectionPointContainer(
251 IConnectionPoint
*iface
,
252 IConnectionPointContainer
**ppCPC
)
254 ConnectionPointImpl
*This
= impl_from_IConnectionPoint(iface
);
255 TRACE("(%p)->(%p)\n", This
, ppCPC
);
257 return IUnknown_QueryInterface(This
->Obj
, &IID_IConnectionPointContainer
, (void**)ppCPC
);
260 /************************************************************************
261 * ConnectionPointImpl_Advise (IConnectionPoint)
264 static HRESULT WINAPI
ConnectionPointImpl_Advise(IConnectionPoint
*iface
,
269 ConnectionPointImpl
*This
= impl_from_IConnectionPoint(iface
);
271 TRACE("(%p)->(%p, %p)\n", This
, lpUnk
, pdwCookie
);
274 if(FAILED(IUnknown_QueryInterface(lpUnk
, &This
->iid
, (void**)&lpSink
)))
275 return CONNECT_E_CANNOTCONNECT
;
277 for(i
= 0; i
< This
->maxSinks
; i
++) {
278 if(This
->sinks
[i
] == NULL
)
281 if(i
== This
->maxSinks
) {
282 This
->maxSinks
+= MAXSINKS
;
283 This
->sinks
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->sinks
,
284 This
->maxSinks
* sizeof(IUnknown
*));
286 This
->sinks
[i
] = lpSink
;
293 /************************************************************************
294 * ConnectionPointImpl_Unadvise (IConnectionPoint)
297 static HRESULT WINAPI
ConnectionPointImpl_Unadvise(IConnectionPoint
*iface
,
300 ConnectionPointImpl
*This
= impl_from_IConnectionPoint(iface
);
301 TRACE("(%p)->(%d)\n", This
, dwCookie
);
303 if(dwCookie
== 0 || dwCookie
> This
->maxSinks
) return E_INVALIDARG
;
305 if(This
->sinks
[dwCookie
-1] == NULL
) return CONNECT_E_NOCONNECTION
;
307 IUnknown_Release(This
->sinks
[dwCookie
-1]);
308 This
->sinks
[dwCookie
-1] = NULL
;
313 /************************************************************************
314 * ConnectionPointImpl_EnumConnections (IConnectionPoint)
317 static HRESULT WINAPI
ConnectionPointImpl_EnumConnections(
318 IConnectionPoint
*iface
,
319 LPENUMCONNECTIONS
*ppEnum
)
321 ConnectionPointImpl
*This
= impl_from_IConnectionPoint(iface
);
324 EnumConnectionsImpl
*EnumObj
;
327 TRACE("(%p)->(%p)\n", This
, ppEnum
);
331 if(This
->nSinks
== 0) return OLE_E_NOCONNECTION
;
333 pCD
= HeapAlloc(GetProcessHeap(), 0, sizeof(CONNECTDATA
) * This
->nSinks
);
335 for(i
= 0, nextslot
= 0; i
< This
->maxSinks
; i
++) {
336 if(This
->sinks
[i
] != NULL
) {
337 pCD
[nextslot
].pUnk
= This
->sinks
[i
];
338 pCD
[nextslot
].dwCookie
= i
+ 1;
342 assert(nextslot
== This
->nSinks
);
344 /* Bump the ref count of this object up by one. It gets Released in
345 IEnumConnections_Release */
346 IUnknown_AddRef((IUnknown
*)This
);
348 EnumObj
= EnumConnectionsImpl_Construct((IUnknown
*)This
, This
->nSinks
, pCD
);
349 hr
= IEnumConnections_QueryInterface(&EnumObj
->IEnumConnections_iface
,
350 &IID_IEnumConnections
, (void**)ppEnum
);
351 IEnumConnections_Release(&EnumObj
->IEnumConnections_iface
);
353 HeapFree(GetProcessHeap(), 0, pCD
);
357 static const IConnectionPointVtbl ConnectionPointImpl_VTable
=
359 ConnectionPointImpl_QueryInterface
,
360 ConnectionPointImpl_AddRef
,
361 ConnectionPointImpl_Release
,
362 ConnectionPointImpl_GetConnectionInterface
,
363 ConnectionPointImpl_GetConnectionPointContainer
,
364 ConnectionPointImpl_Advise
,
365 ConnectionPointImpl_Unadvise
,
366 ConnectionPointImpl_EnumConnections
370 static const IEnumConnectionsVtbl EnumConnectionsImpl_VTable
;
371 static ULONG WINAPI
EnumConnectionsImpl_AddRef(IEnumConnections
* iface
);
373 /************************************************************************
374 * EnumConnectionsImpl_Construct
376 static EnumConnectionsImpl
*EnumConnectionsImpl_Construct(IUnknown
*pUnk
,
380 EnumConnectionsImpl
*Obj
= HeapAlloc(GetProcessHeap(), 0, sizeof(*Obj
));
383 Obj
->IEnumConnections_iface
.lpVtbl
= &EnumConnectionsImpl_VTable
;
386 Obj
->pCD
= HeapAlloc(GetProcessHeap(), 0, nSinks
* sizeof(CONNECTDATA
));
387 Obj
->nConns
= nSinks
;
390 for(i
= 0; i
< nSinks
; i
++) {
391 Obj
->pCD
[i
] = pCD
[i
];
392 IUnknown_AddRef(Obj
->pCD
[i
].pUnk
);
397 /************************************************************************
398 * EnumConnectionsImpl_Destroy
400 static void EnumConnectionsImpl_Destroy(EnumConnectionsImpl
*Obj
)
404 for(i
= 0; i
< Obj
->nConns
; i
++)
405 IUnknown_Release(Obj
->pCD
[i
].pUnk
);
407 HeapFree(GetProcessHeap(), 0, Obj
->pCD
);
408 HeapFree(GetProcessHeap(), 0, Obj
);
412 /************************************************************************
413 * EnumConnectionsImpl_QueryInterface (IUnknown)
415 * See Windows documentation for more details on IUnknown methods.
417 static HRESULT WINAPI
EnumConnectionsImpl_QueryInterface(
418 IEnumConnections
* iface
,
422 ConnectionPointImpl
*This
= (ConnectionPointImpl
*)iface
;
423 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
426 * Perform a sanity check on the parameters.
428 if ( (This
==0) || (ppvObject
==0) )
432 * Initialize the return parameter.
437 * Compare the riid with the interface IDs implemented by this object.
439 if (IsEqualIID(&IID_IUnknown
, riid
))
441 else if (IsEqualIID(&IID_IEnumConnections
, riid
))
445 * Check that we obtained an interface.
449 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid
));
450 return E_NOINTERFACE
;
454 * Query Interface always increases the reference count by one when it is
457 EnumConnectionsImpl_AddRef((IEnumConnections
*)This
);
463 /************************************************************************
464 * EnumConnectionsImpl_AddRef (IUnknown)
466 * See Windows documentation for more details on IUnknown methods.
468 static ULONG WINAPI
EnumConnectionsImpl_AddRef(IEnumConnections
* iface
)
470 EnumConnectionsImpl
*This
= impl_from_IEnumConnections(iface
);
471 ULONG refCount
= InterlockedIncrement(&This
->ref
);
473 TRACE("(%p)->(ref before=%d)\n", This
, refCount
- 1);
475 IUnknown_AddRef(This
->pUnk
);
479 /************************************************************************
480 * EnumConnectionsImpl_Release (IUnknown)
482 * See Windows documentation for more details on IUnknown methods.
484 static ULONG WINAPI
EnumConnectionsImpl_Release(IEnumConnections
* iface
)
486 EnumConnectionsImpl
*This
= impl_from_IEnumConnections(iface
);
487 ULONG refCount
= InterlockedDecrement(&This
->ref
);
489 TRACE("(%p)->(ref before=%d)\n", This
, refCount
+ 1);
491 IUnknown_Release(This
->pUnk
);
494 * If the reference count goes down to 0, perform suicide.
496 if (!refCount
) EnumConnectionsImpl_Destroy(This
);
501 /************************************************************************
502 * EnumConnectionsImpl_Next (IEnumConnections)
505 static HRESULT WINAPI
EnumConnectionsImpl_Next(IEnumConnections
* iface
,
506 ULONG cConn
, LPCONNECTDATA pCD
,
509 EnumConnectionsImpl
*This
= impl_from_IEnumConnections(iface
);
511 TRACE("(%p)->(%d, %p, %p)\n", This
, cConn
, pCD
, pEnum
);
519 if(This
->nCur
>= This
->nConns
)
522 while(This
->nCur
< This
->nConns
&& cConn
) {
523 *pCD
++ = This
->pCD
[This
->nCur
];
524 IUnknown_AddRef(This
->pCD
[This
->nCur
].pUnk
);
537 /************************************************************************
538 * EnumConnectionsImpl_Skip (IEnumConnections)
541 static HRESULT WINAPI
EnumConnectionsImpl_Skip(IEnumConnections
* iface
,
544 EnumConnectionsImpl
*This
= impl_from_IEnumConnections(iface
);
545 TRACE("(%p)->(%d)\n", This
, cSkip
);
547 if(This
->nCur
+ cSkip
>= This
->nConns
)
556 /************************************************************************
557 * EnumConnectionsImpl_Reset (IEnumConnections)
560 static HRESULT WINAPI
EnumConnectionsImpl_Reset(IEnumConnections
* iface
)
562 EnumConnectionsImpl
*This
= impl_from_IEnumConnections(iface
);
563 TRACE("(%p)\n", This
);
571 /************************************************************************
572 * EnumConnectionsImpl_Clone (IEnumConnections)
575 static HRESULT WINAPI
EnumConnectionsImpl_Clone(IEnumConnections
* iface
,
576 LPENUMCONNECTIONS
*ppEnum
)
578 EnumConnectionsImpl
*This
= impl_from_IEnumConnections(iface
);
579 EnumConnectionsImpl
*newObj
;
580 TRACE("(%p)->(%p)\n", This
, ppEnum
);
582 newObj
= EnumConnectionsImpl_Construct(This
->pUnk
, This
->nConns
, This
->pCD
);
583 newObj
->nCur
= This
->nCur
;
584 *ppEnum
= (LPENUMCONNECTIONS
)newObj
;
585 IUnknown_AddRef(This
->pUnk
);
589 static const IEnumConnectionsVtbl EnumConnectionsImpl_VTable
=
591 EnumConnectionsImpl_QueryInterface
,
592 EnumConnectionsImpl_AddRef
,
593 EnumConnectionsImpl_Release
,
594 EnumConnectionsImpl_Next
,
595 EnumConnectionsImpl_Skip
,
596 EnumConnectionsImpl_Reset
,
597 EnumConnectionsImpl_Clone
600 /************************************************************************
602 * The exported function to create the connection point.
603 * NB not a windows API
606 * pUnk [in] IUnknown of object to which the ConnectionPoint is associated.
607 * Needed to access IConnectionPointContainer.
609 * riid [in] IID of sink interface that this ConnectionPoint manages
611 * pCP [out] returns IConnectionPoint
614 HRESULT
CreateConnectionPoint(IUnknown
*pUnk
, REFIID riid
,
615 IConnectionPoint
**pCP
)
617 ConnectionPointImpl
*Obj
;
620 Obj
= ConnectionPointImpl_Construct(pUnk
, riid
);
621 if(!Obj
) return E_OUTOFMEMORY
;
623 hr
= IConnectionPoint_QueryInterface(&Obj
->IConnectionPoint_iface
,
624 &IID_IConnectionPoint
, (void**)pCP
);
625 IConnectionPoint_Release(&Obj
->IConnectionPoint_iface
);