1 /*
2 * Implementation of a generic ConnectionPoint object.
3 *
4 * Copyright 2000 Huw D M Davies for CodeWeavers
5 *
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.
10 *
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.
15 *
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
19 *
20 * NOTES:
21 * See one exported function here is CreateConnectionPoint, see
22 * comments just above that function for information.
23 */
24
25 #include <assert.h>
26 #include <stdarg.h>
27 #include <string.h>
28
29 #define COBJMACROS
30
31 #include "winerror.h"
32 #include "windef.h"
33 #include "winbase.h"
34 #include "wingdi.h"
35 #include "winuser.h"
36 #include "ole2.h"
37 #include "olectl.h"
38 #include "connpt.h"
39
40 #include "wine/debug.h"
41
42 WINE_DEFAULT_DEBUG_CHANNEL(ole);
43
44 #define MAXSINKS 10
45
46 /************************************************************************
47 * Implementation of IConnectionPoint
48 */
49 typedef struct ConnectionPointImpl {
50
51 IConnectionPoint IConnectionPoint_iface;
52
53 /* IUnknown of our main object*/
54 IUnknown *Obj;
55
56 /* Reference count */
57 LONG ref;
58
59 /* IID of sink interface */
60 IID iid;
61
62 /* Array of sink IUnknowns */
63 IUnknown **sinks;
64 DWORD maxSinks;
65
66 DWORD nSinks;
67 } ConnectionPointImpl;
68
69 static const IConnectionPointVtbl ConnectionPointImpl_VTable;
70
71
72 /************************************************************************
73 * Implementation of IEnumConnections
74 */
75 typedef struct EnumConnectionsImpl {
76
77 IEnumConnections IEnumConnections_iface;
78
79 LONG ref;
80
81 /* IUnknown of ConnectionPoint, used for ref counting */
82 IUnknown *pUnk;
83
84 /* Connection Data */
85 CONNECTDATA *pCD;
86 DWORD nConns;
87
88 /* Next connection to enumerate from */
89 DWORD nCur;
90
91 } EnumConnectionsImpl;
92
93 static EnumConnectionsImpl *EnumConnectionsImpl_Construct(IUnknown *pUnk,
94 DWORD nSinks,
95 CONNECTDATA *pCD);
96
97 static inline ConnectionPointImpl *impl_from_IConnectionPoint(IConnectionPoint *iface)
98 {
99 return CONTAINING_RECORD(iface, ConnectionPointImpl, IConnectionPoint_iface);
100 }
101
102 static inline EnumConnectionsImpl *impl_from_IEnumConnections(IEnumConnections *iface)
103 {
104 return CONTAINING_RECORD(iface, EnumConnectionsImpl, IEnumConnections_iface);
105 }
106
107 /************************************************************************
108 * ConnectionPointImpl_Construct
109 */
110 static ConnectionPointImpl *ConnectionPointImpl_Construct(IUnknown *pUnk,
111 REFIID riid)
112 {
113 ConnectionPointImpl *Obj;
114
115 Obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*Obj));
116 Obj->IConnectionPoint_iface.lpVtbl = &ConnectionPointImpl_VTable;
117 Obj->Obj = pUnk;
118 Obj->ref = 1;
119 Obj->iid = *riid;
120 Obj->maxSinks = MAXSINKS;
121 Obj->sinks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
122 sizeof(IUnknown*) * MAXSINKS);
123 Obj->nSinks = 0;
124 return Obj;
125 }
126
127 /************************************************************************
128 * ConnectionPointImpl_Destroy
129 */
130 static void ConnectionPointImpl_Destroy(ConnectionPointImpl *Obj)
131 {
132 DWORD i;
133 for(i = 0; i < Obj->maxSinks; i++) {
134 if(Obj->sinks[i]) {
135 IUnknown_Release(Obj->sinks[i]);
136 Obj->sinks[i] = NULL;
137 }
138 }
139 HeapFree(GetProcessHeap(), 0, Obj->sinks);
140 HeapFree(GetProcessHeap(), 0, Obj);
141 return;
142 }
143
144 static ULONG WINAPI ConnectionPointImpl_AddRef(IConnectionPoint* iface);
145 /************************************************************************
146 * ConnectionPointImpl_QueryInterface (IUnknown)
147 *
148 * See Windows documentation for more details on IUnknown methods.
149 */
150 static HRESULT WINAPI ConnectionPointImpl_QueryInterface(
151 IConnectionPoint* iface,
152 REFIID riid,
153 void** ppvObject)
154 {
155 ConnectionPointImpl *This = impl_from_IConnectionPoint(iface);
156 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
157
158 /*
159 * Perform a sanity check on the parameters.
160 */
161 if ( (This==0) || (ppvObject==0) )
162 return E_INVALIDARG;
163
164 /*
165 * Initialize the return parameter.
166 */
167 *ppvObject = 0;
168
169 /*
170 * Compare the riid with the interface IDs implemented by this object.
171 */
172 if (IsEqualIID(&IID_IUnknown, riid))
173 *ppvObject = This;
174 else if (IsEqualIID(&IID_IConnectionPoint, riid))
175 *ppvObject = This;
176
177 /*
178 * Check that we obtained an interface.
179 */
180 if ((*ppvObject)==0)
181 {
182 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
183 return E_NOINTERFACE;
184 }
185
186 /*
187 * Query Interface always increases the reference count by one when it is
188 * successful
189 */
190 ConnectionPointImpl_AddRef(&This->IConnectionPoint_iface);
191
192 return S_OK;
193 }
194
195
196 /************************************************************************
197 * ConnectionPointImpl_AddRef (IUnknown)
198 *
199 * See Windows documentation for more details on IUnknown methods.
200 */
201 static ULONG WINAPI ConnectionPointImpl_AddRef(IConnectionPoint* iface)
202 {
203 ConnectionPointImpl *This = impl_from_IConnectionPoint(iface);
204 ULONG refCount = InterlockedIncrement(&This->ref);
205
206 TRACE("(%p)->(ref before=%d)\n", This, refCount - 1);
207
208 return refCount;
209 }
210
211 /************************************************************************
212 * ConnectionPointImpl_Release (IUnknown)
213 *
214 * See Windows documentation for more details on IUnknown methods.
215 */
216 static ULONG WINAPI ConnectionPointImpl_Release(
217 IConnectionPoint* iface)
218 {
219 ConnectionPointImpl *This = impl_from_IConnectionPoint(iface);
220 ULONG refCount = InterlockedDecrement(&This->ref);
221
222 TRACE("(%p)->(ref before=%d)\n", This, refCount + 1);
223
224 /*
225 * If the reference count goes down to 0, perform suicide.
226 */
227 if (!refCount) ConnectionPointImpl_Destroy(This);
228
229 return refCount;
230 }
231
232 /************************************************************************
233 * ConnectionPointImpl_GetConnectionInterface (IConnectionPoint)
234 *
235 */
236 static HRESULT WINAPI ConnectionPointImpl_GetConnectionInterface(
237 IConnectionPoint *iface,
238 IID *piid)
239 {
240 ConnectionPointImpl *This = impl_from_IConnectionPoint(iface);
241 TRACE("(%p)->(%p) returning %s\n", This, piid, debugstr_guid(&(This->iid)));
242 *piid = This->iid;
243 return S_OK;
244 }
245
246 /************************************************************************
247 * ConnectionPointImpl_GetConnectionPointContainer (IConnectionPoint)
248 *
249 */
250 static HRESULT WINAPI ConnectionPointImpl_GetConnectionPointContainer(
251 IConnectionPoint *iface,
252 IConnectionPointContainer **ppCPC)
253 {
254 ConnectionPointImpl *This = impl_from_IConnectionPoint(iface);
255 TRACE("(%p)->(%p)\n", This, ppCPC);
256
257 return IUnknown_QueryInterface(This->Obj,
258 &IID_IConnectionPointContainer,
259 (LPVOID)ppCPC);
260 }
261
262 /************************************************************************
263 * ConnectionPointImpl_Advise (IConnectionPoint)
264 *
265 */
266 static HRESULT WINAPI ConnectionPointImpl_Advise(IConnectionPoint *iface,
267 IUnknown *lpUnk,
268 DWORD *pdwCookie)
269 {
270 DWORD i;
271 ConnectionPointImpl *This = impl_from_IConnectionPoint(iface);
272 IUnknown *lpSink;
273 TRACE("(%p)->(%p, %p)\n", This, lpUnk, pdwCookie);
274
275 *pdwCookie = 0;
276 if(FAILED(IUnknown_QueryInterface(lpUnk, &This->iid, (LPVOID)&lpSink)))
277 return CONNECT_E_CANNOTCONNECT;
278
279 for(i = 0; i < This->maxSinks; i++) {
280 if(This->sinks[i] == NULL)
281 break;
282 }
283 if(i == This->maxSinks) {
284 This->maxSinks += MAXSINKS;
285 This->sinks = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->sinks,
286 This->maxSinks * sizeof(IUnknown *));
287 }
288 This->sinks[i] = lpSink;
289 This->nSinks++;
290 *pdwCookie = i + 1;
291 return S_OK;
292 }
293
294
295 /************************************************************************
296 * ConnectionPointImpl_Unadvise (IConnectionPoint)
297 *
298 */
299 static HRESULT WINAPI ConnectionPointImpl_Unadvise(IConnectionPoint *iface,
300 DWORD dwCookie)
301 {
302 ConnectionPointImpl *This = impl_from_IConnectionPoint(iface);
303 TRACE("(%p)->(%d)\n", This, dwCookie);
304
305 if(dwCookie == 0 || dwCookie > This->maxSinks) return E_INVALIDARG;
306
307 if(This->sinks[dwCookie-1] == NULL) return CONNECT_E_NOCONNECTION;
308
309 IUnknown_Release(This->sinks[dwCookie-1]);
310 This->sinks[dwCookie-1] = NULL;
311 This->nSinks--;
312 return S_OK;
313 }
314
315 /************************************************************************
316 * ConnectionPointImpl_EnumConnections (IConnectionPoint)
317 *
318 */
319 static HRESULT WINAPI ConnectionPointImpl_EnumConnections(
320 IConnectionPoint *iface,
321 LPENUMCONNECTIONS *ppEnum)
322 {
323 ConnectionPointImpl *This = impl_from_IConnectionPoint(iface);
324 CONNECTDATA *pCD;
325 DWORD i, nextslot;
326 EnumConnectionsImpl *EnumObj;
327 HRESULT hr;
328
329 TRACE("(%p)->(%p)\n", This, ppEnum);
330
331 *ppEnum = NULL;
332
333 if(This->nSinks == 0) return OLE_E_NOCONNECTION;
334
335 pCD = HeapAlloc(GetProcessHeap(), 0, sizeof(CONNECTDATA) * This->nSinks);
336
337 for(i = 0, nextslot = 0; i < This->maxSinks; i++) {
338 if(This->sinks[i] != NULL) {
339 pCD[nextslot].pUnk = This->sinks[i];
340 pCD[nextslot].dwCookie = i + 1;
341 nextslot++;
342 }
343 }
344 assert(nextslot == This->nSinks);
345
346 /* Bump the ref count of this object up by one. It gets Released in
347 IEnumConnections_Release */
348 IUnknown_AddRef((IUnknown*)This);
349
350 EnumObj = EnumConnectionsImpl_Construct((IUnknown*)This, This->nSinks, pCD);
351 hr = IEnumConnections_QueryInterface(&EnumObj->IEnumConnections_iface,
352 &IID_IEnumConnections, (LPVOID)ppEnum);
353 IEnumConnections_Release(&EnumObj->IEnumConnections_iface);
354
355 HeapFree(GetProcessHeap(), 0, pCD);
356 return hr;
357 }
358
359 static const IConnectionPointVtbl ConnectionPointImpl_VTable =
360 {
361 ConnectionPointImpl_QueryInterface,
362 ConnectionPointImpl_AddRef,
363 ConnectionPointImpl_Release,
364 ConnectionPointImpl_GetConnectionInterface,
365 ConnectionPointImpl_GetConnectionPointContainer,
366 ConnectionPointImpl_Advise,
367 ConnectionPointImpl_Unadvise,
368 ConnectionPointImpl_EnumConnections
369 };
370
371
372 static const IEnumConnectionsVtbl EnumConnectionsImpl_VTable;
373 static ULONG WINAPI EnumConnectionsImpl_AddRef(IEnumConnections* iface);
374
375 /************************************************************************
376 * EnumConnectionsImpl_Construct
377 */
378 static EnumConnectionsImpl *EnumConnectionsImpl_Construct(IUnknown *pUnk,
379 DWORD nSinks,
380 CONNECTDATA *pCD)
381 {
382 EnumConnectionsImpl *Obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*Obj));
383 DWORD i;
384
385 Obj->IEnumConnections_iface.lpVtbl = &EnumConnectionsImpl_VTable;
386 Obj->ref = 1;
387 Obj->pUnk = pUnk;
388 Obj->pCD = HeapAlloc(GetProcessHeap(), 0, nSinks * sizeof(CONNECTDATA));
389 Obj->nConns = nSinks;
390 Obj->nCur = 0;
391
392 for(i = 0; i < nSinks; i++) {
393 Obj->pCD[i] = pCD[i];
394 IUnknown_AddRef(Obj->pCD[i].pUnk);
395 }
396 return Obj;
397 }
398
399 /************************************************************************
400 * EnumConnectionsImpl_Destroy
401 */
402 static void EnumConnectionsImpl_Destroy(EnumConnectionsImpl *Obj)
403 {
404 DWORD i;
405
406 for(i = 0; i < Obj->nConns; i++)
407 IUnknown_Release(Obj->pCD[i].pUnk);
408
409 HeapFree(GetProcessHeap(), 0, Obj->pCD);
410 HeapFree(GetProcessHeap(), 0, Obj);
411 return;
412 }
413
414 /************************************************************************
415 * EnumConnectionsImpl_QueryInterface (IUnknown)
416 *
417 * See Windows documentation for more details on IUnknown methods.
418 */
419 static HRESULT WINAPI EnumConnectionsImpl_QueryInterface(
420 IEnumConnections* iface,
421 REFIID riid,
422 void** ppvObject)
423 {
424 ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
425 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
426
427 /*
428 * Perform a sanity check on the parameters.
429 */
430 if ( (This==0) || (ppvObject==0) )
431 return E_INVALIDARG;
432
433 /*
434 * Initialize the return parameter.
435 */
436 *ppvObject = 0;
437
438 /*
439 * Compare the riid with the interface IDs implemented by this object.
440 */
441 if (IsEqualIID(&IID_IUnknown, riid))
442 *ppvObject = This;
443 else if (IsEqualIID(&IID_IEnumConnections, riid))
444 *ppvObject = This;
445
446 /*
447 * Check that we obtained an interface.
448 */
449 if ((*ppvObject)==0)
450 {
451 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
452 return E_NOINTERFACE;
453 }
454
455 /*
456 * Query Interface always increases the reference count by one when it is
457 * successful
458 */
459 EnumConnectionsImpl_AddRef((IEnumConnections*)This);
460
461 return S_OK;
462 }
463
464
465 /************************************************************************
466 * EnumConnectionsImpl_AddRef (IUnknown)
467 *
468 * See Windows documentation for more details on IUnknown methods.
469 */
470 static ULONG WINAPI EnumConnectionsImpl_AddRef(IEnumConnections* iface)
471 {
472 EnumConnectionsImpl *This = impl_from_IEnumConnections(iface);
473 ULONG refCount = InterlockedIncrement(&This->ref);
474
475 TRACE("(%p)->(ref before=%d)\n", This, refCount - 1);
476
477 IUnknown_AddRef(This->pUnk);
478 return refCount;
479 }
480
481 /************************************************************************
482 * EnumConnectionsImpl_Release (IUnknown)
483 *
484 * See Windows documentation for more details on IUnknown methods.
485 */
486 static ULONG WINAPI EnumConnectionsImpl_Release(IEnumConnections* iface)
487 {
488 EnumConnectionsImpl *This = impl_from_IEnumConnections(iface);
489 ULONG refCount = InterlockedDecrement(&This->ref);
490
491 TRACE("(%p)->(ref before=%d)\n", This, refCount + 1);
492
493 IUnknown_Release(This->pUnk);
494
495 /*
496 * If the reference count goes down to 0, perform suicide.
497 */
498 if (!refCount) EnumConnectionsImpl_Destroy(This);
499
500 return refCount;
501 }
502
503 /************************************************************************
504 * EnumConnectionsImpl_Next (IEnumConnections)
505 *
506 */
507 static HRESULT WINAPI EnumConnectionsImpl_Next(IEnumConnections* iface,
508 ULONG cConn, LPCONNECTDATA pCD,
509 ULONG *pEnum)
510 {
511 EnumConnectionsImpl *This = impl_from_IEnumConnections(iface);
512 DWORD nRet = 0;
513 TRACE("(%p)->(%d, %p, %p)\n", This, cConn, pCD, pEnum);
514
515 if(pEnum == NULL) {
516 if(cConn != 1)
517 return E_POINTER;
518 } else
519 *pEnum = 0;
520
521 if(This->nCur >= This->nConns)
522 return S_FALSE;
523
524 while(This->nCur < This->nConns && cConn) {
525 *pCD++ = This->pCD[This->nCur];
526 IUnknown_AddRef(This->pCD[This->nCur].pUnk);
527 This->nCur++;
528 cConn--;
529 nRet++;
530 }
531
532 if(pEnum)
533 *pEnum = nRet;
534
535 return S_OK;
536 }
537
538
539 /************************************************************************
540 * EnumConnectionsImpl_Skip (IEnumConnections)
541 *
542 */
543 static HRESULT WINAPI EnumConnectionsImpl_Skip(IEnumConnections* iface,
544 ULONG cSkip)
545 {
546 EnumConnectionsImpl *This = impl_from_IEnumConnections(iface);
547 TRACE("(%p)->(%d)\n", This, cSkip);
548
549 if(This->nCur + cSkip >= This->nConns)
550 return S_FALSE;
551
552 This->nCur += cSkip;
553
554 return S_OK;
555 }
556
557
558 /************************************************************************
559 * EnumConnectionsImpl_Reset (IEnumConnections)
560 *
561 */
562 static HRESULT WINAPI EnumConnectionsImpl_Reset(IEnumConnections* iface)
563 {
564 EnumConnectionsImpl *This = impl_from_IEnumConnections(iface);
565 TRACE("(%p)\n", This);
566
567 This->nCur = 0;
568
569 return S_OK;
570 }
571
572
573 /************************************************************************
574 * EnumConnectionsImpl_Clone (IEnumConnections)
575 *
576 */
577 static HRESULT WINAPI EnumConnectionsImpl_Clone(IEnumConnections* iface,
578 LPENUMCONNECTIONS *ppEnum)
579 {
580 EnumConnectionsImpl *This = impl_from_IEnumConnections(iface);
581 EnumConnectionsImpl *newObj;
582 TRACE("(%p)->(%p)\n", This, ppEnum);
583
584 newObj = EnumConnectionsImpl_Construct(This->pUnk, This->nConns, This->pCD);
585 newObj->nCur = This->nCur;
586 *ppEnum = (LPENUMCONNECTIONS)newObj;
587 IUnknown_AddRef(This->pUnk);
588 return S_OK;
589 }
590
591 static const IEnumConnectionsVtbl EnumConnectionsImpl_VTable =
592 {
593 EnumConnectionsImpl_QueryInterface,
594 EnumConnectionsImpl_AddRef,
595 EnumConnectionsImpl_Release,
596 EnumConnectionsImpl_Next,
597 EnumConnectionsImpl_Skip,
598 EnumConnectionsImpl_Reset,
599 EnumConnectionsImpl_Clone
600 };
601
602 /************************************************************************
603 *
604 * The exported function to create the connection point.
605 * NB not a windows API
606 *
607 * PARAMS
608 * pUnk [in] IUnknown of object to which the ConnectionPoint is associated.
609 * Needed to access IConnectionPointContainer.
610 *
611 * riid [in] IID of sink interface that this ConnectionPoint manages
612 *
613 * pCP [out] returns IConnectionPoint
614 *
615 */
616 HRESULT CreateConnectionPoint(IUnknown *pUnk, REFIID riid,
617 IConnectionPoint **pCP)
618 {
619 ConnectionPointImpl *Obj;
620 HRESULT hr;
621
622 Obj = ConnectionPointImpl_Construct(pUnk, riid);
623 if(!Obj) return E_OUTOFMEMORY;
624
625 hr = IConnectionPoint_QueryInterface(&Obj->IConnectionPoint_iface,
626 &IID_IConnectionPoint, (LPVOID)pCP);
627 IConnectionPoint_Release(&Obj->IConnectionPoint_iface);
628 return hr;
629 }
630
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.