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.
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(ole);
43 /************************************************************************
44 * Implementation of IConnectionPoint
46 typedef struct ConnectionPointImpl {
48 IConnectionPointVtbl *lpvtbl;
50 /* IUnknown of our main object*/
56 /* IID of sink interface */
59 /* Array of sink IUnknowns */
64 } ConnectionPointImpl;
66 static IConnectionPointVtbl ConnectionPointImpl_VTable;
69 /************************************************************************
70 * Implementation of IEnumConnections
72 typedef struct EnumConnectionsImpl {
74 IEnumConnectionsVtbl *lpvtbl;
78 /* IUnknown of ConnectionPoint, used for ref counting */
85 /* Next connection to enumerate from */
88 } EnumConnectionsImpl;
90 static EnumConnectionsImpl *EnumConnectionsImpl_Construct(IUnknown *pUnk,
95 /************************************************************************
96 * ConnectionPointImpl_Construct
98 static ConnectionPointImpl *ConnectionPointImpl_Construct(IUnknown *pUnk,
101 ConnectionPointImpl *Obj;
103 Obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*Obj));
104 Obj->lpvtbl = &ConnectionPointImpl_VTable;
108 Obj->maxSinks = MAXSINKS;
109 Obj->sinks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
110 sizeof(IUnknown*) * MAXSINKS);
115 /************************************************************************
116 * ConnectionPointImpl_Destroy
118 static void ConnectionPointImpl_Destroy(ConnectionPointImpl *Obj)
121 for(i = 0; i < Obj->maxSinks; i++) {
123 IUnknown_Release(Obj->sinks[i]);
124 Obj->sinks[i] = NULL;
127 HeapFree(GetProcessHeap(), 0, Obj->sinks);
128 HeapFree(GetProcessHeap(), 0, Obj);
132 static ULONG WINAPI ConnectionPointImpl_AddRef(IConnectionPoint* iface);
133 /************************************************************************
134 * ConnectionPointImpl_QueryInterface (IUnknown)
136 * See Windows documentation for more details on IUnknown methods.
138 static HRESULT WINAPI ConnectionPointImpl_QueryInterface(
139 IConnectionPoint* iface,
143 ICOM_THIS(ConnectionPointImpl, iface);
144 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
147 * Perform a sanity check on the parameters.
149 if ( (This==0) || (ppvObject==0) )
153 * Initialize the return parameter.
158 * Compare the riid with the interface IDs implemented by this object.
160 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
162 *ppvObject = (IConnectionPoint*)This;
164 else if (memcmp(&IID_IConnectionPoint, riid, sizeof(IID_IConnectionPoint)) == 0)
166 *ppvObject = (IConnectionPoint*)This;
170 * Check that we obtained an interface.
174 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
175 return E_NOINTERFACE;
179 * Query Interface always increases the reference count by one when it is
182 ConnectionPointImpl_AddRef((IConnectionPoint*)This);
188 /************************************************************************
189 * ConnectionPointImpl_AddRef (IUnknown)
191 * See Windows documentation for more details on IUnknown methods.
193 static ULONG WINAPI ConnectionPointImpl_AddRef(IConnectionPoint* iface)
195 ICOM_THIS(ConnectionPointImpl, iface);
196 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
202 /************************************************************************
203 * ConnectionPointImpl_Release (IUnknown)
205 * See Windows documentation for more details on IUnknown methods.
207 static ULONG WINAPI ConnectionPointImpl_Release(
208 IConnectionPoint* iface)
210 ICOM_THIS(ConnectionPointImpl, iface);
211 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
214 * Decrease the reference count on this object.
219 * If the reference count goes down to 0, perform suicide.
223 ConnectionPointImpl_Destroy(This);
231 /************************************************************************
232 * ConnectionPointImpl_GetConnectionInterface (IConnectionPoint)
235 static HRESULT WINAPI ConnectionPointImpl_GetConnectionInterface(
236 IConnectionPoint *iface,
239 ICOM_THIS(ConnectionPointImpl, iface);
240 TRACE("(%p)->(%p) returning %s\n", This, piid, debugstr_guid(&(This->iid)));
245 /************************************************************************
246 * ConnectionPointImpl_GetConnectionPointContainer (IConnectionPoint)
249 static HRESULT WINAPI ConnectionPointImpl_GetConnectionPointContainer(
250 IConnectionPoint *iface,
251 IConnectionPointContainer **ppCPC)
253 ICOM_THIS(ConnectionPointImpl, iface);
254 TRACE("(%p)->(%p)\n", This, ppCPC);
256 return IUnknown_QueryInterface(This->Obj,
257 &IID_IConnectionPointContainer,
261 /************************************************************************
262 * ConnectionPointImpl_Advise (IConnectionPoint)
265 static HRESULT WINAPI ConnectionPointImpl_Advise(IConnectionPoint *iface,
270 ICOM_THIS(ConnectionPointImpl, iface);
272 TRACE("(%p)->(%p, %p)\n", This, lpUnk, pdwCookie);
275 if(FAILED(IUnknown_QueryInterface(lpUnk, &This->iid, (LPVOID)&lpSink)))
276 return CONNECT_E_CANNOTCONNECT;
278 for(i = 0; i < This->maxSinks; i++) {
279 if(This->sinks[i] == NULL)
282 if(i == This->maxSinks) {
283 This->maxSinks += MAXSINKS;
284 This->sinks = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->sinks,
285 This->maxSinks * sizeof(IUnknown *));
287 This->sinks[i] = lpSink;
294 /************************************************************************
295 * ConnectionPointImpl_Unadvise (IConnectionPoint)
298 static HRESULT WINAPI ConnectionPointImpl_Unadvise(IConnectionPoint *iface,
301 ICOM_THIS(ConnectionPointImpl, iface);
302 TRACE("(%p)->(%ld)\n", This, dwCookie);
304 if(dwCookie == 0 || dwCookie > This->maxSinks) return E_INVALIDARG;
306 if(This->sinks[dwCookie-1] == NULL) return CONNECT_E_NOCONNECTION;
308 IUnknown_Release(This->sinks[dwCookie-1]);
309 This->sinks[dwCookie-1] = NULL;
314 /************************************************************************
315 * ConnectionPointImpl_EnumConnections (IConnectionPoint)
318 static HRESULT WINAPI ConnectionPointImpl_EnumConnections(
319 IConnectionPoint *iface,
320 LPENUMCONNECTIONS *ppEnum)
322 ICOM_THIS(ConnectionPointImpl, iface);
325 EnumConnectionsImpl *EnumObj;
328 TRACE("(%p)->(%p)\n", This, ppEnum);
332 if(This->nSinks == 0) return OLE_E_NOCONNECTION;
334 pCD = HeapAlloc(GetProcessHeap(), 0, sizeof(CONNECTDATA) * This->nSinks);
336 for(i = 0, nextslot = 0; i < This->maxSinks; i++) {
337 if(This->sinks[i] != NULL) {
338 pCD[nextslot].pUnk = This->sinks[i];
339 pCD[nextslot].dwCookie = i + 1;
343 assert(nextslot == This->nSinks);
345 /* Bump the ref count of this object up by one. It gets Released in
346 IEnumConnections_Release */
347 IUnknown_AddRef((IUnknown*)This);
349 EnumObj = EnumConnectionsImpl_Construct((IUnknown*)This, This->nSinks, pCD);
350 hr = IEnumConnections_QueryInterface((IEnumConnections*)EnumObj,
351 &IID_IEnumConnections, (LPVOID)ppEnum);
352 IEnumConnections_Release((IEnumConnections*)EnumObj);
354 HeapFree(GetProcessHeap(), 0, pCD);
358 static IConnectionPointVtbl ConnectionPointImpl_VTable =
360 ConnectionPointImpl_QueryInterface,
361 ConnectionPointImpl_AddRef,
362 ConnectionPointImpl_Release,
363 ConnectionPointImpl_GetConnectionInterface,
364 ConnectionPointImpl_GetConnectionPointContainer,
365 ConnectionPointImpl_Advise,
366 ConnectionPointImpl_Unadvise,
367 ConnectionPointImpl_EnumConnections
371 static IEnumConnectionsVtbl EnumConnectionsImpl_VTable;
372 static ULONG WINAPI EnumConnectionsImpl_AddRef(IEnumConnections* iface);
374 /************************************************************************
375 * EnumConnectionsImpl_Construct
377 static EnumConnectionsImpl *EnumConnectionsImpl_Construct(IUnknown *pUnk,
381 EnumConnectionsImpl *Obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*Obj));
384 Obj->lpvtbl = &EnumConnectionsImpl_VTable;
387 Obj->pCD = HeapAlloc(GetProcessHeap(), 0, nSinks * sizeof(CONNECTDATA));
388 Obj->nConns = nSinks;
391 for(i = 0; i < nSinks; i++) {
392 Obj->pCD[i] = pCD[i];
393 IUnknown_AddRef(Obj->pCD[i].pUnk);
398 /************************************************************************
399 * EnumConnectionsImpl_Destroy
401 static void EnumConnectionsImpl_Destroy(EnumConnectionsImpl *Obj)
405 for(i = 0; i < Obj->nConns; i++)
406 IUnknown_Release(Obj->pCD[i].pUnk);
408 HeapFree(GetProcessHeap(), 0, Obj->pCD);
409 HeapFree(GetProcessHeap(), 0, Obj);
413 /************************************************************************
414 * EnumConnectionsImpl_QueryInterface (IUnknown)
416 * See Windows documentation for more details on IUnknown methods.
418 static HRESULT WINAPI EnumConnectionsImpl_QueryInterface(
419 IEnumConnections* iface,
423 ICOM_THIS(ConnectionPointImpl, iface);
424 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
427 * Perform a sanity check on the parameters.
429 if ( (This==0) || (ppvObject==0) )
433 * Initialize the return parameter.
438 * Compare the riid with the interface IDs implemented by this object.
440 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
442 *ppvObject = (IEnumConnections*)This;
444 else if (memcmp(&IID_IEnumConnections, riid, sizeof(IID_IEnumConnections)) == 0)
446 *ppvObject = (IEnumConnections*)This;
450 * Check that we obtained an interface.
454 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
455 return E_NOINTERFACE;
459 * Query Interface always increases the reference count by one when it is
462 EnumConnectionsImpl_AddRef((IEnumConnections*)This);
468 /************************************************************************
469 * EnumConnectionsImpl_AddRef (IUnknown)
471 * See Windows documentation for more details on IUnknown methods.
473 static ULONG WINAPI EnumConnectionsImpl_AddRef(IEnumConnections* iface)
475 ICOM_THIS(EnumConnectionsImpl, iface);
476 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
478 IUnknown_AddRef(This->pUnk);
482 /************************************************************************
483 * EnumConnectionsImpl_Release (IUnknown)
485 * See Windows documentation for more details on IUnknown methods.
487 static ULONG WINAPI EnumConnectionsImpl_Release(IEnumConnections* iface)
489 ICOM_THIS(EnumConnectionsImpl, iface);
490 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
492 IUnknown_Release(This->pUnk);
495 * Decrease the reference count on this object.
500 * If the reference count goes down to 0, perform suicide.
504 EnumConnectionsImpl_Destroy(This);
512 /************************************************************************
513 * EnumConnectionsImpl_Next (IEnumConnections)
516 static HRESULT WINAPI EnumConnectionsImpl_Next(IEnumConnections* iface,
517 ULONG cConn, LPCONNECTDATA pCD,
520 ICOM_THIS(EnumConnectionsImpl, iface);
522 TRACE("(%p)->(%ld, %p, %p)\n", This, cConn, pCD, pEnum);
530 if(This->nCur >= This->nConns)
533 while(This->nCur < This->nConns && cConn) {
534 *pCD++ = This->pCD[This->nCur];
535 IUnknown_AddRef(This->pCD[This->nCur].pUnk);
548 /************************************************************************
549 * EnumConnectionsImpl_Skip (IEnumConnections)
552 static HRESULT WINAPI EnumConnectionsImpl_Skip(IEnumConnections* iface,
555 ICOM_THIS(EnumConnectionsImpl, iface);
556 TRACE("(%p)->(%ld)\n", This, cSkip);
558 if(This->nCur + cSkip >= This->nConns)
567 /************************************************************************
568 * EnumConnectionsImpl_Reset (IEnumConnections)
571 static HRESULT WINAPI EnumConnectionsImpl_Reset(IEnumConnections* iface)
573 ICOM_THIS(EnumConnectionsImpl, iface);
574 TRACE("(%p)\n", This);
582 /************************************************************************
583 * EnumConnectionsImpl_Clone (IEnumConnections)
586 static HRESULT WINAPI EnumConnectionsImpl_Clone(IEnumConnections* iface,
587 LPENUMCONNECTIONS *ppEnum)
589 ICOM_THIS(EnumConnectionsImpl, iface);
590 EnumConnectionsImpl *newObj;
591 TRACE("(%p)->(%p)\n", This, ppEnum);
593 newObj = EnumConnectionsImpl_Construct(This->pUnk, This->nConns, This->pCD);
594 newObj->nCur = This->nCur;
595 *ppEnum = (LPENUMCONNECTIONS)newObj;
596 IUnknown_AddRef(This->pUnk);
600 static IEnumConnectionsVtbl EnumConnectionsImpl_VTable =
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);