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

Last change on this file since 5280 was 4837, checked in by sandervl, 25 years ago

merged with Wine 12-22-2000

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