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.
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
41 /************************************************************************
42 * Implementation of IConnectionPoint
44 typedef struct ConnectionPointImpl
{
46 ICOM_VTABLE(IConnectionPoint
) *lpvtbl
;
48 /* IUnknown of our main object*/
54 /* IID of sink interface */
57 /* Array of sink IUnknowns */
62 } ConnectionPointImpl
;
64 static ICOM_VTABLE(IConnectionPoint
) ConnectionPointImpl_VTable
;
67 /************************************************************************
68 * Implementation of IEnumConnections
70 typedef struct EnumConnectionsImpl
{
72 ICOM_VTABLE(IEnumConnections
) *lpvtbl
;
76 /* IUnknown of ConnectionPoint, used for ref counting */
83 /* Next connection to enumerate from */
86 } EnumConnectionsImpl
;
88 static EnumConnectionsImpl
*EnumConnectionsImpl_Construct(IUnknown
*pUnk
,
93 /************************************************************************
94 * ConnectionPointImpl_Construct
96 static ConnectionPointImpl
*ConnectionPointImpl_Construct(IUnknown
*pUnk
,
99 ConnectionPointImpl
*Obj
;
101 Obj
= HeapAlloc(GetProcessHeap(), 0, sizeof(*Obj
));
102 Obj
->lpvtbl
= &ConnectionPointImpl_VTable
;
106 Obj
->maxSinks
= MAXSINKS
;
107 Obj
->sinks
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
108 sizeof(IUnknown
*) * MAXSINKS
);
113 /************************************************************************
114 * ConnectionPointImpl_Destroy
116 static void ConnectionPointImpl_Destroy(ConnectionPointImpl
*Obj
)
119 for(i
= 0; i
< Obj
->maxSinks
; i
++) {
121 IUnknown_Release(Obj
->sinks
[i
]);
122 Obj
->sinks
[i
] = NULL
;
125 HeapFree(GetProcessHeap(), 0, Obj
->sinks
);
126 HeapFree(GetProcessHeap(), 0, Obj
);
130 static ULONG WINAPI
ConnectionPointImpl_AddRef(IConnectionPoint
* iface
);
131 /************************************************************************
132 * ConnectionPointImpl_QueryInterface (IUnknown)
134 * See Windows documentation for more details on IUnknown methods.
136 static HRESULT WINAPI
ConnectionPointImpl_QueryInterface(
137 IConnectionPoint
* iface
,
141 ICOM_THIS(ConnectionPointImpl
, iface
);
142 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
145 * Perform a sanity check on the parameters.
147 if ( (This
==0) || (ppvObject
==0) )
151 * Initialize the return parameter.
156 * Compare the riid with the interface IDs implemented by this object.
158 if (memcmp(&IID_IUnknown
, riid
, sizeof(IID_IUnknown
)) == 0)
160 *ppvObject
= (IConnectionPoint
*)This
;
162 else if (memcmp(&IID_IConnectionPoint
, riid
, sizeof(IID_IConnectionPoint
)) == 0)
164 *ppvObject
= (IConnectionPoint
*)This
;
168 * Check that we obtained an interface.
172 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid
));
173 return E_NOINTERFACE
;
177 * Query Interface always increases the reference count by one when it is
180 ConnectionPointImpl_AddRef((IConnectionPoint
*)This
);
186 /************************************************************************
187 * ConnectionPointImpl_AddRef (IUnknown)
189 * See Windows documentation for more details on IUnknown methods.
191 static ULONG WINAPI
ConnectionPointImpl_AddRef(IConnectionPoint
* iface
)
193 ICOM_THIS(ConnectionPointImpl
, iface
);
194 TRACE("(%p)->(ref=%ld)\n", This
, This
->ref
);
200 /************************************************************************
201 * ConnectionPointImpl_Release (IUnknown)
203 * See Windows documentation for more details on IUnknown methods.
205 static ULONG WINAPI
ConnectionPointImpl_Release(
206 IConnectionPoint
* iface
)
208 ICOM_THIS(ConnectionPointImpl
, iface
);
209 TRACE("(%p)->(ref=%ld)\n", This
, This
->ref
);
212 * Decrease the reference count on this object.
217 * If the reference count goes down to 0, perform suicide.
221 ConnectionPointImpl_Destroy(This
);
229 /************************************************************************
230 * ConnectionPointImpl_GetConnectionInterface (IConnectionPoint)
233 static HRESULT WINAPI
ConnectionPointImpl_GetConnectionInterface(
234 IConnectionPoint
*iface
,
237 ICOM_THIS(ConnectionPointImpl
, iface
);
238 TRACE("(%p)->(%p) returning %s\n", This
, piid
, debugstr_guid(&(This
->iid
)));
243 /************************************************************************
244 * ConnectionPointImpl_GetConnectionPointContainer (IConnectionPoint)
247 static HRESULT WINAPI
ConnectionPointImpl_GetConnectionPointContainer(
248 IConnectionPoint
*iface
,
249 IConnectionPointContainer
**ppCPC
)
251 ICOM_THIS(ConnectionPointImpl
, iface
);
252 TRACE("(%p)->(%p)\n", This
, ppCPC
);
254 return IUnknown_QueryInterface(This
->Obj
,
255 &IID_IConnectionPointContainer
,
259 /************************************************************************
260 * ConnectionPointImpl_Advise (IConnectionPoint)
263 static HRESULT WINAPI
ConnectionPointImpl_Advise(IConnectionPoint
*iface
,
268 ICOM_THIS(ConnectionPointImpl
, iface
);
270 TRACE("(%p)->(%p, %p)\n", This
, lpUnk
, pdwCookie
);
273 if(FAILED(IUnknown_QueryInterface(lpUnk
, &This
->iid
, (LPVOID
)&lpSink
)))
274 return CONNECT_E_CANNOTCONNECT
;
276 for(i
= 0; i
< This
->maxSinks
; i
++) {
277 if(This
->sinks
[i
] == NULL
)
280 if(i
== This
->maxSinks
) {
281 This
->maxSinks
+= MAXSINKS
;
282 This
->sinks
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->sinks
,
283 This
->maxSinks
* sizeof(IUnknown
*));
285 This
->sinks
[i
] = lpSink
;
292 /************************************************************************
293 * ConnectionPointImpl_Unadvise (IConnectionPoint)
296 static HRESULT WINAPI
ConnectionPointImpl_Unadvise(IConnectionPoint
*iface
,
299 ICOM_THIS(ConnectionPointImpl
, iface
);
300 TRACE("(%p)->(%ld)\n", This
, dwCookie
);
302 if(dwCookie
== 0 || dwCookie
> This
->maxSinks
) return E_INVALIDARG
;
304 if(This
->sinks
[dwCookie
-1] == NULL
) return CONNECT_E_NOCONNECTION
;
306 IUnknown_Release(This
->sinks
[dwCookie
-1]);
307 This
->sinks
[dwCookie
-1] = NULL
;
312 /************************************************************************
313 * ConnectionPointImpl_EnumConnections (IConnectionPoint)
316 static HRESULT WINAPI
ConnectionPointImpl_EnumConnections(
317 IConnectionPoint
*iface
,
318 LPENUMCONNECTIONS
*ppEnum
)
320 ICOM_THIS(ConnectionPointImpl
, iface
);
323 EnumConnectionsImpl
*EnumObj
;
326 TRACE("(%p)->(%p)\n", This
, ppEnum
);
330 if(This
->nSinks
== 0) return OLE_E_NOCONNECTION
;
332 pCD
= HeapAlloc(GetProcessHeap(), 0, sizeof(CONNECTDATA
) * This
->nSinks
);
334 for(i
= 0, nextslot
= 0; i
< This
->maxSinks
; i
++) {
335 if(This
->sinks
[i
] != NULL
) {
336 pCD
[nextslot
].pUnk
= This
->sinks
[i
];
337 pCD
[nextslot
].dwCookie
= i
+ 1;
341 assert(nextslot
== This
->nSinks
);
343 /* Bump the ref count of this object up by one. It gets Released in
344 IEnumConnections_Release */
345 IUnknown_AddRef((IUnknown
*)This
);
347 EnumObj
= EnumConnectionsImpl_Construct((IUnknown
*)This
, This
->nSinks
, pCD
);
348 hr
= IEnumConnections_QueryInterface((IEnumConnections
*)EnumObj
,
349 &IID_IEnumConnections
, (LPVOID
)ppEnum
);
350 IEnumConnections_Release((IEnumConnections
*)EnumObj
);
352 HeapFree(GetProcessHeap(), 0, pCD
);
356 static ICOM_VTABLE(IConnectionPoint
) ConnectionPointImpl_VTable
=
358 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
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 ICOM_VTABLE(IEnumConnections
) 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
->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 ICOM_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 (memcmp(&IID_IUnknown
, riid
, sizeof(IID_IUnknown
)) == 0)
441 *ppvObject
= (IEnumConnections
*)This
;
443 else if (memcmp(&IID_IEnumConnections
, riid
, sizeof(IID_IEnumConnections
)) == 0)
445 *ppvObject
= (IEnumConnections
*)This
;
449 * Check that we obtained an interface.
453 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid
));
454 return E_NOINTERFACE
;
458 * Query Interface always increases the reference count by one when it is
461 EnumConnectionsImpl_AddRef((IEnumConnections
*)This
);
467 /************************************************************************
468 * EnumConnectionsImpl_AddRef (IUnknown)
470 * See Windows documentation for more details on IUnknown methods.
472 static ULONG WINAPI
EnumConnectionsImpl_AddRef(IEnumConnections
* iface
)
474 ICOM_THIS(EnumConnectionsImpl
, iface
);
475 TRACE("(%p)->(ref=%ld)\n", This
, This
->ref
);
477 IUnknown_AddRef(This
->pUnk
);
481 /************************************************************************
482 * EnumConnectionsImpl_Release (IUnknown)
484 * See Windows documentation for more details on IUnknown methods.
486 static ULONG WINAPI
EnumConnectionsImpl_Release(IEnumConnections
* iface
)
488 ICOM_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.
499 * If the reference count goes down to 0, perform suicide.
503 EnumConnectionsImpl_Destroy(This
);
511 /************************************************************************
512 * EnumConnectionsImpl_Next (IEnumConnections)
515 static HRESULT WINAPI
EnumConnectionsImpl_Next(IEnumConnections
* iface
,
516 ULONG cConn
, LPCONNECTDATA pCD
,
519 ICOM_THIS(EnumConnectionsImpl
, iface
);
521 TRACE("(%p)->(%ld, %p, %p)\n", This
, cConn
, pCD
, pEnum
);
529 if(This
->nCur
>= This
->nConns
)
532 while(This
->nCur
< This
->nConns
&& cConn
) {
533 *pCD
++ = This
->pCD
[This
->nCur
];
534 IUnknown_AddRef(This
->pCD
[This
->nCur
].pUnk
);
547 /************************************************************************
548 * EnumConnectionsImpl_Skip (IEnumConnections)
551 static HRESULT WINAPI
EnumConnectionsImpl_Skip(IEnumConnections
* iface
,
554 ICOM_THIS(EnumConnectionsImpl
, iface
);
555 TRACE("(%p)->(%ld)\n", This
, cSkip
);
557 if(This
->nCur
+ cSkip
>= This
->nConns
)
566 /************************************************************************
567 * EnumConnectionsImpl_Reset (IEnumConnections)
570 static HRESULT WINAPI
EnumConnectionsImpl_Reset(IEnumConnections
* iface
)
572 ICOM_THIS(EnumConnectionsImpl
, iface
);
573 TRACE("(%p)\n", This
);
581 /************************************************************************
582 * EnumConnectionsImpl_Clone (IEnumConnections)
585 static HRESULT WINAPI
EnumConnectionsImpl_Clone(IEnumConnections
* iface
,
586 LPENUMCONNECTIONS
*ppEnum
)
588 ICOM_THIS(EnumConnectionsImpl
, iface
);
589 EnumConnectionsImpl
*newObj
;
590 TRACE("(%p)->(%p)\n", This
, ppEnum
);
592 newObj
= EnumConnectionsImpl_Construct(This
->pUnk
, This
->nConns
, This
->pCD
);
593 newObj
->nCur
= This
->nCur
;
594 *ppEnum
= (LPENUMCONNECTIONS
)newObj
;
595 IUnknown_AddRef(This
->pUnk
);
599 static ICOM_VTABLE(IEnumConnections
) EnumConnectionsImpl_VTable
=
601 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
602 EnumConnectionsImpl_QueryInterface
,
603 EnumConnectionsImpl_AddRef
,
604 EnumConnectionsImpl_Release
,
605 EnumConnectionsImpl_Next
,
606 EnumConnectionsImpl_Skip
,
607 EnumConnectionsImpl_Reset
,
608 EnumConnectionsImpl_Clone
611 /************************************************************************
613 * The exported function to create the connection point.
614 * NB not a windows API
617 * pUnk [in] IUnknown of object to which the ConnectionPoint is associated.
618 * Needed to access IConnectionPointContainer.
620 * riid [in] IID of sink interface that this ConnectionPoint manages
622 * pCP [out] returns IConnectionPoint
625 HRESULT
CreateConnectionPoint(IUnknown
*pUnk
, REFIID riid
,
626 IConnectionPoint
**pCP
)
628 ConnectionPointImpl
*Obj
;
631 Obj
= ConnectionPointImpl_Construct(pUnk
, riid
);
632 if(!Obj
) return E_OUTOFMEMORY
;
634 hr
= IConnectionPoint_QueryInterface((IConnectionPoint
*)Obj
,
635 &IID_IConnectionPoint
, (LPVOID
)pCP
);
636 IConnectionPoint_Release((IConnectionPoint
*)Obj
);