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 /************************************************************************
70 * Implementation of IEnumConnections
72 typedef struct EnumConnectionsImpl
{
74 IEnumConnections IEnumConnections_iface
;
78 /* IUnknown of ConnectionPoint, used for ref counting */
85 /* Next connection to enumerate from */
88 } EnumConnectionsImpl
;
90 static EnumConnectionsImpl
*EnumConnectionsImpl_Construct(IUnknown
*pUnk
,
94 static inline ConnectionPointImpl
*impl_from_IConnectionPoint(IConnectionPoint
*iface
)
96 return CONTAINING_RECORD(iface
, ConnectionPointImpl
, IConnectionPoint_iface
);
99 static inline EnumConnectionsImpl
*impl_from_IEnumConnections(IEnumConnections
*iface
)
101 return CONTAINING_RECORD(iface
, EnumConnectionsImpl
, IEnumConnections_iface
);
104 /************************************************************************
105 * ConnectionPointImpl_Destroy
107 static void ConnectionPointImpl_Destroy(ConnectionPointImpl
*Obj
)
110 for(i
= 0; i
< Obj
->maxSinks
; i
++) {
112 IUnknown_Release(Obj
->sinks
[i
]);
113 Obj
->sinks
[i
] = NULL
;
116 HeapFree(GetProcessHeap(), 0, Obj
->sinks
);
117 HeapFree(GetProcessHeap(), 0, Obj
);
121 /************************************************************************
122 * ConnectionPointImpl_QueryInterface (IUnknown)
124 * See Windows documentation for more details on IUnknown methods.
126 static HRESULT WINAPI
ConnectionPointImpl_QueryInterface(
127 IConnectionPoint
* iface
,
131 ConnectionPointImpl
*This
= impl_from_IConnectionPoint(iface
);
132 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
135 * Perform a sanity check on the parameters.
141 * Initialize the return parameter.
146 if (IsEqualIID(&IID_IConnectionPoint
, riid
) || IsEqualIID(&IID_IUnknown
, riid
))
150 * Check that we obtained an interface.
154 FIXME("() : asking for unsupported interface %s\n", debugstr_guid(riid
));
155 return E_NOINTERFACE
;
158 IUnknown_AddRef((IUnknown
*)*ppvObject
);
164 /************************************************************************
165 * ConnectionPointImpl_AddRef (IUnknown)
167 * See Windows documentation for more details on IUnknown methods.
169 static ULONG WINAPI
ConnectionPointImpl_AddRef(IConnectionPoint
* iface
)
171 ConnectionPointImpl
*This
= impl_from_IConnectionPoint(iface
);
172 ULONG refCount
= InterlockedIncrement(&This
->ref
);
174 TRACE("(%p)->(ref before=%d)\n", This
, refCount
- 1);
179 /************************************************************************
180 * ConnectionPointImpl_Release (IUnknown)
182 * See Windows documentation for more details on IUnknown methods.
184 static ULONG WINAPI
ConnectionPointImpl_Release(
185 IConnectionPoint
* iface
)
187 ConnectionPointImpl
*This
= impl_from_IConnectionPoint(iface
);
188 ULONG refCount
= InterlockedDecrement(&This
->ref
);
190 TRACE("(%p)->(ref before=%d)\n", This
, refCount
+ 1);
193 * If the reference count goes down to 0, perform suicide.
195 if (!refCount
) ConnectionPointImpl_Destroy(This
);
200 /************************************************************************
201 * ConnectionPointImpl_GetConnectionInterface (IConnectionPoint)
204 static HRESULT WINAPI
ConnectionPointImpl_GetConnectionInterface(
205 IConnectionPoint
*iface
,
208 ConnectionPointImpl
*This
= impl_from_IConnectionPoint(iface
);
209 TRACE("(%p)->(%p) returning %s\n", This
, piid
, debugstr_guid(&(This
->iid
)));
214 /************************************************************************
215 * ConnectionPointImpl_GetConnectionPointContainer (IConnectionPoint)
218 static HRESULT WINAPI
ConnectionPointImpl_GetConnectionPointContainer(
219 IConnectionPoint
*iface
,
220 IConnectionPointContainer
**ppCPC
)
222 ConnectionPointImpl
*This
= impl_from_IConnectionPoint(iface
);
223 TRACE("(%p)->(%p)\n", This
, ppCPC
);
225 return IUnknown_QueryInterface(This
->Obj
, &IID_IConnectionPointContainer
, (void**)ppCPC
);
228 /************************************************************************
229 * ConnectionPointImpl_Advise (IConnectionPoint)
232 static HRESULT WINAPI
ConnectionPointImpl_Advise(IConnectionPoint
*iface
,
237 ConnectionPointImpl
*This
= impl_from_IConnectionPoint(iface
);
239 TRACE("(%p)->(%p, %p)\n", This
, lpUnk
, pdwCookie
);
242 if(FAILED(IUnknown_QueryInterface(lpUnk
, &This
->iid
, (void**)&lpSink
)))
243 return CONNECT_E_CANNOTCONNECT
;
245 for(i
= 0; i
< This
->maxSinks
; i
++) {
246 if(This
->sinks
[i
] == NULL
)
249 if(i
== This
->maxSinks
) {
250 This
->maxSinks
+= MAXSINKS
;
251 This
->sinks
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->sinks
,
252 This
->maxSinks
* sizeof(IUnknown
*));
254 This
->sinks
[i
] = lpSink
;
261 /************************************************************************
262 * ConnectionPointImpl_Unadvise (IConnectionPoint)
265 static HRESULT WINAPI
ConnectionPointImpl_Unadvise(IConnectionPoint
*iface
,
268 ConnectionPointImpl
*This
= impl_from_IConnectionPoint(iface
);
269 TRACE("(%p)->(%d)\n", This
, dwCookie
);
271 if(dwCookie
== 0 || dwCookie
> This
->maxSinks
) return E_INVALIDARG
;
273 if(This
->sinks
[dwCookie
-1] == NULL
) return CONNECT_E_NOCONNECTION
;
275 IUnknown_Release(This
->sinks
[dwCookie
-1]);
276 This
->sinks
[dwCookie
-1] = NULL
;
281 /************************************************************************
282 * ConnectionPointImpl_EnumConnections (IConnectionPoint)
285 static HRESULT WINAPI
ConnectionPointImpl_EnumConnections(
286 IConnectionPoint
*iface
,
287 LPENUMCONNECTIONS
*ppEnum
)
289 ConnectionPointImpl
*This
= impl_from_IConnectionPoint(iface
);
292 EnumConnectionsImpl
*EnumObj
;
295 TRACE("(%p)->(%p)\n", This
, ppEnum
);
299 if(This
->nSinks
== 0) return OLE_E_NOCONNECTION
;
301 pCD
= HeapAlloc(GetProcessHeap(), 0, sizeof(CONNECTDATA
) * This
->nSinks
);
303 for(i
= 0, nextslot
= 0; i
< This
->maxSinks
; i
++) {
304 if(This
->sinks
[i
] != NULL
) {
305 pCD
[nextslot
].pUnk
= This
->sinks
[i
];
306 pCD
[nextslot
].dwCookie
= i
+ 1;
310 assert(nextslot
== This
->nSinks
);
312 /* Bump the ref count of this object up by one. It gets Released in
313 IEnumConnections_Release */
314 IConnectionPoint_AddRef(iface
);
316 EnumObj
= EnumConnectionsImpl_Construct((IUnknown
*)iface
, This
->nSinks
, pCD
);
317 hr
= IEnumConnections_QueryInterface(&EnumObj
->IEnumConnections_iface
,
318 &IID_IEnumConnections
, (void**)ppEnum
);
319 IEnumConnections_Release(&EnumObj
->IEnumConnections_iface
);
321 HeapFree(GetProcessHeap(), 0, pCD
);
325 static const IConnectionPointVtbl ConnectionPointImpl_VTable
=
327 ConnectionPointImpl_QueryInterface
,
328 ConnectionPointImpl_AddRef
,
329 ConnectionPointImpl_Release
,
330 ConnectionPointImpl_GetConnectionInterface
,
331 ConnectionPointImpl_GetConnectionPointContainer
,
332 ConnectionPointImpl_Advise
,
333 ConnectionPointImpl_Unadvise
,
334 ConnectionPointImpl_EnumConnections
338 static const IEnumConnectionsVtbl EnumConnectionsImpl_VTable
;
340 /************************************************************************
341 * EnumConnectionsImpl_Construct
343 static EnumConnectionsImpl
*EnumConnectionsImpl_Construct(IUnknown
*pUnk
,
347 EnumConnectionsImpl
*Obj
= HeapAlloc(GetProcessHeap(), 0, sizeof(*Obj
));
350 Obj
->IEnumConnections_iface
.lpVtbl
= &EnumConnectionsImpl_VTable
;
353 Obj
->pCD
= HeapAlloc(GetProcessHeap(), 0, nSinks
* sizeof(CONNECTDATA
));
354 Obj
->nConns
= nSinks
;
357 for(i
= 0; i
< nSinks
; i
++) {
358 Obj
->pCD
[i
] = pCD
[i
];
359 IUnknown_AddRef(Obj
->pCD
[i
].pUnk
);
364 /************************************************************************
365 * EnumConnectionsImpl_Destroy
367 static void EnumConnectionsImpl_Destroy(EnumConnectionsImpl
*Obj
)
371 for(i
= 0; i
< Obj
->nConns
; i
++)
372 IUnknown_Release(Obj
->pCD
[i
].pUnk
);
374 HeapFree(GetProcessHeap(), 0, Obj
->pCD
);
375 HeapFree(GetProcessHeap(), 0, Obj
);
379 /************************************************************************
380 * EnumConnectionsImpl_QueryInterface (IUnknown)
382 * See Windows documentation for more details on IUnknown methods.
384 static HRESULT WINAPI
EnumConnectionsImpl_QueryInterface(
385 IEnumConnections
* iface
,
389 ConnectionPointImpl
*This
= (ConnectionPointImpl
*)iface
;
390 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
393 * Perform a sanity check on the parameters.
399 * Initialize the return parameter.
403 if (IsEqualIID(&IID_IEnumConnections
, riid
) || IsEqualIID(&IID_IUnknown
, riid
))
407 * Check that we obtained an interface.
411 FIXME("() : asking for unsupported interface %s\n", debugstr_guid(riid
));
412 return E_NOINTERFACE
;
415 IUnknown_AddRef((IUnknown
*)*ppvObject
);
421 /************************************************************************
422 * EnumConnectionsImpl_AddRef (IUnknown)
424 * See Windows documentation for more details on IUnknown methods.
426 static ULONG WINAPI
EnumConnectionsImpl_AddRef(IEnumConnections
* iface
)
428 EnumConnectionsImpl
*This
= impl_from_IEnumConnections(iface
);
429 ULONG refCount
= InterlockedIncrement(&This
->ref
);
431 TRACE("(%p)->(ref before=%d)\n", This
, refCount
- 1);
433 IUnknown_AddRef(This
->pUnk
);
437 /************************************************************************
438 * EnumConnectionsImpl_Release (IUnknown)
440 * See Windows documentation for more details on IUnknown methods.
442 static ULONG WINAPI
EnumConnectionsImpl_Release(IEnumConnections
* iface
)
444 EnumConnectionsImpl
*This
= impl_from_IEnumConnections(iface
);
445 ULONG refCount
= InterlockedDecrement(&This
->ref
);
447 TRACE("(%p)->(ref before=%d)\n", This
, refCount
+ 1);
449 IUnknown_Release(This
->pUnk
);
452 * If the reference count goes down to 0, perform suicide.
454 if (!refCount
) EnumConnectionsImpl_Destroy(This
);
459 /************************************************************************
460 * EnumConnectionsImpl_Next (IEnumConnections)
463 static HRESULT WINAPI
EnumConnectionsImpl_Next(IEnumConnections
* iface
,
464 ULONG cConn
, LPCONNECTDATA pCD
,
467 EnumConnectionsImpl
*This
= impl_from_IEnumConnections(iface
);
469 TRACE("(%p)->(%d, %p, %p)\n", This
, cConn
, pCD
, pEnum
);
477 if(This
->nCur
>= This
->nConns
)
480 while(This
->nCur
< This
->nConns
&& cConn
) {
481 *pCD
++ = This
->pCD
[This
->nCur
];
482 IUnknown_AddRef(This
->pCD
[This
->nCur
].pUnk
);
495 /************************************************************************
496 * EnumConnectionsImpl_Skip (IEnumConnections)
499 static HRESULT WINAPI
EnumConnectionsImpl_Skip(IEnumConnections
* iface
,
502 EnumConnectionsImpl
*This
= impl_from_IEnumConnections(iface
);
503 TRACE("(%p)->(%d)\n", This
, cSkip
);
505 if(This
->nCur
+ cSkip
>= This
->nConns
)
514 /************************************************************************
515 * EnumConnectionsImpl_Reset (IEnumConnections)
518 static HRESULT WINAPI
EnumConnectionsImpl_Reset(IEnumConnections
* iface
)
520 EnumConnectionsImpl
*This
= impl_from_IEnumConnections(iface
);
521 TRACE("(%p)\n", This
);
529 /************************************************************************
530 * EnumConnectionsImpl_Clone (IEnumConnections)
533 static HRESULT WINAPI
EnumConnectionsImpl_Clone(IEnumConnections
* iface
,
534 LPENUMCONNECTIONS
*ppEnum
)
536 EnumConnectionsImpl
*This
= impl_from_IEnumConnections(iface
);
537 EnumConnectionsImpl
*newObj
;
538 TRACE("(%p)->(%p)\n", This
, ppEnum
);
540 newObj
= EnumConnectionsImpl_Construct(This
->pUnk
, This
->nConns
, This
->pCD
);
541 newObj
->nCur
= This
->nCur
;
542 *ppEnum
= &newObj
->IEnumConnections_iface
;
543 IUnknown_AddRef(This
->pUnk
);
547 static const IEnumConnectionsVtbl EnumConnectionsImpl_VTable
=
549 EnumConnectionsImpl_QueryInterface
,
550 EnumConnectionsImpl_AddRef
,
551 EnumConnectionsImpl_Release
,
552 EnumConnectionsImpl_Next
,
553 EnumConnectionsImpl_Skip
,
554 EnumConnectionsImpl_Reset
,
555 EnumConnectionsImpl_Clone
558 /************************************************************************
560 * The exported function to create the connection point.
561 * NB not a windows API
564 * pUnk [in] IUnknown of object to which the ConnectionPoint is associated.
565 * Needed to access IConnectionPointContainer.
567 * riid [in] IID of sink interface that this ConnectionPoint manages
569 * pCP [out] returns IConnectionPoint
572 HRESULT
CreateConnectionPoint(IUnknown
*pUnk
, REFIID riid
,
573 IConnectionPoint
**pCP
)
575 ConnectionPointImpl
*Obj
;
577 TRACE("(%p %s %p)\n", pUnk
, debugstr_guid(riid
), pCP
);
580 Obj
= HeapAlloc(GetProcessHeap(), 0, sizeof(*Obj
));
582 return E_OUTOFMEMORY
;
584 Obj
->IConnectionPoint_iface
.lpVtbl
= &ConnectionPointImpl_VTable
;
588 Obj
->maxSinks
= MAXSINKS
;
589 Obj
->sinks
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IUnknown
*) * MAXSINKS
);
592 *pCP
= &Obj
->IConnectionPoint_iface
;