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
32 #include "wine/debug.h"
35 #include "compobj_private.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(ole);
39 #define INITIAL_SINKS 10
41 static void release_statdata(STATDATA *data)
43 if(data->formatetc.ptd)
45 CoTaskMemFree(data->formatetc.ptd);
46 data->formatetc.ptd = NULL;
51 IAdviseSink_Release(data->pAdvSink);
52 data->pAdvSink = NULL;
56 static HRESULT copy_statdata(STATDATA *dst, const STATDATA *src)
59 if(src->formatetc.ptd)
61 dst->formatetc.ptd = CoTaskMemAlloc(src->formatetc.ptd->tdSize);
62 if(!dst->formatetc.ptd) return E_OUTOFMEMORY;
63 memcpy(dst->formatetc.ptd, src->formatetc.ptd, src->formatetc.ptd->tdSize);
65 if(dst->pAdvSink) IAdviseSink_AddRef(dst->pAdvSink);
69 /**************************************************************************
70 * EnumSTATDATA Implementation
73 static HRESULT EnumSTATDATA_Construct(IUnknown *holder, ULONG index, DWORD array_len, STATDATA *data, IEnumSTATDATA **ppenum);
77 IEnumSTATDATA IEnumSTATDATA_iface;
86 static inline EnumSTATDATA *impl_from_IEnumSTATDATA(IEnumSTATDATA *iface)
88 return CONTAINING_RECORD(iface, EnumSTATDATA, IEnumSTATDATA_iface);
91 static HRESULT WINAPI EnumSTATDATA_QueryInterface(IEnumSTATDATA *iface, REFIID riid, void **ppv)
93 TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
94 if (IsEqualIID(riid, &IID_IUnknown) ||
95 IsEqualIID(riid, &IID_IEnumSTATDATA))
97 IUnknown_AddRef(iface);
101 return E_NOINTERFACE;
104 static ULONG WINAPI EnumSTATDATA_AddRef(IEnumSTATDATA *iface)
106 EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
108 return InterlockedIncrement(&This->ref);
111 static ULONG WINAPI EnumSTATDATA_Release(IEnumSTATDATA *iface)
113 EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
114 LONG refs = InterlockedDecrement(&This->ref);
119 for(i = 0; i < This->num_of_elems; i++)
120 release_statdata(This->statdata + i);
121 HeapFree(GetProcessHeap(), 0, This->statdata);
122 IUnknown_Release(This->holder);
123 HeapFree(GetProcessHeap(), 0, This);
128 static HRESULT WINAPI EnumSTATDATA_Next(IEnumSTATDATA *iface, ULONG num, LPSTATDATA data,
131 EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
135 TRACE("(%d, %p, %p)\n", num, data, fetched);
139 if (This->index >= This->num_of_elems)
145 copy_statdata(data + count, This->statdata + This->index);
151 if (fetched) *fetched = count;
156 static HRESULT WINAPI EnumSTATDATA_Skip(IEnumSTATDATA *iface, ULONG num)
158 EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
160 TRACE("(%d)\n", num);
162 if(This->index + num >= This->num_of_elems)
164 This->index = This->num_of_elems;
172 static HRESULT WINAPI EnumSTATDATA_Reset(IEnumSTATDATA *iface)
174 EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
182 static HRESULT WINAPI EnumSTATDATA_Clone(IEnumSTATDATA *iface, IEnumSTATDATA **ppenum)
184 EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
186 return EnumSTATDATA_Construct(This->holder, This->index, This->num_of_elems, This->statdata, ppenum);
189 static const IEnumSTATDATAVtbl EnumSTATDATA_VTable =
191 EnumSTATDATA_QueryInterface,
193 EnumSTATDATA_Release,
200 static HRESULT EnumSTATDATA_Construct(IUnknown *holder, ULONG index, DWORD array_len, STATDATA *data,
201 IEnumSTATDATA **ppenum)
203 EnumSTATDATA *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
206 if (!This) return E_OUTOFMEMORY;
208 This->IEnumSTATDATA_iface.lpVtbl = &EnumSTATDATA_VTable;
212 This->statdata = HeapAlloc(GetProcessHeap(), 0, array_len * sizeof(*This->statdata));
215 HeapFree(GetProcessHeap(), 0, This);
216 return E_OUTOFMEMORY;
219 for(i = 0, count = 0; i < array_len; i++)
223 copy_statdata(This->statdata + count, data + i);
228 This->num_of_elems = count;
229 This->holder = holder;
230 IUnknown_AddRef(holder);
231 *ppenum = &This->IEnumSTATDATA_iface;
235 /**************************************************************************
236 * OleAdviseHolder Implementation
240 IOleAdviseHolder IOleAdviseHolder_iface;
245 IAdviseSink** arrayOfSinks;
246 } OleAdviseHolderImpl;
248 static inline OleAdviseHolderImpl *impl_from_IOleAdviseHolder(IOleAdviseHolder *iface)
250 return CONTAINING_RECORD(iface, OleAdviseHolderImpl, IOleAdviseHolder_iface);
253 /**************************************************************************
254 * OleAdviseHolderImpl_Destructor
256 static void OleAdviseHolderImpl_Destructor(OleAdviseHolderImpl* ptrToDestroy)
259 TRACE("%p\n", ptrToDestroy);
261 for (index = 0; index < ptrToDestroy->maxSinks; index++)
263 if (ptrToDestroy->arrayOfSinks[index]!=0)
265 IAdviseSink_Release(ptrToDestroy->arrayOfSinks[index]);
266 ptrToDestroy->arrayOfSinks[index] = NULL;
270 HeapFree(GetProcessHeap(),
272 ptrToDestroy->arrayOfSinks);
275 HeapFree(GetProcessHeap(),
280 /**************************************************************************
281 * OleAdviseHolderImpl_QueryInterface
283 static HRESULT WINAPI OleAdviseHolderImpl_QueryInterface(IOleAdviseHolder *iface,
284 REFIID iid, void **obj)
286 OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
287 TRACE("(%p)->(%s,%p)\n",This, debugstr_guid(iid), obj);
294 if (IsEqualIID(iid, &IID_IUnknown) ||
295 IsEqualIID(iid, &IID_IOleAdviseHolder))
297 *obj = &This->IOleAdviseHolder_iface;
301 return E_NOINTERFACE;
303 IUnknown_AddRef((IUnknown*)*obj);
308 /******************************************************************************
309 * OleAdviseHolderImpl_AddRef
311 static ULONG WINAPI OleAdviseHolderImpl_AddRef(IOleAdviseHolder *iface)
313 OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
314 ULONG ref = InterlockedIncrement(&This->ref);
316 TRACE("(%p)->(ref=%d)\n", This, ref - 1);
321 /******************************************************************************
322 * OleAdviseHolderImpl_Release
324 static ULONG WINAPI OleAdviseHolderImpl_Release(IOleAdviseHolder *iface)
326 OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
328 TRACE("(%p)->(ref=%d)\n", This, This->ref);
329 ref = InterlockedDecrement(&This->ref);
331 if (ref == 0) OleAdviseHolderImpl_Destructor(This);
336 /******************************************************************************
337 * OleAdviseHolderImpl_Advise
339 static HRESULT WINAPI OleAdviseHolderImpl_Advise(IOleAdviseHolder *iface,
340 IAdviseSink *pAdvise,
341 DWORD *pdwConnection)
344 OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
346 TRACE("(%p)->(%p, %p)\n", This, pAdvise, pdwConnection);
348 if (pdwConnection==NULL)
353 for (index = 0; index < This->maxSinks; index++)
355 if (This->arrayOfSinks[index]==NULL)
359 if (index == This->maxSinks)
363 This->maxSinks+=INITIAL_SINKS;
365 This->arrayOfSinks = HeapReAlloc(GetProcessHeap(),
368 This->maxSinks*sizeof(IAdviseSink*));
370 for (i=index;i < This->maxSinks; i++)
371 This->arrayOfSinks[i]=0;
374 This->arrayOfSinks[index] = pAdvise;
376 if (This->arrayOfSinks[index]!=NULL)
377 IAdviseSink_AddRef(This->arrayOfSinks[index]);
380 * Return the index as the cookie.
381 * Since 0 is not a valid cookie, we will increment by
382 * 1 the index in the table.
384 *pdwConnection = index+1;
389 /******************************************************************************
390 * OleAdviseHolderImpl_Unadvise
392 static HRESULT WINAPI OleAdviseHolderImpl_Unadvise(IOleAdviseHolder *iface,
395 OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
397 TRACE("(%p)->(%u)\n", This, dwConnection);
400 * So we don't return 0 as a cookie, the index was
401 * incremented by 1 in OleAdviseHolderImpl_Advise
402 * we have to compensate.
407 * Check for invalid cookies.
409 if (dwConnection >= This->maxSinks)
410 return OLE_E_NOCONNECTION;
412 if (This->arrayOfSinks[dwConnection] == NULL)
413 return OLE_E_NOCONNECTION;
416 * Release the sink and mark the spot in the list as free.
418 IAdviseSink_Release(This->arrayOfSinks[dwConnection]);
419 This->arrayOfSinks[dwConnection] = NULL;
424 /******************************************************************************
425 * OleAdviseHolderImpl_EnumAdvise
427 static HRESULT WINAPI OleAdviseHolderImpl_EnumAdvise(IOleAdviseHolder *iface, IEnumSTATDATA **ppenumAdvise)
429 OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
433 static const FORMATETC empty_fmtetc = {0, NULL, 0, -1, 0};
436 TRACE("(%p)->(%p)\n", This, ppenumAdvise);
438 *ppenumAdvise = NULL;
440 /* Build an array of STATDATA structures */
441 data = HeapAlloc(GetProcessHeap(), 0, This->maxSinks * sizeof(*data));
442 if(!data) return E_OUTOFMEMORY;
444 for(i = 0, count = 0; i < This->maxSinks; i++)
446 if(This->arrayOfSinks[i])
448 data[count].formatetc = empty_fmtetc;
449 data[count].advf = 0;
450 data[count].pAdvSink = This->arrayOfSinks[i]; /* The constructor will take a ref. */
451 data[count].dwConnection = i;
456 IOleAdviseHolder_QueryInterface(iface, &IID_IUnknown, (void**)&unk);
457 hr = EnumSTATDATA_Construct(unk, 0, count, data, ppenumAdvise);
458 IUnknown_Release(unk);
459 HeapFree(GetProcessHeap(), 0, data);
464 /******************************************************************************
465 * OleAdviseHolderImpl_SendOnRename
467 static HRESULT WINAPI OleAdviseHolderImpl_SendOnRename(IOleAdviseHolder *iface, IMoniker *pmk)
469 IEnumSTATDATA *pEnum;
472 TRACE("(%p)->(%p)\n", iface, pmk);
474 hr = IOleAdviseHolder_EnumAdvise(iface, &pEnum);
478 while (IEnumSTATDATA_Next(pEnum, 1, &statdata, NULL) == S_OK)
480 IAdviseSink_OnRename(statdata.pAdvSink, pmk);
482 IAdviseSink_Release(statdata.pAdvSink);
484 IEnumSTATDATA_Release(pEnum);
490 /******************************************************************************
491 * OleAdviseHolderImpl_SendOnSave
493 static HRESULT WINAPI OleAdviseHolderImpl_SendOnSave(IOleAdviseHolder *iface)
495 IEnumSTATDATA *pEnum;
498 TRACE("(%p)->()\n", iface);
500 hr = IOleAdviseHolder_EnumAdvise(iface, &pEnum);
504 while (IEnumSTATDATA_Next(pEnum, 1, &statdata, NULL) == S_OK)
506 IAdviseSink_OnSave(statdata.pAdvSink);
508 IAdviseSink_Release(statdata.pAdvSink);
510 IEnumSTATDATA_Release(pEnum);
516 /******************************************************************************
517 * OleAdviseHolderImpl_SendOnClose
519 static HRESULT WINAPI OleAdviseHolderImpl_SendOnClose(IOleAdviseHolder *iface)
521 IEnumSTATDATA *pEnum;
524 TRACE("(%p)->()\n", iface);
526 hr = IOleAdviseHolder_EnumAdvise(iface, &pEnum);
530 while (IEnumSTATDATA_Next(pEnum, 1, &statdata, NULL) == S_OK)
532 IAdviseSink_OnClose(statdata.pAdvSink);
534 IAdviseSink_Release(statdata.pAdvSink);
536 IEnumSTATDATA_Release(pEnum);
542 /**************************************************************************
543 * OleAdviseHolderImpl_VTable
545 static const IOleAdviseHolderVtbl oahvt =
547 OleAdviseHolderImpl_QueryInterface,
548 OleAdviseHolderImpl_AddRef,
549 OleAdviseHolderImpl_Release,
550 OleAdviseHolderImpl_Advise,
551 OleAdviseHolderImpl_Unadvise,
552 OleAdviseHolderImpl_EnumAdvise,
553 OleAdviseHolderImpl_SendOnRename,
554 OleAdviseHolderImpl_SendOnSave,
555 OleAdviseHolderImpl_SendOnClose
558 /**************************************************************************
559 * OleAdviseHolderImpl_Constructor
562 static IOleAdviseHolder *OleAdviseHolderImpl_Constructor(void)
564 OleAdviseHolderImpl* lpoah;
567 lpoah = HeapAlloc(GetProcessHeap(), 0, sizeof(OleAdviseHolderImpl));
569 lpoah->IOleAdviseHolder_iface.lpVtbl = &oahvt;
571 lpoah->maxSinks = INITIAL_SINKS;
572 lpoah->arrayOfSinks = HeapAlloc(GetProcessHeap(),
574 lpoah->maxSinks * sizeof(IAdviseSink*));
576 for (index = 0; index < lpoah->maxSinks; index++)
577 lpoah->arrayOfSinks[index]=0;
579 TRACE("returning %p\n", &lpoah->IOleAdviseHolder_iface);
580 return &lpoah->IOleAdviseHolder_iface;
583 /**************************************************************************
584 * DataAdviseHolder Implementation
588 IDataAdviseHolder IDataAdviseHolder_iface;
592 STATDATA* connections;
593 DWORD* remote_connections;
594 IDataObject* delegate;
597 /* this connection has also has been advised to the delegate data object */
598 #define WINE_ADVF_REMOTE 0x80000000
600 static inline DataAdviseHolder *impl_from_IDataAdviseHolder(IDataAdviseHolder *iface)
602 return CONTAINING_RECORD(iface, DataAdviseHolder, IDataAdviseHolder_iface);
605 /******************************************************************************
606 * DataAdviseHolder_Destructor
608 static void DataAdviseHolder_Destructor(DataAdviseHolder* ptrToDestroy)
611 TRACE("%p\n", ptrToDestroy);
613 for (index = 0; index < ptrToDestroy->maxCons; index++)
615 if (ptrToDestroy->connections[index].pAdvSink != NULL)
617 if (ptrToDestroy->delegate &&
618 (ptrToDestroy->connections[index].advf & WINE_ADVF_REMOTE))
619 IDataObject_DUnadvise(ptrToDestroy->delegate,
620 ptrToDestroy->remote_connections[index]);
622 release_statdata(ptrToDestroy->connections + index);
626 HeapFree(GetProcessHeap(), 0, ptrToDestroy->remote_connections);
627 HeapFree(GetProcessHeap(), 0, ptrToDestroy->connections);
628 HeapFree(GetProcessHeap(), 0, ptrToDestroy);
631 /************************************************************************
632 * DataAdviseHolder_QueryInterface (IUnknown)
634 static HRESULT WINAPI DataAdviseHolder_QueryInterface(IDataAdviseHolder *iface,
635 REFIID riid, void **ppvObject)
637 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
638 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObject);
640 if ( (This==0) || (ppvObject==0) )
645 if ( IsEqualIID(&IID_IUnknown, riid) ||
646 IsEqualIID(&IID_IDataAdviseHolder, riid) )
653 return E_NOINTERFACE;
656 IUnknown_AddRef((IUnknown*)*ppvObject);
660 /************************************************************************
661 * DataAdviseHolder_AddRef (IUnknown)
663 static ULONG WINAPI DataAdviseHolder_AddRef(IDataAdviseHolder *iface)
665 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
666 TRACE("(%p) (ref=%d)\n", This, This->ref);
667 return InterlockedIncrement(&This->ref);
670 /************************************************************************
671 * DataAdviseHolder_Release (IUnknown)
673 static ULONG WINAPI DataAdviseHolder_Release(IDataAdviseHolder *iface)
675 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
677 TRACE("(%p) (ref=%d)\n", This, This->ref);
679 ref = InterlockedDecrement(&This->ref);
680 if (ref==0) DataAdviseHolder_Destructor(This);
685 /************************************************************************
686 * DataAdviseHolder_Advise
689 static HRESULT WINAPI DataAdviseHolder_Advise(IDataAdviseHolder *iface,
690 IDataObject *pDataObject, FORMATETC *pFetc,
691 DWORD advf, IAdviseSink *pAdvise,
692 DWORD *pdwConnection)
696 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
698 TRACE("(%p)->(%p, %p, %08x, %p, %p)\n", This, pDataObject, pFetc, advf,
699 pAdvise, pdwConnection);
701 if (pdwConnection==NULL)
706 for (index = 0; index < This->maxCons; index++)
708 if (This->connections[index].pAdvSink == NULL)
712 if (index == This->maxCons)
714 This->maxCons+=INITIAL_SINKS;
715 This->connections = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
717 This->maxCons * sizeof(*This->connections));
718 This->remote_connections = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
719 This->remote_connections,
720 This->maxCons * sizeof(*This->remote_connections));
723 new_conn.pAdvSink = pAdvise;
724 new_conn.advf = advf & ~WINE_ADVF_REMOTE;
725 new_conn.formatetc = *pFetc;
726 new_conn.dwConnection = index + 1; /* 0 is not a valid cookie, so increment the index */
728 copy_statdata(This->connections + index, &new_conn);
730 if (This->connections[index].pAdvSink != NULL)
732 /* if we are already connected advise the remote object */
737 hr = IDataObject_DAdvise(This->delegate, &new_conn.formatetc,
738 new_conn.advf, new_conn.pAdvSink,
739 &This->remote_connections[index]);
742 IDataAdviseHolder_Unadvise(iface, new_conn.dwConnection);
745 This->connections[index].advf |= WINE_ADVF_REMOTE;
747 else if(advf & ADVF_PRIMEFIRST)
748 /* only do this if we have no delegate, since in the above case the
749 * delegate will do the priming for us */
750 IDataAdviseHolder_SendOnDataChange(iface, pDataObject, 0, advf);
753 *pdwConnection = new_conn.dwConnection;
758 /******************************************************************************
759 * DataAdviseHolder_Unadvise
761 static HRESULT WINAPI DataAdviseHolder_Unadvise(IDataAdviseHolder *iface,
764 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
766 TRACE("(%p)->(%u)\n", This, dwConnection);
768 /* The connection number is 1 more than the index, see DataAdviseHolder_Advise */
769 index = dwConnection - 1;
771 if (index >= This->maxCons || This->connections[index].pAdvSink == NULL)
772 return OLE_E_NOCONNECTION;
774 if (This->delegate && This->connections[index].advf & WINE_ADVF_REMOTE)
776 IDataObject_DUnadvise(This->delegate, This->remote_connections[index]);
777 This->remote_connections[index] = 0;
780 release_statdata(This->connections + index);
785 /******************************************************************************
786 * DataAdviseHolder_EnumAdvise
788 static HRESULT WINAPI DataAdviseHolder_EnumAdvise(IDataAdviseHolder *iface,
789 IEnumSTATDATA **enum_advise)
791 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
795 TRACE("(%p)->(%p)\n", This, enum_advise);
797 IDataAdviseHolder_QueryInterface(iface, &IID_IUnknown, (void**)&unk);
798 hr = EnumSTATDATA_Construct(unk, 0, This->maxCons, This->connections, enum_advise);
799 IUnknown_Release(unk);
803 /******************************************************************************
804 * DataAdviseHolder_SendOnDataChange
806 static HRESULT WINAPI DataAdviseHolder_SendOnDataChange(IDataAdviseHolder *iface,
807 IDataObject *pDataObject,
808 DWORD dwReserved, DWORD advf)
810 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
815 TRACE("(%p)->(%p,%08x,%08x)\n", This, pDataObject, dwReserved, advf);
817 for(index = 0; index < This->maxCons; index++)
819 if(This->connections[index].pAdvSink != NULL)
821 memset(&stg, 0, sizeof(stg));
822 if(!(This->connections[index].advf & ADVF_NODATA))
824 TRACE("Calling IDataObject_GetData\n");
825 res = IDataObject_GetData(pDataObject,
826 &(This->connections[index].formatetc),
828 TRACE("returns %08x\n", res);
830 TRACE("Calling IAdviseSink_OnDataChange\n");
831 IAdviseSink_OnDataChange(This->connections[index].pAdvSink,
832 &(This->connections[index].formatetc),
834 TRACE("Done IAdviseSink_OnDataChange\n");
835 if(This->connections[index].advf & ADVF_ONLYONCE) {
836 TRACE("Removing connection\n");
837 DataAdviseHolder_Unadvise(iface, This->connections[index].dwConnection);
844 /**************************************************************************
845 * DataAdviseHolderImpl_VTable
847 static const IDataAdviseHolderVtbl DataAdviseHolderImpl_VTable =
849 DataAdviseHolder_QueryInterface,
850 DataAdviseHolder_AddRef,
851 DataAdviseHolder_Release,
852 DataAdviseHolder_Advise,
853 DataAdviseHolder_Unadvise,
854 DataAdviseHolder_EnumAdvise,
855 DataAdviseHolder_SendOnDataChange
858 HRESULT DataAdviseHolder_OnConnect(IDataAdviseHolder *iface, IDataObject *pDelegate)
860 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
864 for(index = 0; index < This->maxCons; index++)
866 if(This->connections[index].pAdvSink != NULL)
868 hr = IDataObject_DAdvise(pDelegate, &This->connections[index].formatetc,
869 This->connections[index].advf,
870 This->connections[index].pAdvSink,
871 &This->remote_connections[index]);
872 if (FAILED(hr)) break;
873 This->connections[index].advf |= WINE_ADVF_REMOTE;
876 This->delegate = pDelegate;
880 void DataAdviseHolder_OnDisconnect(IDataAdviseHolder *iface)
882 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
885 for(index = 0; index < This->maxCons; index++)
887 if((This->connections[index].pAdvSink != NULL) &&
888 (This->connections[index].advf & WINE_ADVF_REMOTE))
890 IDataObject_DUnadvise(This->delegate, This->remote_connections[index]);
891 This->remote_connections[index] = 0;
892 This->connections[index].advf &= ~WINE_ADVF_REMOTE;
895 This->delegate = NULL;
898 /******************************************************************************
899 * DataAdviseHolder_Constructor
901 static IDataAdviseHolder *DataAdviseHolder_Constructor(void)
903 DataAdviseHolder* newHolder;
905 newHolder = HeapAlloc(GetProcessHeap(), 0, sizeof(DataAdviseHolder));
907 newHolder->IDataAdviseHolder_iface.lpVtbl = &DataAdviseHolderImpl_VTable;
909 newHolder->maxCons = INITIAL_SINKS;
910 newHolder->connections = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
911 newHolder->maxCons * sizeof(*newHolder->connections));
912 newHolder->remote_connections = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
913 newHolder->maxCons * sizeof(*newHolder->remote_connections));
914 newHolder->delegate = NULL;
916 TRACE("returning %p\n", &newHolder->IDataAdviseHolder_iface);
917 return &newHolder->IDataAdviseHolder_iface;
920 /***********************************************************************
924 /***********************************************************************
925 * CreateOleAdviseHolder [OLE32.@]
927 HRESULT WINAPI CreateOleAdviseHolder(IOleAdviseHolder **ppOAHolder)
929 TRACE("(%p)\n", ppOAHolder);
931 if (ppOAHolder==NULL)
934 *ppOAHolder = OleAdviseHolderImpl_Constructor ();
936 if (*ppOAHolder != NULL)
939 return E_OUTOFMEMORY;
942 /******************************************************************************
943 * CreateDataAdviseHolder [OLE32.@]
945 HRESULT WINAPI CreateDataAdviseHolder(IDataAdviseHolder **ppDAHolder)
947 TRACE("(%p)\n", ppDAHolder);
949 if (ppDAHolder==NULL)
952 *ppDAHolder = DataAdviseHolder_Constructor();
954 if (*ppDAHolder != NULL)
957 return E_OUTOFMEMORY;