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 const IConnectionPointVtbl *lpvtbl;
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 const 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 ULONG refCount = InterlockedIncrement(&This->ref);
201 TRACE("(%p)->(ref before=%ld)\n", This, refCount - 1);
206 /************************************************************************
207 * ConnectionPointImpl_Release (IUnknown)
209 * See Windows documentation for more details on IUnknown methods.
211 static ULONG WINAPI ConnectionPointImpl_Release(
212 IConnectionPoint* iface)
214 ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
215 ULONG refCount = InterlockedDecrement(&This->ref);
217 TRACE("(%p)->(ref before=%ld)\n", This, refCount + 1);
220 * If the reference count goes down to 0, perform suicide.
222 if (!refCount) ConnectionPointImpl_Destroy(This);
227 /************************************************************************
228 * ConnectionPointImpl_GetConnectionInterface (IConnectionPoint)
231 static HRESULT WINAPI ConnectionPointImpl_GetConnectionInterface(
232 IConnectionPoint *iface,
235 ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
236 TRACE("(%p)->(%p) returning %s\n", This, piid, debugstr_guid(&(This->iid)));
241 /************************************************************************
242 * ConnectionPointImpl_GetConnectionPointContainer (IConnectionPoint)
245 static HRESULT WINAPI ConnectionPointImpl_GetConnectionPointContainer(
246 IConnectionPoint *iface,
247 IConnectionPointContainer **ppCPC)
249 ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
250 TRACE("(%p)->(%p)\n", This, ppCPC);
252 return IUnknown_QueryInterface(This->Obj,
253 &IID_IConnectionPointContainer,
257 /************************************************************************
258 * ConnectionPointImpl_Advise (IConnectionPoint)
261 static HRESULT WINAPI ConnectionPointImpl_Advise(IConnectionPoint *iface,
266 ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
268 TRACE("(%p)->(%p, %p)\n", This, lpUnk, pdwCookie);
271 if(FAILED(IUnknown_QueryInterface(lpUnk, &This->iid, (LPVOID)&lpSink)))
272 return CONNECT_E_CANNOTCONNECT;
274 for(i = 0; i < This->maxSinks; i++) {
275 if(This->sinks[i] == NULL)
278 if(i == This->maxSinks) {
279 This->maxSinks += MAXSINKS;
280 This->sinks = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->sinks,
281 This->maxSinks * sizeof(IUnknown *));
283 This->sinks[i] = lpSink;
290 /************************************************************************
291 * ConnectionPointImpl_Unadvise (IConnectionPoint)
294 static HRESULT WINAPI ConnectionPointImpl_Unadvise(IConnectionPoint *iface,
297 ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
298 TRACE("(%p)->(%ld)\n", This, dwCookie);
300 if(dwCookie == 0 || dwCookie > This->maxSinks) return E_INVALIDARG;
302 if(This->sinks[dwCookie-1] == NULL) return CONNECT_E_NOCONNECTION;
304 IUnknown_Release(This->sinks[dwCookie-1]);
305 This->sinks[dwCookie-1] = NULL;
310 /************************************************************************
311 * ConnectionPointImpl_EnumConnections (IConnectionPoint)
314 static HRESULT WINAPI ConnectionPointImpl_EnumConnections(
315 IConnectionPoint *iface,
316 LPENUMCONNECTIONS *ppEnum)
318 ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
321 EnumConnectionsImpl *EnumObj;
324 TRACE("(%p)->(%p)\n", This, ppEnum);
328 if(This->nSinks == 0) return OLE_E_NOCONNECTION;
330 pCD = HeapAlloc(GetProcessHeap(), 0, sizeof(CONNECTDATA) * This->nSinks);
332 for(i = 0, nextslot = 0; i < This->maxSinks; i++) {
333 if(This->sinks[i] != NULL) {
334 pCD[nextslot].pUnk = This->sinks[i];
335 pCD[nextslot].dwCookie = i + 1;
339 assert(nextslot == This->nSinks);
341 /* Bump the ref count of this object up by one. It gets Released in
342 IEnumConnections_Release */
343 IUnknown_AddRef((IUnknown*)This);
345 EnumObj = EnumConnectionsImpl_Construct((IUnknown*)This, This->nSinks, pCD);
346 hr = IEnumConnections_QueryInterface((IEnumConnections*)EnumObj,
347 &IID_IEnumConnections, (LPVOID)ppEnum);
348 IEnumConnections_Release((IEnumConnections*)EnumObj);
350 HeapFree(GetProcessHeap(), 0, pCD);
354 static const IConnectionPointVtbl ConnectionPointImpl_VTable =
356 ConnectionPointImpl_QueryInterface,
357 ConnectionPointImpl_AddRef,
358 ConnectionPointImpl_Release,
359 ConnectionPointImpl_GetConnectionInterface,
360 ConnectionPointImpl_GetConnectionPointContainer,
361 ConnectionPointImpl_Advise,
362 ConnectionPointImpl_Unadvise,
363 ConnectionPointImpl_EnumConnections
367 static const IEnumConnectionsVtbl EnumConnectionsImpl_VTable;
368 static ULONG WINAPI EnumConnectionsImpl_AddRef(IEnumConnections* iface);
370 /************************************************************************
371 * EnumConnectionsImpl_Construct
373 static EnumConnectionsImpl *EnumConnectionsImpl_Construct(IUnknown *pUnk,
377 EnumConnectionsImpl *Obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*Obj));
380 Obj->lpvtbl = &EnumConnectionsImpl_VTable;
383 Obj->pCD = HeapAlloc(GetProcessHeap(), 0, nSinks * sizeof(CONNECTDATA));
384 Obj->nConns = nSinks;
387 for(i = 0; i < nSinks; i++) {
388 Obj->pCD[i] = pCD[i];
389 IUnknown_AddRef(Obj->pCD[i].pUnk);
394 /************************************************************************
395 * EnumConnectionsImpl_Destroy
397 static void EnumConnectionsImpl_Destroy(EnumConnectionsImpl *Obj)
401 for(i = 0; i < Obj->nConns; i++)
402 IUnknown_Release(Obj->pCD[i].pUnk);
404 HeapFree(GetProcessHeap(), 0, Obj->pCD);
405 HeapFree(GetProcessHeap(), 0, Obj);
409 /************************************************************************
410 * EnumConnectionsImpl_QueryInterface (IUnknown)
412 * See Windows documentation for more details on IUnknown methods.
414 static HRESULT WINAPI EnumConnectionsImpl_QueryInterface(
415 IEnumConnections* iface,
419 ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
420 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
423 * Perform a sanity check on the parameters.
425 if ( (This==0) || (ppvObject==0) )
429 * Initialize the return parameter.
434 * Compare the riid with the interface IDs implemented by this object.
436 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
438 *ppvObject = (IEnumConnections*)This;
440 else if (memcmp(&IID_IEnumConnections, riid, sizeof(IID_IEnumConnections)) == 0)
442 *ppvObject = (IEnumConnections*)This;
446 * Check that we obtained an interface.
450 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
451 return E_NOINTERFACE;
455 * Query Interface always increases the reference count by one when it is
458 EnumConnectionsImpl_AddRef((IEnumConnections*)This);
464 /************************************************************************
465 * EnumConnectionsImpl_AddRef (IUnknown)
467 * See Windows documentation for more details on IUnknown methods.
469 static ULONG WINAPI EnumConnectionsImpl_AddRef(IEnumConnections* iface)
471 EnumConnectionsImpl *This = (EnumConnectionsImpl *)iface;
472 ULONG refCount = InterlockedIncrement(&This->ref);
474 TRACE("(%p)->(ref before=%ld)\n", This, refCount - 1);
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;
488 ULONG refCount = InterlockedDecrement(&This->ref);
490 TRACE("(%p)->(ref before=%ld)\n", This, refCount + 1);
492 IUnknown_Release(This->pUnk);
495 * If the reference count goes down to 0, perform suicide.
497 if (!refCount) EnumConnectionsImpl_Destroy(This);
502 /************************************************************************
503 * EnumConnectionsImpl_Next (IEnumConnections)
506 static HRESULT WINAPI EnumConnectionsImpl_Next(IEnumConnections* iface,
507 ULONG cConn, LPCONNECTDATA pCD,
510 EnumConnectionsImpl *This = (EnumConnectionsImpl *)iface;
512 TRACE("(%p)->(%ld, %p, %p)\n", This, cConn, pCD, pEnum);
520 if(This->nCur >= This->nConns)
523 while(This->nCur < This->nConns && cConn) {
524 *pCD++ = This->pCD[This->nCur];
525 IUnknown_AddRef(This->pCD[This->nCur].pUnk);
538 /************************************************************************
539 * EnumConnectionsImpl_Skip (IEnumConnections)
542 static HRESULT WINAPI EnumConnectionsImpl_Skip(IEnumConnections* iface,
545 EnumConnectionsImpl *This = (EnumConnectionsImpl *)iface;
546 TRACE("(%p)->(%ld)\n", This, cSkip);
548 if(This->nCur + cSkip >= This->nConns)
557 /************************************************************************
558 * EnumConnectionsImpl_Reset (IEnumConnections)
561 static HRESULT WINAPI EnumConnectionsImpl_Reset(IEnumConnections* iface)
563 EnumConnectionsImpl *This = (EnumConnectionsImpl *)iface;
564 TRACE("(%p)\n", This);
572 /************************************************************************
573 * EnumConnectionsImpl_Clone (IEnumConnections)
576 static HRESULT WINAPI EnumConnectionsImpl_Clone(IEnumConnections* iface,
577 LPENUMCONNECTIONS *ppEnum)
579 EnumConnectionsImpl *This = (EnumConnectionsImpl *)iface;
580 EnumConnectionsImpl *newObj;
581 TRACE("(%p)->(%p)\n", This, ppEnum);
583 newObj = EnumConnectionsImpl_Construct(This->pUnk, This->nConns, This->pCD);
584 newObj->nCur = This->nCur;
585 *ppEnum = (LPENUMCONNECTIONS)newObj;
586 IUnknown_AddRef(This->pUnk);
590 static const IEnumConnectionsVtbl EnumConnectionsImpl_VTable =
592 EnumConnectionsImpl_QueryInterface,
593 EnumConnectionsImpl_AddRef,
594 EnumConnectionsImpl_Release,
595 EnumConnectionsImpl_Next,
596 EnumConnectionsImpl_Skip,
597 EnumConnectionsImpl_Reset,
598 EnumConnectionsImpl_Clone
601 /************************************************************************
603 * The exported function to create the connection point.
604 * NB not a windows API
607 * pUnk [in] IUnknown of object to which the ConnectionPoint is associated.
608 * Needed to access IConnectionPointContainer.
610 * riid [in] IID of sink interface that this ConnectionPoint manages
612 * pCP [out] returns IConnectionPoint
615 HRESULT CreateConnectionPoint(IUnknown *pUnk, REFIID riid,
616 IConnectionPoint **pCP)
618 ConnectionPointImpl *Obj;
621 Obj = ConnectionPointImpl_Construct(pUnk, riid);
622 if(!Obj) return E_OUTOFMEMORY;
624 hr = IConnectionPoint_QueryInterface((IConnectionPoint *)Obj,
625 &IID_IConnectionPoint, (LPVOID)pCP);
626 IConnectionPoint_Release((IConnectionPoint *)Obj);