It's important to keep the original dib colour table and not just the
[wine/multimedia.git] / dlls / oleaut32 / connpt.c
blobe6bf0987151357c5c3b6c9700f539bc2984196bc
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 <stdarg.h>
27 #include <string.h>
28 #include "winerror.h"
29 #include "windef.h"
30 #include "winbase.h"
31 #include "wingdi.h"
32 #include "winuser.h"
33 #include "ole2.h"
34 #include "olectl.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 IConnectionPointVtbl *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 IConnectionPointVtbl ConnectionPointImpl_VTable;
69 /************************************************************************
70 * Implementation of IEnumConnections
72 typedef struct EnumConnectionsImpl {
74 IEnumConnectionsVtbl *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 ConnectionPointImpl *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 ConnectionPointImpl *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 ConnectionPointImpl *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 ConnectionPointImpl *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 ConnectionPointImpl *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 ConnectionPointImpl *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 ConnectionPointImpl *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 ConnectionPointImpl *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 IConnectionPointVtbl ConnectionPointImpl_VTable =
360 ConnectionPointImpl_QueryInterface,
361 ConnectionPointImpl_AddRef,
362 ConnectionPointImpl_Release,
363 ConnectionPointImpl_GetConnectionInterface,
364 ConnectionPointImpl_GetConnectionPointContainer,
365 ConnectionPointImpl_Advise,
366 ConnectionPointImpl_Unadvise,
367 ConnectionPointImpl_EnumConnections
371 static IEnumConnectionsVtbl EnumConnectionsImpl_VTable;
372 static ULONG WINAPI EnumConnectionsImpl_AddRef(IEnumConnections* iface);
374 /************************************************************************
375 * EnumConnectionsImpl_Construct
377 static EnumConnectionsImpl *EnumConnectionsImpl_Construct(IUnknown *pUnk,
378 DWORD nSinks,
379 CONNECTDATA *pCD)
381 EnumConnectionsImpl *Obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*Obj));
382 DWORD i;
384 Obj->lpvtbl = &EnumConnectionsImpl_VTable;
385 Obj->ref = 1;
386 Obj->pUnk = pUnk;
387 Obj->pCD = HeapAlloc(GetProcessHeap(), 0, nSinks * sizeof(CONNECTDATA));
388 Obj->nConns = nSinks;
389 Obj->nCur = 0;
391 for(i = 0; i < nSinks; i++) {
392 Obj->pCD[i] = pCD[i];
393 IUnknown_AddRef(Obj->pCD[i].pUnk);
395 return Obj;
398 /************************************************************************
399 * EnumConnectionsImpl_Destroy
401 static void EnumConnectionsImpl_Destroy(EnumConnectionsImpl *Obj)
403 DWORD i;
405 for(i = 0; i < Obj->nConns; i++)
406 IUnknown_Release(Obj->pCD[i].pUnk);
408 HeapFree(GetProcessHeap(), 0, Obj->pCD);
409 HeapFree(GetProcessHeap(), 0, Obj);
410 return;
413 /************************************************************************
414 * EnumConnectionsImpl_QueryInterface (IUnknown)
416 * See Windows documentation for more details on IUnknown methods.
418 static HRESULT WINAPI EnumConnectionsImpl_QueryInterface(
419 IEnumConnections* iface,
420 REFIID riid,
421 void** ppvObject)
423 ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
424 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
427 * Perform a sanity check on the parameters.
429 if ( (This==0) || (ppvObject==0) )
430 return E_INVALIDARG;
433 * Initialize the return parameter.
435 *ppvObject = 0;
438 * Compare the riid with the interface IDs implemented by this object.
440 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
442 *ppvObject = (IEnumConnections*)This;
444 else if (memcmp(&IID_IEnumConnections, riid, sizeof(IID_IEnumConnections)) == 0)
446 *ppvObject = (IEnumConnections*)This;
450 * Check that we obtained an interface.
452 if ((*ppvObject)==0)
454 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
455 return E_NOINTERFACE;
459 * Query Interface always increases the reference count by one when it is
460 * successful
462 EnumConnectionsImpl_AddRef((IEnumConnections*)This);
464 return S_OK;
468 /************************************************************************
469 * EnumConnectionsImpl_AddRef (IUnknown)
471 * See Windows documentation for more details on IUnknown methods.
473 static ULONG WINAPI EnumConnectionsImpl_AddRef(IEnumConnections* iface)
475 EnumConnectionsImpl *This = (EnumConnectionsImpl *)iface;
476 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
477 This->ref++;
478 IUnknown_AddRef(This->pUnk);
479 return This->ref;
482 /************************************************************************
483 * EnumConnectionsImpl_Release (IUnknown)
485 * See Windows documentation for more details on IUnknown methods.
487 static ULONG WINAPI EnumConnectionsImpl_Release(IEnumConnections* iface)
489 EnumConnectionsImpl *This = (EnumConnectionsImpl *)iface;
490 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
492 IUnknown_Release(This->pUnk);
495 * Decrease the reference count on this object.
497 This->ref--;
500 * If the reference count goes down to 0, perform suicide.
502 if (This->ref==0)
504 EnumConnectionsImpl_Destroy(This);
506 return 0;
509 return This->ref;
512 /************************************************************************
513 * EnumConnectionsImpl_Next (IEnumConnections)
516 static HRESULT WINAPI EnumConnectionsImpl_Next(IEnumConnections* iface,
517 ULONG cConn, LPCONNECTDATA pCD,
518 ULONG *pEnum)
520 EnumConnectionsImpl *This = (EnumConnectionsImpl *)iface;
521 DWORD nRet = 0;
522 TRACE("(%p)->(%ld, %p, %p)\n", This, cConn, pCD, pEnum);
524 if(pEnum == NULL) {
525 if(cConn != 1)
526 return E_POINTER;
527 } else
528 *pEnum = 0;
530 if(This->nCur >= This->nConns)
531 return S_FALSE;
533 while(This->nCur < This->nConns && cConn) {
534 *pCD++ = This->pCD[This->nCur];
535 IUnknown_AddRef(This->pCD[This->nCur].pUnk);
536 This->nCur++;
537 cConn--;
538 nRet++;
541 if(pEnum)
542 *pEnum = nRet;
544 return S_OK;
548 /************************************************************************
549 * EnumConnectionsImpl_Skip (IEnumConnections)
552 static HRESULT WINAPI EnumConnectionsImpl_Skip(IEnumConnections* iface,
553 ULONG cSkip)
555 EnumConnectionsImpl *This = (EnumConnectionsImpl *)iface;
556 TRACE("(%p)->(%ld)\n", This, cSkip);
558 if(This->nCur + cSkip >= This->nConns)
559 return S_FALSE;
561 This->nCur += cSkip;
563 return S_OK;
567 /************************************************************************
568 * EnumConnectionsImpl_Reset (IEnumConnections)
571 static HRESULT WINAPI EnumConnectionsImpl_Reset(IEnumConnections* iface)
573 EnumConnectionsImpl *This = (EnumConnectionsImpl *)iface;
574 TRACE("(%p)\n", This);
576 This->nCur = 0;
578 return S_OK;
582 /************************************************************************
583 * EnumConnectionsImpl_Clone (IEnumConnections)
586 static HRESULT WINAPI EnumConnectionsImpl_Clone(IEnumConnections* iface,
587 LPENUMCONNECTIONS *ppEnum)
589 EnumConnectionsImpl *This = (EnumConnectionsImpl *)iface;
590 EnumConnectionsImpl *newObj;
591 TRACE("(%p)->(%p)\n", This, ppEnum);
593 newObj = EnumConnectionsImpl_Construct(This->pUnk, This->nConns, This->pCD);
594 newObj->nCur = This->nCur;
595 *ppEnum = (LPENUMCONNECTIONS)newObj;
596 IUnknown_AddRef(This->pUnk);
597 return S_OK;
600 static IEnumConnectionsVtbl EnumConnectionsImpl_VTable =
602 EnumConnectionsImpl_QueryInterface,
603 EnumConnectionsImpl_AddRef,
604 EnumConnectionsImpl_Release,
605 EnumConnectionsImpl_Next,
606 EnumConnectionsImpl_Skip,
607 EnumConnectionsImpl_Reset,
608 EnumConnectionsImpl_Clone
611 /************************************************************************
613 * The exported function to create the connection point.
614 * NB not a windows API
616 * PARAMS
617 * pUnk [in] IUnknown of object to which the ConnectionPoint is associated.
618 * Needed to access IConnectionPointContainer.
620 * riid [in] IID of sink interface that this ConnectionPoint manages
622 * pCP [out] returns IConnectionPoint
625 HRESULT CreateConnectionPoint(IUnknown *pUnk, REFIID riid,
626 IConnectionPoint **pCP)
628 ConnectionPointImpl *Obj;
629 HRESULT hr;
631 Obj = ConnectionPointImpl_Construct(pUnk, riid);
632 if(!Obj) return E_OUTOFMEMORY;
634 hr = IConnectionPoint_QueryInterface((IConnectionPoint *)Obj,
635 &IID_IConnectionPoint, (LPVOID)pCP);
636 IConnectionPoint_Release((IConnectionPoint *)Obj);
637 return hr;