Fixed some issues found by winapi_check.
[wine/dcerpc.git] / dlls / oleaut32 / connpt.c
blobfe99c985954caedab8fe191b301eedb682b5f7ce
1 /*
2 * Implementation of a generic ConnectionPoint object.
4 * Copyright 2000 Huw D M Davies for CodeWeavers
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.
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.
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
20 * NOTES:
21 * See one exported function here is CreateConnectionPoint, see
22 * comments just above that function for information.
25 #include <assert.h>
26 #include <string.h>
27 #include "winerror.h"
28 #include "winbase.h"
29 #include "wingdi.h"
30 #include "winuser.h"
31 #include "ole2.h"
32 #include "olectl.h"
33 #include "wine/obj_base.h"
34 #include "wine/obj_connection.h"
35 #include "connpt.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(ole);
41 #define MAXSINKS 10
43 /************************************************************************
44 * Implementation of IConnectionPoint
46 typedef struct ConnectionPointImpl {
48 ICOM_VTABLE(IConnectionPoint) *lpvtbl;
50 /* IUnknown of our main object*/
51 IUnknown *Obj;
53 /* Reference count */
54 DWORD ref;
56 /* IID of sink interface */
57 IID iid;
59 /* Array of sink IUnknowns */
60 IUnknown **sinks;
61 DWORD maxSinks;
63 DWORD nSinks;
64 } ConnectionPointImpl;
66 static ICOM_VTABLE(IConnectionPoint) ConnectionPointImpl_VTable;
69 /************************************************************************
70 * Implementation of IEnumConnections
72 typedef struct EnumConnectionsImpl {
74 ICOM_VTABLE(IEnumConnections) *lpvtbl;
76 DWORD ref;
78 /* IUnknown of ConnectionPoint, used for ref counting */
79 IUnknown *pUnk;
81 /* Connection Data */
82 CONNECTDATA *pCD;
83 DWORD nConns;
85 /* Next connection to enumerate from */
86 DWORD nCur;
88 } EnumConnectionsImpl;
90 static EnumConnectionsImpl *EnumConnectionsImpl_Construct(IUnknown *pUnk,
91 DWORD nSinks,
92 CONNECTDATA *pCD);
95 /************************************************************************
96 * ConnectionPointImpl_Construct
98 static ConnectionPointImpl *ConnectionPointImpl_Construct(IUnknown *pUnk,
99 REFIID riid)
101 ConnectionPointImpl *Obj;
103 Obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*Obj));
104 Obj->lpvtbl = &ConnectionPointImpl_VTable;
105 Obj->Obj = pUnk;
106 Obj->ref = 1;
107 Obj->iid = *riid;
108 Obj->maxSinks = MAXSINKS;
109 Obj->sinks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
110 sizeof(IUnknown*) * MAXSINKS);
111 Obj->nSinks = 0;
112 return Obj;
115 /************************************************************************
116 * ConnectionPointImpl_Destroy
118 static void ConnectionPointImpl_Destroy(ConnectionPointImpl *Obj)
120 DWORD i;
121 for(i = 0; i < Obj->maxSinks; i++) {
122 if(Obj->sinks[i]) {
123 IUnknown_Release(Obj->sinks[i]);
124 Obj->sinks[i] = NULL;
127 HeapFree(GetProcessHeap(), 0, Obj->sinks);
128 HeapFree(GetProcessHeap(), 0, Obj);
129 return;
132 static ULONG WINAPI ConnectionPointImpl_AddRef(IConnectionPoint* iface);
133 /************************************************************************
134 * ConnectionPointImpl_QueryInterface (IUnknown)
136 * See Windows documentation for more details on IUnknown methods.
138 static HRESULT WINAPI ConnectionPointImpl_QueryInterface(
139 IConnectionPoint* iface,
140 REFIID riid,
141 void** ppvObject)
143 ICOM_THIS(ConnectionPointImpl, iface);
144 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
147 * Perform a sanity check on the parameters.
149 if ( (This==0) || (ppvObject==0) )
150 return E_INVALIDARG;
153 * Initialize the return parameter.
155 *ppvObject = 0;
158 * Compare the riid with the interface IDs implemented by this object.
160 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
162 *ppvObject = (IConnectionPoint*)This;
164 else if (memcmp(&IID_IConnectionPoint, riid, sizeof(IID_IConnectionPoint)) == 0)
166 *ppvObject = (IConnectionPoint*)This;
170 * Check that we obtained an interface.
172 if ((*ppvObject)==0)
174 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
175 return E_NOINTERFACE;
179 * Query Interface always increases the reference count by one when it is
180 * successful
182 ConnectionPointImpl_AddRef((IConnectionPoint*)This);
184 return S_OK;
188 /************************************************************************
189 * ConnectionPointImpl_AddRef (IUnknown)
191 * See Windows documentation for more details on IUnknown methods.
193 static ULONG WINAPI ConnectionPointImpl_AddRef(IConnectionPoint* iface)
195 ICOM_THIS(ConnectionPointImpl, iface);
196 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
197 This->ref++;
199 return This->ref;
202 /************************************************************************
203 * ConnectionPointImpl_Release (IUnknown)
205 * See Windows documentation for more details on IUnknown methods.
207 static ULONG WINAPI ConnectionPointImpl_Release(
208 IConnectionPoint* iface)
210 ICOM_THIS(ConnectionPointImpl, iface);
211 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
214 * Decrease the reference count on this object.
216 This->ref--;
219 * If the reference count goes down to 0, perform suicide.
221 if (This->ref==0)
223 ConnectionPointImpl_Destroy(This);
225 return 0;
228 return This->ref;
231 /************************************************************************
232 * ConnectionPointImpl_GetConnectionInterface (IConnectionPoint)
235 static HRESULT WINAPI ConnectionPointImpl_GetConnectionInterface(
236 IConnectionPoint *iface,
237 IID *piid)
239 ICOM_THIS(ConnectionPointImpl, iface);
240 TRACE("(%p)->(%p) returning %s\n", This, piid, debugstr_guid(&(This->iid)));
241 *piid = This->iid;
242 return S_OK;
245 /************************************************************************
246 * ConnectionPointImpl_GetConnectionPointContainer (IConnectionPoint)
249 static HRESULT WINAPI ConnectionPointImpl_GetConnectionPointContainer(
250 IConnectionPoint *iface,
251 IConnectionPointContainer **ppCPC)
253 ICOM_THIS(ConnectionPointImpl, iface);
254 TRACE("(%p)->(%p)\n", This, ppCPC);
256 return IUnknown_QueryInterface(This->Obj,
257 &IID_IConnectionPointContainer,
258 (LPVOID)ppCPC);
261 /************************************************************************
262 * ConnectionPointImpl_Advise (IConnectionPoint)
265 static HRESULT WINAPI ConnectionPointImpl_Advise(IConnectionPoint *iface,
266 IUnknown *lpUnk,
267 DWORD *pdwCookie)
269 DWORD i;
270 ICOM_THIS(ConnectionPointImpl, iface);
271 IUnknown *lpSink;
272 TRACE("(%p)->(%p, %p)\n", This, lpUnk, pdwCookie);
274 *pdwCookie = 0;
275 if(FAILED(IUnknown_QueryInterface(lpUnk, &This->iid, (LPVOID)&lpSink)))
276 return CONNECT_E_CANNOTCONNECT;
278 for(i = 0; i < This->maxSinks; i++) {
279 if(This->sinks[i] == NULL)
280 break;
282 if(i == This->maxSinks) {
283 This->maxSinks += MAXSINKS;
284 This->sinks = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->sinks,
285 This->maxSinks * sizeof(IUnknown *));
287 This->sinks[i] = lpSink;
288 This->nSinks++;
289 *pdwCookie = i + 1;
290 return S_OK;
294 /************************************************************************
295 * ConnectionPointImpl_Unadvise (IConnectionPoint)
298 static HRESULT WINAPI ConnectionPointImpl_Unadvise(IConnectionPoint *iface,
299 DWORD dwCookie)
301 ICOM_THIS(ConnectionPointImpl, iface);
302 TRACE("(%p)->(%ld)\n", This, dwCookie);
304 if(dwCookie == 0 || dwCookie > This->maxSinks) return E_INVALIDARG;
306 if(This->sinks[dwCookie-1] == NULL) return CONNECT_E_NOCONNECTION;
308 IUnknown_Release(This->sinks[dwCookie-1]);
309 This->sinks[dwCookie-1] = NULL;
310 This->nSinks--;
311 return S_OK;
314 /************************************************************************
315 * ConnectionPointImpl_EnumConnections (IConnectionPoint)
318 static HRESULT WINAPI ConnectionPointImpl_EnumConnections(
319 IConnectionPoint *iface,
320 LPENUMCONNECTIONS *ppEnum)
322 ICOM_THIS(ConnectionPointImpl, iface);
323 CONNECTDATA *pCD;
324 DWORD i, nextslot;
325 EnumConnectionsImpl *EnumObj;
326 HRESULT hr;
328 TRACE("(%p)->(%p)\n", This, ppEnum);
330 *ppEnum = NULL;
332 if(This->nSinks == 0) return OLE_E_NOCONNECTION;
334 pCD = HeapAlloc(GetProcessHeap(), 0, sizeof(CONNECTDATA) * This->nSinks);
336 for(i = 0, nextslot = 0; i < This->maxSinks; i++) {
337 if(This->sinks[i] != NULL) {
338 pCD[nextslot].pUnk = This->sinks[i];
339 pCD[nextslot].dwCookie = i + 1;
340 nextslot++;
343 assert(nextslot == This->nSinks);
345 /* Bump the ref count of this object up by one. It gets Released in
346 IEnumConnections_Release */
347 IUnknown_AddRef((IUnknown*)This);
349 EnumObj = EnumConnectionsImpl_Construct((IUnknown*)This, This->nSinks, pCD);
350 hr = IEnumConnections_QueryInterface((IEnumConnections*)EnumObj,
351 &IID_IEnumConnections, (LPVOID)ppEnum);
352 IEnumConnections_Release((IEnumConnections*)EnumObj);
354 HeapFree(GetProcessHeap(), 0, pCD);
355 return hr;
358 static ICOM_VTABLE(IConnectionPoint) ConnectionPointImpl_VTable =
360 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
361 ConnectionPointImpl_QueryInterface,
362 ConnectionPointImpl_AddRef,
363 ConnectionPointImpl_Release,
364 ConnectionPointImpl_GetConnectionInterface,
365 ConnectionPointImpl_GetConnectionPointContainer,
366 ConnectionPointImpl_Advise,
367 ConnectionPointImpl_Unadvise,
368 ConnectionPointImpl_EnumConnections
372 static ICOM_VTABLE(IEnumConnections) EnumConnectionsImpl_VTable;
373 static ULONG WINAPI EnumConnectionsImpl_AddRef(IEnumConnections* iface);
375 /************************************************************************
376 * EnumConnectionsImpl_Construct
378 static EnumConnectionsImpl *EnumConnectionsImpl_Construct(IUnknown *pUnk,
379 DWORD nSinks,
380 CONNECTDATA *pCD)
382 EnumConnectionsImpl *Obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*Obj));
383 DWORD i;
385 Obj->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;
392 for(i = 0; i < nSinks; i++) {
393 Obj->pCD[i] = pCD[i];
394 IUnknown_AddRef(Obj->pCD[i].pUnk);
396 return Obj;
399 /************************************************************************
400 * EnumConnectionsImpl_Destroy
402 static void EnumConnectionsImpl_Destroy(EnumConnectionsImpl *Obj)
404 DWORD i;
406 for(i = 0; i < Obj->nConns; i++)
407 IUnknown_Release(Obj->pCD[i].pUnk);
409 HeapFree(GetProcessHeap(), 0, Obj->pCD);
410 HeapFree(GetProcessHeap(), 0, Obj);
411 return;
414 /************************************************************************
415 * EnumConnectionsImpl_QueryInterface (IUnknown)
417 * See Windows documentation for more details on IUnknown methods.
419 static HRESULT WINAPI EnumConnectionsImpl_QueryInterface(
420 IEnumConnections* iface,
421 REFIID riid,
422 void** ppvObject)
424 ICOM_THIS(ConnectionPointImpl, iface);
425 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
428 * Perform a sanity check on the parameters.
430 if ( (This==0) || (ppvObject==0) )
431 return E_INVALIDARG;
434 * Initialize the return parameter.
436 *ppvObject = 0;
439 * Compare the riid with the interface IDs implemented by this object.
441 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
443 *ppvObject = (IEnumConnections*)This;
445 else if (memcmp(&IID_IEnumConnections, riid, sizeof(IID_IEnumConnections)) == 0)
447 *ppvObject = (IEnumConnections*)This;
451 * Check that we obtained an interface.
453 if ((*ppvObject)==0)
455 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
456 return E_NOINTERFACE;
460 * Query Interface always increases the reference count by one when it is
461 * successful
463 EnumConnectionsImpl_AddRef((IEnumConnections*)This);
465 return S_OK;
469 /************************************************************************
470 * EnumConnectionsImpl_AddRef (IUnknown)
472 * See Windows documentation for more details on IUnknown methods.
474 static ULONG WINAPI EnumConnectionsImpl_AddRef(IEnumConnections* iface)
476 ICOM_THIS(EnumConnectionsImpl, iface);
477 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
478 This->ref++;
479 IUnknown_AddRef(This->pUnk);
480 return This->ref;
483 /************************************************************************
484 * EnumConnectionsImpl_Release (IUnknown)
486 * See Windows documentation for more details on IUnknown methods.
488 static ULONG WINAPI EnumConnectionsImpl_Release(IEnumConnections* iface)
490 ICOM_THIS(EnumConnectionsImpl, iface);
491 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
493 IUnknown_Release(This->pUnk);
496 * Decrease the reference count on this object.
498 This->ref--;
501 * If the reference count goes down to 0, perform suicide.
503 if (This->ref==0)
505 EnumConnectionsImpl_Destroy(This);
507 return 0;
510 return This->ref;
513 /************************************************************************
514 * EnumConnectionsImpl_Next (IEnumConnections)
517 static HRESULT WINAPI EnumConnectionsImpl_Next(IEnumConnections* iface,
518 ULONG cConn, LPCONNECTDATA pCD,
519 ULONG *pEnum)
521 ICOM_THIS(EnumConnectionsImpl, iface);
522 DWORD nRet = 0;
523 TRACE("(%p)->(%ld, %p, %p)\n", This, cConn, pCD, pEnum);
525 if(pEnum == NULL) {
526 if(cConn != 1)
527 return E_POINTER;
528 } else
529 *pEnum = 0;
531 if(This->nCur >= This->nConns)
532 return S_FALSE;
534 while(This->nCur < This->nConns && cConn) {
535 *pCD++ = This->pCD[This->nCur];
536 IUnknown_AddRef(This->pCD[This->nCur].pUnk);
537 This->nCur++;
538 cConn--;
539 nRet++;
542 if(pEnum)
543 *pEnum = nRet;
545 return S_OK;
549 /************************************************************************
550 * EnumConnectionsImpl_Skip (IEnumConnections)
553 static HRESULT WINAPI EnumConnectionsImpl_Skip(IEnumConnections* iface,
554 ULONG cSkip)
556 ICOM_THIS(EnumConnectionsImpl, iface);
557 TRACE("(%p)->(%ld)\n", This, cSkip);
559 if(This->nCur + cSkip >= This->nConns)
560 return S_FALSE;
562 This->nCur += cSkip;
564 return S_OK;
568 /************************************************************************
569 * EnumConnectionsImpl_Reset (IEnumConnections)
572 static HRESULT WINAPI EnumConnectionsImpl_Reset(IEnumConnections* iface)
574 ICOM_THIS(EnumConnectionsImpl, iface);
575 TRACE("(%p)\n", This);
577 This->nCur = 0;
579 return S_OK;
583 /************************************************************************
584 * EnumConnectionsImpl_Clone (IEnumConnections)
587 static HRESULT WINAPI EnumConnectionsImpl_Clone(IEnumConnections* iface,
588 LPENUMCONNECTIONS *ppEnum)
590 ICOM_THIS(EnumConnectionsImpl, iface);
591 EnumConnectionsImpl *newObj;
592 TRACE("(%p)->(%p)\n", This, ppEnum);
594 newObj = EnumConnectionsImpl_Construct(This->pUnk, This->nConns, This->pCD);
595 newObj->nCur = This->nCur;
596 *ppEnum = (LPENUMCONNECTIONS)newObj;
597 IUnknown_AddRef(This->pUnk);
598 return S_OK;
601 static ICOM_VTABLE(IEnumConnections) EnumConnectionsImpl_VTable =
603 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
604 EnumConnectionsImpl_QueryInterface,
605 EnumConnectionsImpl_AddRef,
606 EnumConnectionsImpl_Release,
607 EnumConnectionsImpl_Next,
608 EnumConnectionsImpl_Skip,
609 EnumConnectionsImpl_Reset,
610 EnumConnectionsImpl_Clone
613 /************************************************************************
615 * The exported function to create the connection point.
616 * NB not a windows API
618 * PARAMS
619 * pUnk [in] IUnknown of object to which the ConnectionPoint is associated.
620 * Needed to access IConnectionPointContainer.
622 * riid [in] IID of sink interface that this ConnectionPoint manages
624 * pCP [out] returns IConnectionPoint
627 HRESULT CreateConnectionPoint(IUnknown *pUnk, REFIID riid,
628 IConnectionPoint **pCP)
630 ConnectionPointImpl *Obj;
631 HRESULT hr;
633 Obj = ConnectionPointImpl_Construct(pUnk, riid);
634 if(!Obj) return E_OUTOFMEMORY;
636 hr = IConnectionPoint_QueryInterface((IConnectionPoint *)Obj,
637 &IID_IConnectionPoint, (LPVOID)pCP);
638 IConnectionPoint_Release((IConnectionPoint *)Obj);
639 return hr;