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

Last change on this file since 10367 was 8450, checked in by sandervl, 23 years ago

Wine resync

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