source: trunk/src/oleaut32/connpt.c@ 6648

Last change on this file since 6648 was 6648, checked in by bird, 24 years ago

Added $Id:$ keyword.

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