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.
40 #include "wine/debug.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
46 /************************************************************************
47 * Implementation of IConnectionPoint
49 typedef struct ConnectionPointImpl
{
51 IConnectionPointVtbl
*lpvtbl
;
53 /* IUnknown of our main object*/
59 /* IID of sink interface */
62 /* Array of sink IUnknowns */
67 } ConnectionPointImpl
;
69 static IConnectionPointVtbl ConnectionPointImpl_VTable
;
72 /************************************************************************
73 * Implementation of IEnumConnections
75 typedef struct EnumConnectionsImpl
{
77 IEnumConnectionsVtbl
*lpvtbl
;
81 /* IUnknown of ConnectionPoint, used for ref counting */
88 /* Next connection to enumerate from */
91 } EnumConnectionsImpl
;
93 static EnumConnectionsImpl
*EnumConnectionsImpl_Construct(IUnknown
*pUnk
,
98 /************************************************************************
99 * ConnectionPointImpl_Construct
101 static ConnectionPointImpl
*ConnectionPointImpl_Construct(IUnknown
*pUnk
,
104 ConnectionPointImpl
*Obj
;
106 Obj
= HeapAlloc(GetProcessHeap(), 0, sizeof(*Obj
));
107 Obj
->lpvtbl
= &ConnectionPointImpl_VTable
;
111 Obj
->maxSinks
= MAXSINKS
;
112 Obj
->sinks
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
113 sizeof(IUnknown
*) * MAXSINKS
);
118 /************************************************************************
119 * ConnectionPointImpl_Destroy
121 static void ConnectionPointImpl_Destroy(ConnectionPointImpl
*Obj
)
124 for(i
= 0; i
< Obj
->maxSinks
; i
++) {
126 IUnknown_Release(Obj
->sinks
[i
]);
127 Obj
->sinks
[i
] = NULL
;
130 HeapFree(GetProcessHeap(), 0, Obj
->sinks
);
131 HeapFree(GetProcessHeap(), 0, Obj
);
135 static ULONG WINAPI
ConnectionPointImpl_AddRef(IConnectionPoint
* iface
);
136 /************************************************************************
137 * ConnectionPointImpl_QueryInterface (IUnknown)
139 * See Windows documentation for more details on IUnknown methods.
141 static HRESULT WINAPI
ConnectionPointImpl_QueryInterface(
142 IConnectionPoint
* iface
,
146 ConnectionPointImpl
*This
= (ConnectionPointImpl
*)iface
;
147 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
150 * Perform a sanity check on the parameters.
152 if ( (This
==0) || (ppvObject
==0) )
156 * Initialize the return parameter.
161 * Compare the riid with the interface IDs implemented by this object.
163 if (memcmp(&IID_IUnknown
, riid
, sizeof(IID_IUnknown
)) == 0)
165 *ppvObject
= (IConnectionPoint
*)This
;
167 else if (memcmp(&IID_IConnectionPoint
, riid
, sizeof(IID_IConnectionPoint
)) == 0)
169 *ppvObject
= (IConnectionPoint
*)This
;
173 * Check that we obtained an interface.
177 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid
));
178 return E_NOINTERFACE
;
182 * Query Interface always increases the reference count by one when it is
185 ConnectionPointImpl_AddRef((IConnectionPoint
*)This
);
191 /************************************************************************
192 * ConnectionPointImpl_AddRef (IUnknown)
194 * See Windows documentation for more details on IUnknown methods.
196 static ULONG WINAPI
ConnectionPointImpl_AddRef(IConnectionPoint
* iface
)
198 ConnectionPointImpl
*This
= (ConnectionPointImpl
*)iface
;
199 TRACE("(%p)->(ref=%ld)\n", This
, This
->ref
);
200 return InterlockedIncrement(&This
->ref
);
203 /************************************************************************
204 * ConnectionPointImpl_Release (IUnknown)
206 * See Windows documentation for more details on IUnknown methods.
208 static ULONG WINAPI
ConnectionPointImpl_Release(
209 IConnectionPoint
* iface
)
211 ConnectionPointImpl
*This
= (ConnectionPointImpl
*)iface
;
213 TRACE("(%p)->(ref=%ld)\n", This
, This
->ref
);
216 * Decrease the reference count on this object.
218 ref
= InterlockedDecrement(&This
->ref
);
221 * If the reference count goes down to 0, perform suicide.
223 if (ref
== 0) ConnectionPointImpl_Destroy(This
);
228 /************************************************************************
229 * ConnectionPointImpl_GetConnectionInterface (IConnectionPoint)
232 static HRESULT WINAPI
ConnectionPointImpl_GetConnectionInterface(
233 IConnectionPoint
*iface
,
236 ConnectionPointImpl
*This
= (ConnectionPointImpl
*)iface
;
237 TRACE("(%p)->(%p) returning %s\n", This
, piid
, debugstr_guid(&(This
->iid
)));
242 /************************************************************************
243 * ConnectionPointImpl_GetConnectionPointContainer (IConnectionPoint)
246 static HRESULT WINAPI
ConnectionPointImpl_GetConnectionPointContainer(
247 IConnectionPoint
*iface
,
248 IConnectionPointContainer
**ppCPC
)
250 ConnectionPointImpl
*This
= (ConnectionPointImpl
*)iface
;
251 TRACE("(%p)->(%p)\n", This
, ppCPC
);
253 return IUnknown_QueryInterface(This
->Obj
,
254 &IID_IConnectionPointContainer
,
258 /************************************************************************
259 * ConnectionPointImpl_Advise (IConnectionPoint)
262 static HRESULT WINAPI
ConnectionPointImpl_Advise(IConnectionPoint
*iface
,
267 ConnectionPointImpl
*This
= (ConnectionPointImpl
*)iface
;
269 TRACE("(%p)->(%p, %p)\n", This
, lpUnk
, pdwCookie
);
272 if(FAILED(IUnknown_QueryInterface(lpUnk
, &This
->iid
, (LPVOID
)&lpSink
)))
273 return CONNECT_E_CANNOTCONNECT
;
275 for(i
= 0; i
< This
->maxSinks
; i
++) {
276 if(This
->sinks
[i
] == NULL
)
279 if(i
== This
->maxSinks
) {
280 This
->maxSinks
+= MAXSINKS
;
281 This
->sinks
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->sinks
,
282 This
->maxSinks
* sizeof(IUnknown
*));
284 This
->sinks
[i
] = lpSink
;
291 /************************************************************************
292 * ConnectionPointImpl_Unadvise (IConnectionPoint)
295 static HRESULT WINAPI
ConnectionPointImpl_Unadvise(IConnectionPoint
*iface
,
298 ConnectionPointImpl
*This
= (ConnectionPointImpl
*)iface
;
299 TRACE("(%p)->(%ld)\n", This
, dwCookie
);
301 if(dwCookie
== 0 || dwCookie
> This
->maxSinks
) return E_INVALIDARG
;
303 if(This
->sinks
[dwCookie
-1] == NULL
) return CONNECT_E_NOCONNECTION
;
305 IUnknown_Release(This
->sinks
[dwCookie
-1]);
306 This
->sinks
[dwCookie
-1] = NULL
;
311 /************************************************************************
312 * ConnectionPointImpl_EnumConnections (IConnectionPoint)
315 static HRESULT WINAPI
ConnectionPointImpl_EnumConnections(
316 IConnectionPoint
*iface
,
317 LPENUMCONNECTIONS
*ppEnum
)
319 ConnectionPointImpl
*This
= (ConnectionPointImpl
*)iface
;
322 EnumConnectionsImpl
*EnumObj
;
325 TRACE("(%p)->(%p)\n", This
, ppEnum
);
329 if(This
->nSinks
== 0) return OLE_E_NOCONNECTION
;
331 pCD
= HeapAlloc(GetProcessHeap(), 0, sizeof(CONNECTDATA
) * This
->nSinks
);
333 for(i
= 0, nextslot
= 0; i
< This
->maxSinks
; i
++) {
334 if(This
->sinks
[i
] != NULL
) {
335 pCD
[nextslot
].pUnk
= This
->sinks
[i
];
336 pCD
[nextslot
].dwCookie
= i
+ 1;
340 assert(nextslot
== This
->nSinks
);
342 /* Bump the ref count of this object up by one. It gets Released in
343 IEnumConnections_Release */
344 IUnknown_AddRef((IUnknown
*)This
);
346 EnumObj
= EnumConnectionsImpl_Construct((IUnknown
*)This
, This
->nSinks
, pCD
);
347 hr
= IEnumConnections_QueryInterface((IEnumConnections
*)EnumObj
,
348 &IID_IEnumConnections
, (LPVOID
)ppEnum
);
349 IEnumConnections_Release((IEnumConnections
*)EnumObj
);
351 HeapFree(GetProcessHeap(), 0, pCD
);
355 static IConnectionPointVtbl ConnectionPointImpl_VTable
=
357 ConnectionPointImpl_QueryInterface
,
358 ConnectionPointImpl_AddRef
,
359 ConnectionPointImpl_Release
,
360 ConnectionPointImpl_GetConnectionInterface
,
361 ConnectionPointImpl_GetConnectionPointContainer
,
362 ConnectionPointImpl_Advise
,
363 ConnectionPointImpl_Unadvise
,
364 ConnectionPointImpl_EnumConnections
368 static IEnumConnectionsVtbl EnumConnectionsImpl_VTable
;
369 static ULONG WINAPI
EnumConnectionsImpl_AddRef(IEnumConnections
* iface
);
371 /************************************************************************
372 * EnumConnectionsImpl_Construct
374 static EnumConnectionsImpl
*EnumConnectionsImpl_Construct(IUnknown
*pUnk
,
378 EnumConnectionsImpl
*Obj
= HeapAlloc(GetProcessHeap(), 0, sizeof(*Obj
));
381 Obj
->lpvtbl
= &EnumConnectionsImpl_VTable
;
384 Obj
->pCD
= HeapAlloc(GetProcessHeap(), 0, nSinks
* sizeof(CONNECTDATA
));
385 Obj
->nConns
= nSinks
;
388 for(i
= 0; i
< nSinks
; i
++) {
389 Obj
->pCD
[i
] = pCD
[i
];
390 IUnknown_AddRef(Obj
->pCD
[i
].pUnk
);
395 /************************************************************************
396 * EnumConnectionsImpl_Destroy
398 static void EnumConnectionsImpl_Destroy(EnumConnectionsImpl
*Obj
)
402 for(i
= 0; i
< Obj
->nConns
; i
++)
403 IUnknown_Release(Obj
->pCD
[i
].pUnk
);
405 HeapFree(GetProcessHeap(), 0, Obj
->pCD
);
406 HeapFree(GetProcessHeap(), 0, Obj
);
410 /************************************************************************
411 * EnumConnectionsImpl_QueryInterface (IUnknown)
413 * See Windows documentation for more details on IUnknown methods.
415 static HRESULT WINAPI
EnumConnectionsImpl_QueryInterface(
416 IEnumConnections
* iface
,
420 ConnectionPointImpl
*This
= (ConnectionPointImpl
*)iface
;
421 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
424 * Perform a sanity check on the parameters.
426 if ( (This
==0) || (ppvObject
==0) )
430 * Initialize the return parameter.
435 * Compare the riid with the interface IDs implemented by this object.
437 if (memcmp(&IID_IUnknown
, riid
, sizeof(IID_IUnknown
)) == 0)
439 *ppvObject
= (IEnumConnections
*)This
;
441 else if (memcmp(&IID_IEnumConnections
, riid
, sizeof(IID_IEnumConnections
)) == 0)
443 *ppvObject
= (IEnumConnections
*)This
;
447 * Check that we obtained an interface.
451 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid
));
452 return E_NOINTERFACE
;
456 * Query Interface always increases the reference count by one when it is
459 EnumConnectionsImpl_AddRef((IEnumConnections
*)This
);
465 /************************************************************************
466 * EnumConnectionsImpl_AddRef (IUnknown)
468 * See Windows documentation for more details on IUnknown methods.
470 static ULONG WINAPI
EnumConnectionsImpl_AddRef(IEnumConnections
* iface
)
472 EnumConnectionsImpl
*This
= (EnumConnectionsImpl
*)iface
;
474 TRACE("(%p)->(ref=%ld)\n", This
, This
->ref
);
475 ref
= InterlockedIncrement(&This
->ref
);
476 IUnknown_AddRef(This
->pUnk
);
480 /************************************************************************
481 * EnumConnectionsImpl_Release (IUnknown)
483 * See Windows documentation for more details on IUnknown methods.
485 static ULONG WINAPI
EnumConnectionsImpl_Release(IEnumConnections
* iface
)
487 EnumConnectionsImpl
*This
= (EnumConnectionsImpl
*)iface
;
489 TRACE("(%p)->(ref=%ld)\n", This
, This
->ref
);
491 IUnknown_Release(This
->pUnk
);
494 * Decrease the reference count on this object.
496 ref
= InterlockedDecrement(&This
->ref
);
499 * If the reference count goes down to 0, perform suicide.
501 if (ref
== 0) EnumConnectionsImpl_Destroy(This
);
506 /************************************************************************
507 * EnumConnectionsImpl_Next (IEnumConnections)
510 static HRESULT WINAPI
EnumConnectionsImpl_Next(IEnumConnections
* iface
,
511 ULONG cConn
, LPCONNECTDATA pCD
,
514 EnumConnectionsImpl
*This
= (EnumConnectionsImpl
*)iface
;
516 TRACE("(%p)->(%ld, %p, %p)\n", This
, cConn
, pCD
, pEnum
);
524 if(This
->nCur
>= This
->nConns
)
527 while(This
->nCur
< This
->nConns
&& cConn
) {
528 *pCD
++ = This
->pCD
[This
->nCur
];
529 IUnknown_AddRef(This
->pCD
[This
->nCur
].pUnk
);
542 /************************************************************************
543 * EnumConnectionsImpl_Skip (IEnumConnections)
546 static HRESULT WINAPI
EnumConnectionsImpl_Skip(IEnumConnections
* iface
,
549 EnumConnectionsImpl
*This
= (EnumConnectionsImpl
*)iface
;
550 TRACE("(%p)->(%ld)\n", This
, cSkip
);
552 if(This
->nCur
+ cSkip
>= This
->nConns
)
561 /************************************************************************
562 * EnumConnectionsImpl_Reset (IEnumConnections)
565 static HRESULT WINAPI
EnumConnectionsImpl_Reset(IEnumConnections
* iface
)
567 EnumConnectionsImpl
*This
= (EnumConnectionsImpl
*)iface
;
568 TRACE("(%p)\n", This
);
576 /************************************************************************
577 * EnumConnectionsImpl_Clone (IEnumConnections)
580 static HRESULT WINAPI
EnumConnectionsImpl_Clone(IEnumConnections
* iface
,
581 LPENUMCONNECTIONS
*ppEnum
)
583 EnumConnectionsImpl
*This
= (EnumConnectionsImpl
*)iface
;
584 EnumConnectionsImpl
*newObj
;
585 TRACE("(%p)->(%p)\n", This
, ppEnum
);
587 newObj
= EnumConnectionsImpl_Construct(This
->pUnk
, This
->nConns
, This
->pCD
);
588 newObj
->nCur
= This
->nCur
;
589 *ppEnum
= (LPENUMCONNECTIONS
)newObj
;
590 IUnknown_AddRef(This
->pUnk
);
594 static IEnumConnectionsVtbl EnumConnectionsImpl_VTable
=
596 EnumConnectionsImpl_QueryInterface
,
597 EnumConnectionsImpl_AddRef
,
598 EnumConnectionsImpl_Release
,
599 EnumConnectionsImpl_Next
,
600 EnumConnectionsImpl_Skip
,
601 EnumConnectionsImpl_Reset
,
602 EnumConnectionsImpl_Clone
605 /************************************************************************
607 * The exported function to create the connection point.
608 * NB not a windows API
611 * pUnk [in] IUnknown of object to which the ConnectionPoint is associated.
612 * Needed to access IConnectionPointContainer.
614 * riid [in] IID of sink interface that this ConnectionPoint manages
616 * pCP [out] returns IConnectionPoint
619 HRESULT
CreateConnectionPoint(IUnknown
*pUnk
, REFIID riid
,
620 IConnectionPoint
**pCP
)
622 ConnectionPointImpl
*Obj
;
625 Obj
= ConnectionPointImpl_Construct(pUnk
, riid
);
626 if(!Obj
) return E_OUTOFMEMORY
;
628 hr
= IConnectionPoint_QueryInterface((IConnectionPoint
*)Obj
,
629 &IID_IConnectionPoint
, (LPVOID
)pCP
);
630 IConnectionPoint_Release((IConnectionPoint
*)Obj
);