ole32: Fix a leak of the IBindCtx object in FileMonikerImpl_IsEqual.
[wine/multimedia.git] / dlls / ole32 / oleobj.c
blob1c887977ac5f806a8999f043dbbe54e20c4fc7cc
1 /*
2 * OLE2 COM objects
4 * Copyright 1998 Eric Kohl
5 * Copyright 1999 Francis Beaudet
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include <stdarg.h>
24 #include <string.h>
26 #define COBJMACROS
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winuser.h"
31 #include "winerror.h"
32 #include "wine/debug.h"
33 #include "ole2.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(ole);
37 #define INITIAL_SINKS 10
39 /**************************************************************************
40 * OleAdviseHolderImpl Implementation
42 typedef struct OleAdviseHolderImpl
44 const IOleAdviseHolderVtbl *lpVtbl;
46 LONG ref;
48 DWORD maxSinks;
49 IAdviseSink** arrayOfSinks;
51 } OleAdviseHolderImpl;
53 static HRESULT EnumOleSTATDATA_Construct(OleAdviseHolderImpl *pOleAdviseHolder, ULONG index, IEnumSTATDATA **ppenum);
55 typedef struct
57 const IEnumSTATDATAVtbl *lpvtbl;
58 LONG ref;
60 ULONG index;
61 OleAdviseHolderImpl *pOleAdviseHolder;
62 } EnumOleSTATDATA;
64 static HRESULT WINAPI EnumOleSTATDATA_QueryInterface(
65 IEnumSTATDATA *iface, REFIID riid, void **ppv)
67 TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
68 if (IsEqualIID(riid, &IID_IUnknown) ||
69 IsEqualIID(riid, &IID_IEnumSTATDATA))
71 IUnknown_AddRef(iface);
72 *ppv = iface;
73 return S_OK;
75 return E_NOINTERFACE;
78 static ULONG WINAPI EnumOleSTATDATA_AddRef(
79 IEnumSTATDATA *iface)
81 EnumOleSTATDATA *This = (EnumOleSTATDATA *)iface;
82 TRACE("()\n");
83 return InterlockedIncrement(&This->ref);
86 static ULONG WINAPI EnumOleSTATDATA_Release(
87 IEnumSTATDATA *iface)
89 EnumOleSTATDATA *This = (EnumOleSTATDATA *)iface;
90 LONG refs = InterlockedDecrement(&This->ref);
91 TRACE("()\n");
92 if (!refs)
94 IOleAdviseHolder_Release((IOleAdviseHolder *)This->pOleAdviseHolder);
95 HeapFree(GetProcessHeap(), 0, This);
97 return refs;
100 static HRESULT WINAPI EnumOleSTATDATA_Next(
101 IEnumSTATDATA *iface, ULONG celt, LPSTATDATA rgelt,
102 ULONG *pceltFetched)
104 EnumOleSTATDATA *This = (EnumOleSTATDATA *)iface;
105 HRESULT hr = S_OK;
107 TRACE("(%d, %p, %p)\n", celt, rgelt, pceltFetched);
109 if (pceltFetched)
110 *pceltFetched = 0;
112 for (; celt; celt--, rgelt++)
114 while ((This->index < This->pOleAdviseHolder->maxSinks) &&
115 !This->pOleAdviseHolder->arrayOfSinks[This->index])
117 This->index++;
119 if (This->index >= This->pOleAdviseHolder->maxSinks)
121 hr = S_FALSE;
122 break;
125 memset(&rgelt->formatetc, 0, sizeof(rgelt->formatetc));
126 rgelt->advf = 0;
127 rgelt->pAdvSink = This->pOleAdviseHolder->arrayOfSinks[This->index];
128 IAdviseSink_AddRef(rgelt->pAdvSink);
129 rgelt->dwConnection = This->index;
131 if (pceltFetched)
132 (*pceltFetched)++;
133 This->index++;
135 return hr;
138 static HRESULT WINAPI EnumOleSTATDATA_Skip(
139 IEnumSTATDATA *iface, ULONG celt)
141 EnumOleSTATDATA *This = (EnumOleSTATDATA *)iface;
143 TRACE("(%d)\n", celt);
145 for (; celt; celt--)
147 while ((This->index < This->pOleAdviseHolder->maxSinks) &&
148 !This->pOleAdviseHolder->arrayOfSinks[This->index])
150 This->index++;
152 if (This->index >= This->pOleAdviseHolder->maxSinks)
153 return S_FALSE;
154 This->index++;
156 return S_OK;
159 static HRESULT WINAPI EnumOleSTATDATA_Reset(
160 IEnumSTATDATA *iface)
162 EnumOleSTATDATA *This = (EnumOleSTATDATA *)iface;
164 TRACE("()\n");
166 This->index = 0;
167 return S_OK;
170 static HRESULT WINAPI EnumOleSTATDATA_Clone(
171 IEnumSTATDATA *iface,
172 IEnumSTATDATA **ppenum)
174 EnumOleSTATDATA *This = (EnumOleSTATDATA *)iface;
175 return EnumOleSTATDATA_Construct(This->pOleAdviseHolder, This->index, ppenum);
178 static const IEnumSTATDATAVtbl EnumOleSTATDATA_VTable =
180 EnumOleSTATDATA_QueryInterface,
181 EnumOleSTATDATA_AddRef,
182 EnumOleSTATDATA_Release,
183 EnumOleSTATDATA_Next,
184 EnumOleSTATDATA_Skip,
185 EnumOleSTATDATA_Reset,
186 EnumOleSTATDATA_Clone
189 static HRESULT EnumOleSTATDATA_Construct(OleAdviseHolderImpl *pOleAdviseHolder, ULONG index, IEnumSTATDATA **ppenum)
191 EnumOleSTATDATA *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
192 if (!This)
193 return E_OUTOFMEMORY;
194 This->lpvtbl = &EnumOleSTATDATA_VTable;
195 This->ref = 1;
196 This->index = index;
197 This->pOleAdviseHolder = pOleAdviseHolder;
198 IOleAdviseHolder_AddRef((IOleAdviseHolder *)pOleAdviseHolder);
199 *ppenum = (IEnumSTATDATA *)&This->lpvtbl;
200 return S_OK;
203 /**************************************************************************
204 * OleAdviseHolderImpl_Destructor
206 static void OleAdviseHolderImpl_Destructor(
207 OleAdviseHolderImpl* ptrToDestroy)
209 DWORD index;
210 TRACE("%p\n", ptrToDestroy);
212 for (index = 0; index < ptrToDestroy->maxSinks; index++)
214 if (ptrToDestroy->arrayOfSinks[index]!=0)
216 IAdviseSink_Release(ptrToDestroy->arrayOfSinks[index]);
217 ptrToDestroy->arrayOfSinks[index] = NULL;
221 HeapFree(GetProcessHeap(),
223 ptrToDestroy->arrayOfSinks);
226 HeapFree(GetProcessHeap(),
228 ptrToDestroy);
231 /**************************************************************************
232 * OleAdviseHolderImpl_QueryInterface
234 static HRESULT WINAPI OleAdviseHolderImpl_QueryInterface(
235 LPOLEADVISEHOLDER iface,
236 REFIID riid,
237 LPVOID* ppvObj)
239 OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
240 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObj);
242 * Sanity check
244 if (ppvObj==NULL)
245 return E_POINTER;
247 *ppvObj = NULL;
249 if (IsEqualIID(riid, &IID_IUnknown))
251 /* IUnknown */
252 *ppvObj = This;
254 else if(IsEqualIID(riid, &IID_IOleAdviseHolder))
256 /* IOleAdviseHolder */
257 *ppvObj = (IOleAdviseHolder*) This;
260 if(*ppvObj == NULL)
261 return E_NOINTERFACE;
264 * A successful QI always increments the reference count.
266 IUnknown_AddRef((IUnknown*)*ppvObj);
268 return S_OK;
271 /******************************************************************************
272 * OleAdviseHolderImpl_AddRef
274 static ULONG WINAPI OleAdviseHolderImpl_AddRef(
275 LPOLEADVISEHOLDER iface)
277 OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
278 ULONG ref = InterlockedIncrement(&This->ref);
280 TRACE("(%p)->(ref=%d)\n", This, ref - 1);
282 return ref;
285 /******************************************************************************
286 * OleAdviseHolderImpl_Release
288 static ULONG WINAPI OleAdviseHolderImpl_Release(
289 LPOLEADVISEHOLDER iface)
291 OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
292 ULONG ref;
293 TRACE("(%p)->(ref=%d)\n", This, This->ref);
294 ref = InterlockedDecrement(&This->ref);
296 if (ref == 0) OleAdviseHolderImpl_Destructor(This);
298 return ref;
301 /******************************************************************************
302 * OleAdviseHolderImpl_Advise
304 static HRESULT WINAPI OleAdviseHolderImpl_Advise(
305 LPOLEADVISEHOLDER iface,
306 IAdviseSink* pAdvise,
307 DWORD* pdwConnection)
309 DWORD index;
311 OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
313 TRACE("(%p)->(%p, %p)\n", This, pAdvise, pdwConnection);
316 * Sanity check
318 if (pdwConnection==NULL)
319 return E_POINTER;
321 *pdwConnection = 0;
324 * Find a free spot in the array.
326 for (index = 0; index < This->maxSinks; index++)
328 if (This->arrayOfSinks[index]==NULL)
329 break;
333 * If the array is full, we need to grow it.
335 if (index == This->maxSinks)
337 DWORD i;
339 This->maxSinks+=INITIAL_SINKS;
341 This->arrayOfSinks = HeapReAlloc(GetProcessHeap(),
343 This->arrayOfSinks,
344 This->maxSinks*sizeof(IAdviseSink*));
346 for (i=index;i < This->maxSinks; i++)
347 This->arrayOfSinks[i]=0;
351 * Store the new sink
353 This->arrayOfSinks[index] = pAdvise;
355 if (This->arrayOfSinks[index]!=NULL)
356 IAdviseSink_AddRef(This->arrayOfSinks[index]);
359 * Return the index as the cookie.
360 * Since 0 is not a valid cookie, we will increment by
361 * 1 the index in the table.
363 *pdwConnection = index+1;
365 return S_OK;
368 /******************************************************************************
369 * OleAdviseHolderImpl_Unadvise
371 static HRESULT WINAPI OleAdviseHolderImpl_Unadvise(
372 LPOLEADVISEHOLDER iface,
373 DWORD dwConnection)
375 OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
377 TRACE("(%p)->(%u)\n", This, dwConnection);
380 * So we don't return 0 as a cookie, the index was
381 * incremented by 1 in OleAdviseHolderImpl_Advise
382 * we have to compensate.
384 dwConnection--;
387 * Check for invalid cookies.
389 if (dwConnection >= This->maxSinks)
390 return OLE_E_NOCONNECTION;
392 if (This->arrayOfSinks[dwConnection] == NULL)
393 return OLE_E_NOCONNECTION;
396 * Release the sink and mark the spot in the list as free.
398 IAdviseSink_Release(This->arrayOfSinks[dwConnection]);
399 This->arrayOfSinks[dwConnection] = NULL;
401 return S_OK;
404 /******************************************************************************
405 * OleAdviseHolderImpl_EnumAdvise
407 static HRESULT WINAPI
408 OleAdviseHolderImpl_EnumAdvise (LPOLEADVISEHOLDER iface, IEnumSTATDATA **ppenumAdvise)
410 OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
412 TRACE("(%p)->(%p)\n", This, ppenumAdvise);
414 *ppenumAdvise = NULL;
416 return EnumOleSTATDATA_Construct(This, 0, ppenumAdvise);
419 /******************************************************************************
420 * OleAdviseHolderImpl_SendOnRename
422 static HRESULT WINAPI
423 OleAdviseHolderImpl_SendOnRename (LPOLEADVISEHOLDER iface, IMoniker *pmk)
425 IEnumSTATDATA *pEnum;
426 HRESULT hr;
428 TRACE("(%p)->(%p)\n", iface, pmk);
430 hr = IOleAdviseHolder_EnumAdvise(iface, &pEnum);
431 if (SUCCEEDED(hr))
433 STATDATA statdata;
434 while (IEnumSTATDATA_Next(pEnum, 1, &statdata, NULL) == S_OK)
436 IAdviseSink_OnRename(statdata.pAdvSink, pmk);
438 IAdviseSink_Release(statdata.pAdvSink);
440 IEnumSTATDATA_Release(pEnum);
443 return hr;
446 /******************************************************************************
447 * OleAdviseHolderImpl_SendOnSave
449 static HRESULT WINAPI
450 OleAdviseHolderImpl_SendOnSave (LPOLEADVISEHOLDER iface)
452 IEnumSTATDATA *pEnum;
453 HRESULT hr;
455 TRACE("(%p)->()\n", iface);
457 hr = IOleAdviseHolder_EnumAdvise(iface, &pEnum);
458 if (SUCCEEDED(hr))
460 STATDATA statdata;
461 while (IEnumSTATDATA_Next(pEnum, 1, &statdata, NULL) == S_OK)
463 IAdviseSink_OnSave(statdata.pAdvSink);
465 IAdviseSink_Release(statdata.pAdvSink);
467 IEnumSTATDATA_Release(pEnum);
470 return hr;
473 /******************************************************************************
474 * OleAdviseHolderImpl_SendOnClose
476 static HRESULT WINAPI
477 OleAdviseHolderImpl_SendOnClose (LPOLEADVISEHOLDER iface)
479 IEnumSTATDATA *pEnum;
480 HRESULT hr;
482 TRACE("(%p)->()\n", iface);
484 hr = IOleAdviseHolder_EnumAdvise(iface, &pEnum);
485 if (SUCCEEDED(hr))
487 STATDATA statdata;
488 while (IEnumSTATDATA_Next(pEnum, 1, &statdata, NULL) == S_OK)
490 IAdviseSink_OnClose(statdata.pAdvSink);
492 IAdviseSink_Release(statdata.pAdvSink);
494 IEnumSTATDATA_Release(pEnum);
497 return hr;
500 /**************************************************************************
501 * OleAdviseHolderImpl_VTable
503 static const IOleAdviseHolderVtbl oahvt =
505 OleAdviseHolderImpl_QueryInterface,
506 OleAdviseHolderImpl_AddRef,
507 OleAdviseHolderImpl_Release,
508 OleAdviseHolderImpl_Advise,
509 OleAdviseHolderImpl_Unadvise,
510 OleAdviseHolderImpl_EnumAdvise,
511 OleAdviseHolderImpl_SendOnRename,
512 OleAdviseHolderImpl_SendOnSave,
513 OleAdviseHolderImpl_SendOnClose
516 /**************************************************************************
517 * OleAdviseHolderImpl_Constructor
520 static LPOLEADVISEHOLDER OleAdviseHolderImpl_Constructor(void)
522 OleAdviseHolderImpl* lpoah;
523 DWORD index;
525 lpoah = HeapAlloc(GetProcessHeap(), 0, sizeof(OleAdviseHolderImpl));
527 lpoah->lpVtbl = &oahvt;
528 lpoah->ref = 1;
529 lpoah->maxSinks = INITIAL_SINKS;
530 lpoah->arrayOfSinks = HeapAlloc(GetProcessHeap(),
532 lpoah->maxSinks * sizeof(IAdviseSink*));
534 for (index = 0; index < lpoah->maxSinks; index++)
535 lpoah->arrayOfSinks[index]=0;
537 TRACE("returning %p\n", lpoah);
538 return (LPOLEADVISEHOLDER)lpoah;
541 /**************************************************************************
542 * DataAdviseHolder Implementation
544 typedef struct DataAdviseConnection {
545 IAdviseSink *sink;
546 FORMATETC fmat;
547 DWORD advf;
548 DWORD remote_connection;
549 } DataAdviseConnection;
551 typedef struct DataAdviseHolder
553 const IDataAdviseHolderVtbl *lpVtbl;
555 LONG ref;
556 DWORD maxCons;
557 DataAdviseConnection* Connections;
558 IDataObject* delegate;
559 } DataAdviseHolder;
561 /* this connection has also has been advised to the delegate data object */
562 #define WINE_ADVF_REMOTE 0x80000000
564 /******************************************************************************
565 * DataAdviseHolder_Destructor
567 static void DataAdviseHolder_Destructor(DataAdviseHolder* ptrToDestroy)
569 DWORD index;
570 TRACE("%p\n", ptrToDestroy);
572 for (index = 0; index < ptrToDestroy->maxCons; index++)
574 if (ptrToDestroy->Connections[index].sink != NULL)
576 if (ptrToDestroy->delegate &&
577 (ptrToDestroy->Connections[index].advf & WINE_ADVF_REMOTE))
578 IDataObject_DUnadvise(ptrToDestroy->delegate,
579 ptrToDestroy->Connections[index].remote_connection);
581 IAdviseSink_Release(ptrToDestroy->Connections[index].sink);
582 ptrToDestroy->Connections[index].sink = NULL;
586 HeapFree(GetProcessHeap(), 0, ptrToDestroy->Connections);
587 HeapFree(GetProcessHeap(), 0, ptrToDestroy);
590 /************************************************************************
591 * DataAdviseHolder_QueryInterface (IUnknown)
593 * See Windows documentation for more details on IUnknown methods.
595 static HRESULT WINAPI DataAdviseHolder_QueryInterface(
596 IDataAdviseHolder* iface,
597 REFIID riid,
598 void** ppvObject)
600 DataAdviseHolder *This = (DataAdviseHolder *)iface;
601 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObject);
603 * Perform a sanity check on the parameters.
605 if ( (This==0) || (ppvObject==0) )
606 return E_INVALIDARG;
609 * Initialize the return parameter.
611 *ppvObject = 0;
614 * Compare the riid with the interface IDs implemented by this object.
616 if ( (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0) ||
617 (memcmp(&IID_IDataAdviseHolder, riid, sizeof(IID_IDataAdviseHolder)) == 0) )
619 *ppvObject = iface;
623 * Check that we obtained an interface.
625 if ((*ppvObject)==0)
627 return E_NOINTERFACE;
631 * Query Interface always increases the reference count by one when it is
632 * successful.
634 IUnknown_AddRef((IUnknown*)*ppvObject);
636 return S_OK;
639 /************************************************************************
640 * DataAdviseHolder_AddRef (IUnknown)
642 * See Windows documentation for more details on IUnknown methods.
644 static ULONG WINAPI DataAdviseHolder_AddRef(
645 IDataAdviseHolder* iface)
647 DataAdviseHolder *This = (DataAdviseHolder *)iface;
648 TRACE("(%p) (ref=%d)\n", This, This->ref);
649 return InterlockedIncrement(&This->ref);
652 /************************************************************************
653 * DataAdviseHolder_Release (IUnknown)
655 * See Windows documentation for more details on IUnknown methods.
657 static ULONG WINAPI DataAdviseHolder_Release(
658 IDataAdviseHolder* iface)
660 DataAdviseHolder *This = (DataAdviseHolder *)iface;
661 ULONG ref;
662 TRACE("(%p) (ref=%d)\n", This, This->ref);
665 * Decrease the reference count on this object.
667 ref = InterlockedDecrement(&This->ref);
670 * If the reference count goes down to 0, perform suicide.
672 if (ref==0) DataAdviseHolder_Destructor(This);
674 return ref;
677 /************************************************************************
678 * DataAdviseHolder_Advise
681 static HRESULT WINAPI DataAdviseHolder_Advise(
682 IDataAdviseHolder* iface,
683 IDataObject* pDataObject,
684 FORMATETC* pFetc,
685 DWORD advf,
686 IAdviseSink* pAdvise,
687 DWORD* pdwConnection)
689 DWORD index;
691 DataAdviseHolder *This = (DataAdviseHolder *)iface;
693 TRACE("(%p)->(%p, %p, %08x, %p, %p)\n", This, pDataObject, pFetc, advf,
694 pAdvise, pdwConnection);
696 * Sanity check
698 if (pdwConnection==NULL)
699 return E_POINTER;
701 *pdwConnection = 0;
704 * Find a free spot in the array.
706 for (index = 0; index < This->maxCons; index++)
708 if (This->Connections[index].sink == NULL)
709 break;
713 * If the array is full, we need to grow it.
715 if (index == This->maxCons)
717 This->maxCons+=INITIAL_SINKS;
718 This->Connections = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
719 This->Connections,
720 This->maxCons*sizeof(DataAdviseConnection));
723 * Store the new sink
725 This->Connections[index].sink = pAdvise;
726 This->Connections[index].advf = advf & ~WINE_ADVF_REMOTE;
727 memcpy(&(This->Connections[index].fmat), pFetc, sizeof(FORMATETC));
728 if (pFetc->ptd)
730 This->Connections[index].fmat.ptd = CoTaskMemAlloc(pFetc->ptd->tdSize);
731 if (!This->Connections[index].fmat.ptd)
733 IDataAdviseHolder_Unadvise(iface, index + 1);
734 return E_OUTOFMEMORY;
736 memcpy(This->Connections[index].fmat.ptd, pFetc->ptd, pFetc->ptd->tdSize);
739 if (This->Connections[index].sink != NULL) {
740 IAdviseSink_AddRef(This->Connections[index].sink);
742 /* if we are already connected advise the remote object */
743 if (This->delegate)
745 HRESULT hr;
747 hr = IDataObject_DAdvise(This->delegate, &This->Connections[index].fmat,
748 This->Connections[index].advf,
749 This->Connections[index].sink,
750 &This->Connections[index].remote_connection);
751 if (FAILED(hr))
753 IDataAdviseHolder_Unadvise(iface, index + 1);
754 return hr;
756 This->Connections[index].advf |= WINE_ADVF_REMOTE;
758 else if(advf & ADVF_PRIMEFIRST)
759 /* only do this if we have no delegate, since in the above case the
760 * delegate will do the priming for us */
761 IDataAdviseHolder_SendOnDataChange(iface, pDataObject, 0, advf);
764 * Return the index as the cookie.
765 * Since 0 is not a valid cookie, we will increment by
766 * 1 the index in the table.
768 *pdwConnection = index+1;
770 return S_OK;
773 /******************************************************************************
774 * DataAdviseHolder_Unadvise
776 static HRESULT WINAPI DataAdviseHolder_Unadvise(
777 IDataAdviseHolder* iface,
778 DWORD dwConnection)
780 DataAdviseHolder *This = (DataAdviseHolder *)iface;
782 TRACE("(%p)->(%u)\n", This, dwConnection);
785 * So we don't return 0 as a cookie, the index was
786 * incremented by 1 in OleAdviseHolderImpl_Advise
787 * we have to compensate.
789 dwConnection--;
792 * Check for invalid cookies.
794 if (dwConnection >= This->maxCons)
795 return OLE_E_NOCONNECTION;
797 if (This->Connections[dwConnection].sink == NULL)
798 return OLE_E_NOCONNECTION;
800 if (This->delegate && This->Connections[dwConnection].advf & WINE_ADVF_REMOTE)
801 IDataObject_DUnadvise(This->delegate,
802 This->Connections[dwConnection].remote_connection);
805 * Release the sink and mark the spot in the list as free.
807 IAdviseSink_Release(This->Connections[dwConnection].sink);
808 memset(&(This->Connections[dwConnection]), 0, sizeof(DataAdviseConnection));
810 return S_OK;
813 static HRESULT WINAPI DataAdviseHolder_EnumAdvise(
814 IDataAdviseHolder* iface,
815 IEnumSTATDATA** ppenumAdvise)
817 DataAdviseHolder *This = (DataAdviseHolder *)iface;
819 FIXME("(%p)->(%p)\n", This, ppenumAdvise);
820 return E_NOTIMPL;
823 /******************************************************************************
824 * DataAdviseHolder_SendOnDataChange
826 static HRESULT WINAPI DataAdviseHolder_SendOnDataChange(
827 IDataAdviseHolder* iface,
828 IDataObject* pDataObject,
829 DWORD dwReserved,
830 DWORD advf)
832 DataAdviseHolder *This = (DataAdviseHolder *)iface;
833 DWORD index;
834 STGMEDIUM stg;
835 HRESULT res;
837 TRACE("(%p)->(%p,%08x,%08x)\n", This, pDataObject, dwReserved, advf);
839 for(index = 0; index < This->maxCons; index++) {
840 if(This->Connections[index].sink != NULL) {
841 memset(&stg, 0, sizeof(stg));
842 if(!(This->Connections[index].advf & ADVF_NODATA)) {
843 TRACE("Calling IDataObject_GetData\n");
844 res = IDataObject_GetData(pDataObject,
845 &(This->Connections[index].fmat),
846 &stg);
847 TRACE("returns %08x\n", res);
849 TRACE("Calling IAdviseSink_OnDataChange\n");
850 IAdviseSink_OnDataChange(This->Connections[index].sink,
851 &(This->Connections[index].fmat),
852 &stg);
853 TRACE("Done IAdviseSink_OnDataChange\n");
854 if(This->Connections[index].advf & ADVF_ONLYONCE) {
855 TRACE("Removing connection\n");
856 DataAdviseHolder_Unadvise(iface, index+1);
860 return S_OK;
863 /**************************************************************************
864 * DataAdviseHolderImpl_VTable
866 static const IDataAdviseHolderVtbl DataAdviseHolderImpl_VTable =
868 DataAdviseHolder_QueryInterface,
869 DataAdviseHolder_AddRef,
870 DataAdviseHolder_Release,
871 DataAdviseHolder_Advise,
872 DataAdviseHolder_Unadvise,
873 DataAdviseHolder_EnumAdvise,
874 DataAdviseHolder_SendOnDataChange
877 HRESULT DataAdviseHolder_OnConnect(IDataAdviseHolder *iface, IDataObject *pDelegate)
879 DataAdviseHolder *This = (DataAdviseHolder *)iface;
880 DWORD index;
881 HRESULT hr = S_OK;
883 for(index = 0; index < This->maxCons; index++)
885 if(This->Connections[index].sink != NULL)
887 hr = IDataObject_DAdvise(pDelegate, &This->Connections[index].fmat,
888 This->Connections[index].advf,
889 This->Connections[index].sink,
890 &This->Connections[index].remote_connection);
891 if (FAILED(hr)) break;
892 This->Connections[index].advf |= WINE_ADVF_REMOTE;
895 This->delegate = pDelegate;
896 return hr;
899 void DataAdviseHolder_OnDisconnect(IDataAdviseHolder *iface)
901 DataAdviseHolder *This = (DataAdviseHolder *)iface;
902 DWORD index;
904 for(index = 0; index < This->maxCons; index++)
906 if((This->Connections[index].sink != NULL) &&
907 (This->Connections[index].advf & WINE_ADVF_REMOTE))
909 IDataObject_DUnadvise(This->delegate,
910 This->Connections[index].remote_connection);
911 This->Connections[index].advf &= ~WINE_ADVF_REMOTE;
914 This->delegate = NULL;
917 /******************************************************************************
918 * DataAdviseHolder_Constructor
920 static IDataAdviseHolder* DataAdviseHolder_Constructor(void)
922 DataAdviseHolder* newHolder;
924 newHolder = HeapAlloc(GetProcessHeap(), 0, sizeof(DataAdviseHolder));
926 newHolder->lpVtbl = &DataAdviseHolderImpl_VTable;
927 newHolder->ref = 1;
928 newHolder->maxCons = INITIAL_SINKS;
929 newHolder->Connections = HeapAlloc(GetProcessHeap(),
930 HEAP_ZERO_MEMORY,
931 newHolder->maxCons *
932 sizeof(DataAdviseConnection));
933 newHolder->delegate = NULL;
935 TRACE("returning %p\n", newHolder);
936 return (IDataAdviseHolder*)newHolder;
939 /***********************************************************************
940 * API functions
943 /***********************************************************************
944 * CreateOleAdviseHolder [OLE32.@]
946 HRESULT WINAPI CreateOleAdviseHolder(
947 LPOLEADVISEHOLDER *ppOAHolder)
949 TRACE("(%p)\n", ppOAHolder);
952 * Sanity check,
954 if (ppOAHolder==NULL)
955 return E_POINTER;
957 *ppOAHolder = OleAdviseHolderImpl_Constructor ();
959 if (*ppOAHolder != NULL)
960 return S_OK;
962 return E_OUTOFMEMORY;
965 /******************************************************************************
966 * CreateDataAdviseHolder [OLE32.@]
968 HRESULT WINAPI CreateDataAdviseHolder(
969 LPDATAADVISEHOLDER* ppDAHolder)
971 TRACE("(%p)\n", ppDAHolder);
974 * Sanity check,
976 if (ppDAHolder==NULL)
977 return E_POINTER;
979 *ppDAHolder = DataAdviseHolder_Constructor();
981 if (*ppDAHolder != NULL)
982 return S_OK;
984 return E_OUTOFMEMORY;