For a radio button even if the initial style includes WS_TABSTOP the
[wine/wine64.git] / dlls / oleaut32 / connpt.c
blob8026c83a7339b62a125bf05795dd0b2315c9619a
1 /*
2 * Implementation of a generic ConnectionPoint object.
4 * Copyright 2000 Huw D M Davies for CodeWeavers
6 * See one exported function here is CreateConnectionPoint, see
7 * comments just above that function for information.
8 */
10 #include <assert.h>
11 #include <string.h>
12 #include "winerror.h"
13 #include "winbase.h"
14 #include "wingdi.h"
15 #include "winuser.h"
16 #include "ole2.h"
17 #include "olectl.h"
18 #include "wine/obj_base.h"
19 #include "wine/obj_connection.h"
20 #include "connpt.h"
22 #include "debugtools.h"
24 DEFAULT_DEBUG_CHANNEL(ole);
26 #define MAXSINKS 10
28 /************************************************************************
29 * Implementation of IConnectionPoint
31 typedef struct ConnectionPointImpl {
33 ICOM_VTABLE(IConnectionPoint) *lpvtbl;
35 /* IUnknown of our main object*/
36 IUnknown *Obj;
38 /* Reference count */
39 DWORD ref;
41 /* IID of sink interface */
42 IID iid;
44 /* Array of sink IUnknowns */
45 IUnknown **sinks;
46 DWORD maxSinks;
48 DWORD nSinks;
49 } ConnectionPointImpl;
51 static ICOM_VTABLE(IConnectionPoint) ConnectionPointImpl_VTable;
54 /************************************************************************
55 * Implementation of IEnumConnections
57 typedef struct EnumConnectionsImpl {
59 ICOM_VTABLE(IEnumConnections) *lpvtbl;
61 DWORD ref;
63 /* IUnknown of ConnectionPoint, used for ref counting */
64 IUnknown *pUnk;
66 /* Connection Data */
67 CONNECTDATA *pCD;
68 DWORD nConns;
70 /* Next connection to enumerate from */
71 DWORD nCur;
73 } EnumConnectionsImpl;
75 static EnumConnectionsImpl *EnumConnectionsImpl_Construct(IUnknown *pUnk,
76 DWORD nSinks,
77 CONNECTDATA *pCD);
80 /************************************************************************
81 * ConnectionPointImpl_Construct
83 static ConnectionPointImpl *ConnectionPointImpl_Construct(IUnknown *pUnk,
84 REFIID riid)
86 ConnectionPointImpl *Obj;
88 Obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*Obj));
89 Obj->lpvtbl = &ConnectionPointImpl_VTable;
90 Obj->Obj = pUnk;
91 Obj->ref = 1;
92 Obj->iid = *riid;
93 Obj->maxSinks = MAXSINKS;
94 Obj->sinks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
95 sizeof(IUnknown*) * MAXSINKS);
96 Obj->nSinks = 0;
97 return Obj;
100 /************************************************************************
101 * ConnectionPointImpl_Destroy
103 static void ConnectionPointImpl_Destroy(ConnectionPointImpl *Obj)
105 DWORD i;
106 for(i = 0; i < Obj->maxSinks; i++) {
107 if(Obj->sinks[i]) {
108 IUnknown_Release(Obj->sinks[i]);
109 Obj->sinks[i] = NULL;
112 HeapFree(GetProcessHeap(), 0, Obj->sinks);
113 HeapFree(GetProcessHeap(), 0, Obj);
114 return;
117 static ULONG WINAPI ConnectionPointImpl_AddRef(IConnectionPoint* iface);
118 /************************************************************************
119 * ConnectionPointImpl_QueryInterface (IUnknown)
121 * See Windows documentation for more details on IUnknown methods.
123 static HRESULT WINAPI ConnectionPointImpl_QueryInterface(
124 IConnectionPoint* iface,
125 REFIID riid,
126 void** ppvObject)
128 ICOM_THIS(ConnectionPointImpl, iface);
129 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
132 * Perform a sanity check on the parameters.
134 if ( (This==0) || (ppvObject==0) )
135 return E_INVALIDARG;
138 * Initialize the return parameter.
140 *ppvObject = 0;
143 * Compare the riid with the interface IDs implemented by this object.
145 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
147 *ppvObject = (IConnectionPoint*)This;
149 else if (memcmp(&IID_IConnectionPoint, riid, sizeof(IID_IConnectionPoint)) == 0)
151 *ppvObject = (IConnectionPoint*)This;
155 * Check that we obtained an interface.
157 if ((*ppvObject)==0)
159 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
160 return E_NOINTERFACE;
164 * Query Interface always increases the reference count by one when it is
165 * successful
167 ConnectionPointImpl_AddRef((IConnectionPoint*)This);
169 return S_OK;;
173 /************************************************************************
174 * ConnectionPointImpl_AddRef (IUnknown)
176 * See Windows documentation for more details on IUnknown methods.
178 static ULONG WINAPI ConnectionPointImpl_AddRef(IConnectionPoint* iface)
180 ICOM_THIS(ConnectionPointImpl, iface);
181 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
182 This->ref++;
184 return This->ref;
187 /************************************************************************
188 * ConnectionPointImpl_Release (IUnknown)
190 * See Windows documentation for more details on IUnknown methods.
192 static ULONG WINAPI ConnectionPointImpl_Release(
193 IConnectionPoint* iface)
195 ICOM_THIS(ConnectionPointImpl, iface);
196 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
199 * Decrease the reference count on this object.
201 This->ref--;
204 * If the reference count goes down to 0, perform suicide.
206 if (This->ref==0)
208 ConnectionPointImpl_Destroy(This);
210 return 0;
213 return This->ref;
216 /************************************************************************
217 * ConnectionPointImpl_GetConnectionInterface (IConnectionPoint)
220 static HRESULT WINAPI ConnectionPointImpl_GetConnectionInterface(
221 IConnectionPoint *iface,
222 IID *piid)
224 ICOM_THIS(ConnectionPointImpl, iface);
225 TRACE("(%p)->(%p) returning %s\n", This, piid, debugstr_guid(&(This->iid)));
226 *piid = This->iid;
227 return S_OK;
230 /************************************************************************
231 * ConnectionPointImpl_GetConnectionPointContainer (IConnectionPoint)
234 static HRESULT WINAPI ConnectionPointImpl_GetConnectionPointContainer(
235 IConnectionPoint *iface,
236 IConnectionPointContainer **ppCPC)
238 ICOM_THIS(ConnectionPointImpl, iface);
239 TRACE("(%p)->(%p)\n", This, ppCPC);
241 return IUnknown_QueryInterface(This->Obj,
242 &IID_IConnectionPointContainer,
243 (LPVOID)ppCPC);
246 /************************************************************************
247 * ConnectionPointImpl_Advise (IConnectionPoint)
250 static HRESULT WINAPI ConnectionPointImpl_Advise(IConnectionPoint *iface,
251 IUnknown *lpUnk,
252 DWORD *pdwCookie)
254 DWORD i;
255 ICOM_THIS(ConnectionPointImpl, iface);
256 IUnknown *lpSink;
257 TRACE("(%p)->(%p, %p)\n", This, lpUnk, pdwCookie);
259 *pdwCookie = 0;
260 if(FAILED(IUnknown_QueryInterface(lpUnk, &This->iid, (LPVOID)&lpSink)))
261 return CONNECT_E_CANNOTCONNECT;
263 for(i = 0; i < This->maxSinks; i++) {
264 if(This->sinks[i] == NULL)
265 break;
267 if(i == This->maxSinks) {
268 This->maxSinks += MAXSINKS;
269 This->sinks = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->sinks,
270 This->maxSinks * sizeof(IUnknown *));
272 This->sinks[i] = lpSink;
273 This->nSinks++;
274 *pdwCookie = i + 1;
275 return S_OK;
279 /************************************************************************
280 * ConnectionPointImpl_Unadvise (IConnectionPoint)
283 static HRESULT WINAPI ConnectionPointImpl_Unadvise(IConnectionPoint *iface,
284 DWORD dwCookie)
286 ICOM_THIS(ConnectionPointImpl, iface);
287 TRACE("(%p)->(%ld)\n", This, dwCookie);
289 if(dwCookie == 0 || dwCookie > This->maxSinks) return E_INVALIDARG;
291 if(This->sinks[dwCookie-1] == NULL) return CONNECT_E_NOCONNECTION;
293 IUnknown_Release(This->sinks[dwCookie-1]);
294 This->sinks[dwCookie-1] = NULL;
295 This->nSinks--;
296 return S_OK;
299 /************************************************************************
300 * ConnectionPointImpl_EnumConnections (IConnectionPoint)
303 static HRESULT WINAPI ConnectionPointImpl_EnumConnections(
304 IConnectionPoint *iface,
305 LPENUMCONNECTIONS *ppEnum)
307 ICOM_THIS(ConnectionPointImpl, iface);
308 CONNECTDATA *pCD;
309 DWORD i, nextslot;
310 EnumConnectionsImpl *EnumObj;
311 HRESULT hr;
313 TRACE("(%p)->(%p)\n", This, ppEnum);
315 *ppEnum = NULL;
317 if(This->nSinks == 0) return OLE_E_NOCONNECTION;
319 pCD = HeapAlloc(GetProcessHeap(), 0, sizeof(CONNECTDATA) * This->nSinks);
321 for(i = 0, nextslot = 0; i < This->maxSinks; i++) {
322 if(This->sinks[i] != NULL) {
323 pCD[nextslot].pUnk = This->sinks[i];
324 pCD[nextslot].dwCookie = i + 1;
325 nextslot++;
328 assert(nextslot == This->nSinks);
330 /* Bump the ref count of this object up by one. It gets Released in
331 IEnumConnections_Release */
332 IUnknown_AddRef((IUnknown*)This);
334 EnumObj = EnumConnectionsImpl_Construct((IUnknown*)This, This->nSinks, pCD);
335 hr = IEnumConnections_QueryInterface((IEnumConnections*)EnumObj,
336 &IID_IEnumConnections, (LPVOID)ppEnum);
337 IEnumConnections_Release((IEnumConnections*)EnumObj);
339 HeapFree(GetProcessHeap(), 0, pCD);
340 return hr;
343 static ICOM_VTABLE(IConnectionPoint) ConnectionPointImpl_VTable =
345 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
346 ConnectionPointImpl_QueryInterface,
347 ConnectionPointImpl_AddRef,
348 ConnectionPointImpl_Release,
349 ConnectionPointImpl_GetConnectionInterface,
350 ConnectionPointImpl_GetConnectionPointContainer,
351 ConnectionPointImpl_Advise,
352 ConnectionPointImpl_Unadvise,
353 ConnectionPointImpl_EnumConnections
357 static ICOM_VTABLE(IEnumConnections) EnumConnectionsImpl_VTable;
358 static ULONG WINAPI EnumConnectionsImpl_AddRef(IEnumConnections* iface);
360 /************************************************************************
361 * EnumConnectionsImpl_Construct
363 static EnumConnectionsImpl *EnumConnectionsImpl_Construct(IUnknown *pUnk,
364 DWORD nSinks,
365 CONNECTDATA *pCD)
367 EnumConnectionsImpl *Obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*Obj));
368 DWORD i;
370 Obj->lpvtbl = &EnumConnectionsImpl_VTable;
371 Obj->ref = 1;
372 Obj->pUnk = pUnk;
373 Obj->pCD = HeapAlloc(GetProcessHeap(), 0, nSinks * sizeof(CONNECTDATA));
374 Obj->nConns = nSinks;
375 Obj->nCur = 0;
377 for(i = 0; i < nSinks; i++) {
378 Obj->pCD[i] = pCD[i];
379 IUnknown_AddRef(Obj->pCD[i].pUnk);
381 return Obj;
384 /************************************************************************
385 * EnumConnectionsImpl_Destroy
387 static void EnumConnectionsImpl_Destroy(EnumConnectionsImpl *Obj)
389 DWORD i;
391 for(i = 0; i < Obj->nConns; i++)
392 IUnknown_Release(Obj->pCD[i].pUnk);
394 HeapFree(GetProcessHeap(), 0, Obj->pCD);
395 HeapFree(GetProcessHeap(), 0, Obj);
396 return;
399 /************************************************************************
400 * EnumConnectionsImpl_QueryInterface (IUnknown)
402 * See Windows documentation for more details on IUnknown methods.
404 static HRESULT WINAPI EnumConnectionsImpl_QueryInterface(
405 IEnumConnections* iface,
406 REFIID riid,
407 void** ppvObject)
409 ICOM_THIS(ConnectionPointImpl, iface);
410 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
413 * Perform a sanity check on the parameters.
415 if ( (This==0) || (ppvObject==0) )
416 return E_INVALIDARG;
419 * Initialize the return parameter.
421 *ppvObject = 0;
424 * Compare the riid with the interface IDs implemented by this object.
426 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
428 *ppvObject = (IEnumConnections*)This;
430 else if (memcmp(&IID_IEnumConnections, riid, sizeof(IID_IEnumConnections)) == 0)
432 *ppvObject = (IEnumConnections*)This;
436 * Check that we obtained an interface.
438 if ((*ppvObject)==0)
440 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
441 return E_NOINTERFACE;
445 * Query Interface always increases the reference count by one when it is
446 * successful
448 EnumConnectionsImpl_AddRef((IEnumConnections*)This);
450 return S_OK;;
454 /************************************************************************
455 * EnumConnectionsImpl_AddRef (IUnknown)
457 * See Windows documentation for more details on IUnknown methods.
459 static ULONG WINAPI EnumConnectionsImpl_AddRef(IEnumConnections* iface)
461 ICOM_THIS(EnumConnectionsImpl, iface);
462 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
463 This->ref++;
464 IUnknown_AddRef(This->pUnk);
465 return This->ref;
468 /************************************************************************
469 * EnumConnectionsImpl_Release (IUnknown)
471 * See Windows documentation for more details on IUnknown methods.
473 static ULONG WINAPI EnumConnectionsImpl_Release(IEnumConnections* iface)
475 ICOM_THIS(EnumConnectionsImpl, iface);
476 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
478 IUnknown_Release(This->pUnk);
481 * Decrease the reference count on this object.
483 This->ref--;
486 * If the reference count goes down to 0, perform suicide.
488 if (This->ref==0)
490 EnumConnectionsImpl_Destroy(This);
492 return 0;
495 return This->ref;
498 /************************************************************************
499 * EnumConnectionsImpl_Next (IEnumConnections)
502 static HRESULT WINAPI EnumConnectionsImpl_Next(IEnumConnections* iface,
503 ULONG cConn, LPCONNECTDATA pCD,
504 ULONG *pEnum)
506 ICOM_THIS(EnumConnectionsImpl, iface);
507 DWORD nRet = 0;
508 TRACE("(%p)->(%ld, %p, %p)\n", This, cConn, pCD, pEnum);
510 if(pEnum == NULL) {
511 if(cConn != 1)
512 return E_POINTER;
513 } else
514 *pEnum = 0;
516 if(This->nCur >= This->nConns)
517 return S_FALSE;
519 while(This->nCur < This->nConns && cConn) {
520 *pCD++ = This->pCD[This->nCur];
521 IUnknown_AddRef(This->pCD[This->nCur].pUnk);
522 This->nCur++;
523 cConn--;
524 nRet++;
527 if(pEnum)
528 *pEnum = nRet;
530 return S_OK;
534 /************************************************************************
535 * EnumConnectionsImpl_Skip (IEnumConnections)
538 static HRESULT WINAPI EnumConnectionsImpl_Skip(IEnumConnections* iface,
539 ULONG cSkip)
541 ICOM_THIS(EnumConnectionsImpl, iface);
542 TRACE("(%p)->(%ld)\n", This, cSkip);
544 if(This->nCur + cSkip >= This->nConns)
545 return S_FALSE;
547 This->nCur += cSkip;
549 return S_OK;
553 /************************************************************************
554 * EnumConnectionsImpl_Reset (IEnumConnections)
557 static HRESULT WINAPI EnumConnectionsImpl_Reset(IEnumConnections* iface)
559 ICOM_THIS(EnumConnectionsImpl, iface);
560 TRACE("(%p)\n", This);
562 This->nCur = 0;
564 return S_OK;
568 /************************************************************************
569 * EnumConnectionsImpl_Clone (IEnumConnections)
572 static HRESULT WINAPI EnumConnectionsImpl_Clone(IEnumConnections* iface,
573 LPENUMCONNECTIONS *ppEnum)
575 ICOM_THIS(EnumConnectionsImpl, iface);
576 EnumConnectionsImpl *newObj;
577 TRACE("(%p)->(%p)\n", This, ppEnum);
579 newObj = EnumConnectionsImpl_Construct(This->pUnk, This->nConns, This->pCD);
580 newObj->nCur = This->nCur;
581 *ppEnum = (LPENUMCONNECTIONS)newObj;
582 IUnknown_AddRef(This->pUnk);
583 return S_OK;
586 static ICOM_VTABLE(IEnumConnections) EnumConnectionsImpl_VTable =
588 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
589 EnumConnectionsImpl_QueryInterface,
590 EnumConnectionsImpl_AddRef,
591 EnumConnectionsImpl_Release,
592 EnumConnectionsImpl_Next,
593 EnumConnectionsImpl_Skip,
594 EnumConnectionsImpl_Reset,
595 EnumConnectionsImpl_Clone
598 /************************************************************************
600 * The exported function to create the connection point.
601 * NB not a windows API
603 * PARAMS
604 * pUnk [in] IUnknown of object to which the ConnectionPoint is associated.
605 * Needed to access IConnectionPointContainer.
607 * riid [in] IID of sink interface that this ConnectionPoint manages
609 * pCP [out] returns IConnectionPoint
612 HRESULT CreateConnectionPoint(IUnknown *pUnk, REFIID riid,
613 IConnectionPoint **pCP)
615 ConnectionPointImpl *Obj;
616 HRESULT hr;
618 Obj = ConnectionPointImpl_Construct(pUnk, riid);
619 if(!Obj) return E_OUTOFMEMORY;
621 hr = IConnectionPoint_QueryInterface((IConnectionPoint *)Obj,
622 &IID_IConnectionPoint, (LPVOID)pCP);
623 IConnectionPoint_Release((IConnectionPoint *)Obj);
624 return hr;