Release 1.9.16.
[wine.git] / dlls / ole32 / oleobj.c
blobedbef554c52f6584a8a4d42f214fca1b815a9017
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
27 #define NONAMELESSUNION
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winuser.h"
32 #include "winerror.h"
33 #include "wine/debug.h"
34 #include "ole2.h"
36 #include "compobj_private.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(ole);
40 #define INITIAL_SINKS 10
42 static void release_statdata(STATDATA *data)
44 if(data->formatetc.ptd)
46 CoTaskMemFree(data->formatetc.ptd);
47 data->formatetc.ptd = NULL;
50 if(data->pAdvSink)
52 IAdviseSink_Release(data->pAdvSink);
53 data->pAdvSink = NULL;
57 static HRESULT copy_statdata(STATDATA *dst, const STATDATA *src)
59 *dst = *src;
60 if(src->formatetc.ptd)
62 dst->formatetc.ptd = CoTaskMemAlloc(src->formatetc.ptd->tdSize);
63 if(!dst->formatetc.ptd) return E_OUTOFMEMORY;
64 memcpy(dst->formatetc.ptd, src->formatetc.ptd, src->formatetc.ptd->tdSize);
66 if(dst->pAdvSink) IAdviseSink_AddRef(dst->pAdvSink);
67 return S_OK;
70 /**************************************************************************
71 * EnumSTATDATA Implementation
74 static HRESULT EnumSTATDATA_Construct(IUnknown *holder, ULONG index, DWORD array_len, STATDATA *data, IEnumSTATDATA **ppenum);
76 typedef struct
78 IEnumSTATDATA IEnumSTATDATA_iface;
79 LONG ref;
81 ULONG index;
82 DWORD num_of_elems;
83 STATDATA *statdata;
84 IUnknown *holder;
85 } EnumSTATDATA;
87 static inline EnumSTATDATA *impl_from_IEnumSTATDATA(IEnumSTATDATA *iface)
89 return CONTAINING_RECORD(iface, EnumSTATDATA, IEnumSTATDATA_iface);
92 static HRESULT WINAPI EnumSTATDATA_QueryInterface(IEnumSTATDATA *iface, REFIID riid, void **ppv)
94 TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
95 if (IsEqualIID(riid, &IID_IUnknown) ||
96 IsEqualIID(riid, &IID_IEnumSTATDATA))
98 IEnumSTATDATA_AddRef(iface);
99 *ppv = iface;
100 return S_OK;
102 return E_NOINTERFACE;
105 static ULONG WINAPI EnumSTATDATA_AddRef(IEnumSTATDATA *iface)
107 EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
108 TRACE("()\n");
109 return InterlockedIncrement(&This->ref);
112 static ULONG WINAPI EnumSTATDATA_Release(IEnumSTATDATA *iface)
114 EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
115 LONG refs = InterlockedDecrement(&This->ref);
116 TRACE("()\n");
117 if (!refs)
119 DWORD i;
120 for(i = 0; i < This->num_of_elems; i++)
121 release_statdata(This->statdata + i);
122 HeapFree(GetProcessHeap(), 0, This->statdata);
123 IUnknown_Release(This->holder);
124 HeapFree(GetProcessHeap(), 0, This);
126 return refs;
129 static HRESULT WINAPI EnumSTATDATA_Next(IEnumSTATDATA *iface, ULONG num, LPSTATDATA data,
130 ULONG *fetched)
132 EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
133 DWORD count = 0;
134 HRESULT hr = S_OK;
136 TRACE("(%d, %p, %p)\n", num, data, fetched);
138 while(num--)
140 if (This->index >= This->num_of_elems)
142 hr = S_FALSE;
143 break;
146 copy_statdata(data + count, This->statdata + This->index);
148 count++;
149 This->index++;
152 if (fetched) *fetched = count;
154 return hr;
157 static HRESULT WINAPI EnumSTATDATA_Skip(IEnumSTATDATA *iface, ULONG num)
159 EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
161 TRACE("(%d)\n", num);
163 if(This->index + num >= This->num_of_elems)
165 This->index = This->num_of_elems;
166 return S_FALSE;
169 This->index += num;
170 return S_OK;
173 static HRESULT WINAPI EnumSTATDATA_Reset(IEnumSTATDATA *iface)
175 EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
177 TRACE("()\n");
179 This->index = 0;
180 return S_OK;
183 static HRESULT WINAPI EnumSTATDATA_Clone(IEnumSTATDATA *iface, IEnumSTATDATA **ppenum)
185 EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
187 return EnumSTATDATA_Construct(This->holder, This->index, This->num_of_elems, This->statdata, ppenum);
190 static const IEnumSTATDATAVtbl EnumSTATDATA_VTable =
192 EnumSTATDATA_QueryInterface,
193 EnumSTATDATA_AddRef,
194 EnumSTATDATA_Release,
195 EnumSTATDATA_Next,
196 EnumSTATDATA_Skip,
197 EnumSTATDATA_Reset,
198 EnumSTATDATA_Clone
201 static HRESULT EnumSTATDATA_Construct(IUnknown *holder, ULONG index, DWORD array_len, STATDATA *data,
202 IEnumSTATDATA **ppenum)
204 EnumSTATDATA *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
205 DWORD i, count;
207 if (!This) return E_OUTOFMEMORY;
209 This->IEnumSTATDATA_iface.lpVtbl = &EnumSTATDATA_VTable;
210 This->ref = 1;
211 This->index = index;
213 This->statdata = HeapAlloc(GetProcessHeap(), 0, array_len * sizeof(*This->statdata));
214 if(!This->statdata)
216 HeapFree(GetProcessHeap(), 0, This);
217 return E_OUTOFMEMORY;
220 for(i = 0, count = 0; i < array_len; i++)
222 if(data[i].pAdvSink)
224 copy_statdata(This->statdata + count, data + i);
225 count++;
229 This->num_of_elems = count;
230 This->holder = holder;
231 IUnknown_AddRef(holder);
232 *ppenum = &This->IEnumSTATDATA_iface;
233 return S_OK;
236 /**************************************************************************
237 * OleAdviseHolder Implementation
239 typedef struct
241 IOleAdviseHolder IOleAdviseHolder_iface;
243 LONG ref;
245 DWORD max_cons;
246 STATDATA *connections;
247 } OleAdviseHolderImpl;
249 static inline OleAdviseHolderImpl *impl_from_IOleAdviseHolder(IOleAdviseHolder *iface)
251 return CONTAINING_RECORD(iface, OleAdviseHolderImpl, IOleAdviseHolder_iface);
254 /**************************************************************************
255 * OleAdviseHolderImpl_Destructor
257 static void OleAdviseHolderImpl_Destructor(OleAdviseHolderImpl *This)
259 DWORD index;
260 TRACE("%p\n", This);
262 for (index = 0; index < This->max_cons; index++)
264 if (This->connections[index].pAdvSink != NULL)
265 release_statdata(This->connections + index);
268 HeapFree(GetProcessHeap(), 0, This->connections);
269 HeapFree(GetProcessHeap(), 0, This);
272 /**************************************************************************
273 * OleAdviseHolderImpl_QueryInterface
275 static HRESULT WINAPI OleAdviseHolderImpl_QueryInterface(IOleAdviseHolder *iface,
276 REFIID iid, void **obj)
278 OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
279 TRACE("(%p)->(%s,%p)\n",This, debugstr_guid(iid), obj);
281 if (obj == NULL)
282 return E_POINTER;
284 *obj = NULL;
286 if (IsEqualIID(iid, &IID_IUnknown) ||
287 IsEqualIID(iid, &IID_IOleAdviseHolder))
289 *obj = &This->IOleAdviseHolder_iface;
292 if(*obj == NULL)
293 return E_NOINTERFACE;
295 IUnknown_AddRef((IUnknown*)*obj);
297 return S_OK;
300 /******************************************************************************
301 * OleAdviseHolderImpl_AddRef
303 static ULONG WINAPI OleAdviseHolderImpl_AddRef(IOleAdviseHolder *iface)
305 OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
306 ULONG ref = InterlockedIncrement(&This->ref);
308 TRACE("(%p)->(ref=%d)\n", This, ref - 1);
310 return ref;
313 /******************************************************************************
314 * OleAdviseHolderImpl_Release
316 static ULONG WINAPI OleAdviseHolderImpl_Release(IOleAdviseHolder *iface)
318 OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
319 ULONG ref;
320 TRACE("(%p)->(ref=%d)\n", This, This->ref);
321 ref = InterlockedDecrement(&This->ref);
323 if (ref == 0) OleAdviseHolderImpl_Destructor(This);
325 return ref;
328 /******************************************************************************
329 * OleAdviseHolderImpl_Advise
331 static HRESULT WINAPI OleAdviseHolderImpl_Advise(IOleAdviseHolder *iface,
332 IAdviseSink *pAdvise,
333 DWORD *pdwConnection)
335 DWORD index;
336 OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
337 STATDATA new_conn;
338 static const FORMATETC empty_fmtetc = {0, NULL, 0, -1, 0};
340 TRACE("(%p)->(%p, %p)\n", This, pAdvise, pdwConnection);
342 if (pdwConnection==NULL)
343 return E_POINTER;
345 *pdwConnection = 0;
347 for (index = 0; index < This->max_cons; index++)
349 if (This->connections[index].pAdvSink == NULL)
350 break;
353 if (index == This->max_cons)
355 This->max_cons += INITIAL_SINKS;
356 This->connections = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->connections,
357 This->max_cons * sizeof(*This->connections));
360 new_conn.pAdvSink = pAdvise;
361 new_conn.advf = 0;
362 new_conn.formatetc = empty_fmtetc;
363 new_conn.dwConnection = index + 1; /* 0 is not a valid cookie, so increment the index */
365 copy_statdata(This->connections + index, &new_conn);
367 *pdwConnection = new_conn.dwConnection;
369 return S_OK;
372 /******************************************************************************
373 * OleAdviseHolderImpl_Unadvise
375 static HRESULT WINAPI OleAdviseHolderImpl_Unadvise(IOleAdviseHolder *iface,
376 DWORD dwConnection)
378 OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
379 DWORD index;
381 TRACE("(%p)->(%u)\n", This, dwConnection);
383 /* The connection number is 1 more than the index, see OleAdviseHolder_Advise */
384 index = dwConnection - 1;
386 if (index >= This->max_cons || This->connections[index].pAdvSink == NULL)
387 return OLE_E_NOCONNECTION;
389 release_statdata(This->connections + index);
391 return S_OK;
394 /******************************************************************************
395 * OleAdviseHolderImpl_EnumAdvise
397 static HRESULT WINAPI OleAdviseHolderImpl_EnumAdvise(IOleAdviseHolder *iface, IEnumSTATDATA **enum_advise)
399 OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
400 IUnknown *unk;
401 HRESULT hr;
403 TRACE("(%p)->(%p)\n", This, enum_advise);
405 IOleAdviseHolder_QueryInterface(iface, &IID_IUnknown, (void**)&unk);
406 hr = EnumSTATDATA_Construct(unk, 0, This->max_cons, This->connections, enum_advise);
407 IUnknown_Release(unk);
408 return hr;
411 /******************************************************************************
412 * OleAdviseHolderImpl_SendOnRename
414 static HRESULT WINAPI OleAdviseHolderImpl_SendOnRename(IOleAdviseHolder *iface, IMoniker *pmk)
416 IEnumSTATDATA *pEnum;
417 HRESULT hr;
419 TRACE("(%p)->(%p)\n", iface, pmk);
421 hr = IOleAdviseHolder_EnumAdvise(iface, &pEnum);
422 if (SUCCEEDED(hr))
424 STATDATA statdata;
425 while (IEnumSTATDATA_Next(pEnum, 1, &statdata, NULL) == S_OK)
427 IAdviseSink_OnRename(statdata.pAdvSink, pmk);
429 IAdviseSink_Release(statdata.pAdvSink);
431 IEnumSTATDATA_Release(pEnum);
434 return hr;
437 /******************************************************************************
438 * OleAdviseHolderImpl_SendOnSave
440 static HRESULT WINAPI OleAdviseHolderImpl_SendOnSave(IOleAdviseHolder *iface)
442 IEnumSTATDATA *pEnum;
443 HRESULT hr;
445 TRACE("(%p)->()\n", iface);
447 hr = IOleAdviseHolder_EnumAdvise(iface, &pEnum);
448 if (SUCCEEDED(hr))
450 STATDATA statdata;
451 while (IEnumSTATDATA_Next(pEnum, 1, &statdata, NULL) == S_OK)
453 IAdviseSink_OnSave(statdata.pAdvSink);
455 IAdviseSink_Release(statdata.pAdvSink);
457 IEnumSTATDATA_Release(pEnum);
460 return hr;
463 /******************************************************************************
464 * OleAdviseHolderImpl_SendOnClose
466 static HRESULT WINAPI OleAdviseHolderImpl_SendOnClose(IOleAdviseHolder *iface)
468 IEnumSTATDATA *pEnum;
469 HRESULT hr;
471 TRACE("(%p)->()\n", iface);
473 hr = IOleAdviseHolder_EnumAdvise(iface, &pEnum);
474 if (SUCCEEDED(hr))
476 STATDATA statdata;
477 while (IEnumSTATDATA_Next(pEnum, 1, &statdata, NULL) == S_OK)
479 IAdviseSink_OnClose(statdata.pAdvSink);
481 IAdviseSink_Release(statdata.pAdvSink);
483 IEnumSTATDATA_Release(pEnum);
486 return hr;
489 /**************************************************************************
490 * OleAdviseHolderImpl_VTable
492 static const IOleAdviseHolderVtbl oahvt =
494 OleAdviseHolderImpl_QueryInterface,
495 OleAdviseHolderImpl_AddRef,
496 OleAdviseHolderImpl_Release,
497 OleAdviseHolderImpl_Advise,
498 OleAdviseHolderImpl_Unadvise,
499 OleAdviseHolderImpl_EnumAdvise,
500 OleAdviseHolderImpl_SendOnRename,
501 OleAdviseHolderImpl_SendOnSave,
502 OleAdviseHolderImpl_SendOnClose
505 /**************************************************************************
506 * OleAdviseHolderImpl_Constructor
509 static IOleAdviseHolder *OleAdviseHolderImpl_Constructor(void)
511 OleAdviseHolderImpl* lpoah;
513 lpoah = HeapAlloc(GetProcessHeap(), 0, sizeof(OleAdviseHolderImpl));
515 lpoah->IOleAdviseHolder_iface.lpVtbl = &oahvt;
516 lpoah->ref = 1;
517 lpoah->max_cons = INITIAL_SINKS;
518 lpoah->connections = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
519 lpoah->max_cons * sizeof(*lpoah->connections));
521 TRACE("returning %p\n", &lpoah->IOleAdviseHolder_iface);
522 return &lpoah->IOleAdviseHolder_iface;
525 /**************************************************************************
526 * DataAdviseHolder Implementation
528 typedef struct
530 IDataAdviseHolder IDataAdviseHolder_iface;
532 LONG ref;
533 DWORD maxCons;
534 STATDATA* connections;
535 DWORD* remote_connections;
536 IDataObject* delegate;
537 } DataAdviseHolder;
539 /* this connection has also has been advised to the delegate data object */
540 #define WINE_ADVF_REMOTE 0x80000000
542 static inline DataAdviseHolder *impl_from_IDataAdviseHolder(IDataAdviseHolder *iface)
544 return CONTAINING_RECORD(iface, DataAdviseHolder, IDataAdviseHolder_iface);
547 /******************************************************************************
548 * DataAdviseHolder_Destructor
550 static void DataAdviseHolder_Destructor(DataAdviseHolder* ptrToDestroy)
552 DWORD index;
553 TRACE("%p\n", ptrToDestroy);
555 for (index = 0; index < ptrToDestroy->maxCons; index++)
557 if (ptrToDestroy->connections[index].pAdvSink != NULL)
559 if (ptrToDestroy->delegate &&
560 (ptrToDestroy->connections[index].advf & WINE_ADVF_REMOTE))
561 IDataObject_DUnadvise(ptrToDestroy->delegate,
562 ptrToDestroy->remote_connections[index]);
564 release_statdata(ptrToDestroy->connections + index);
568 HeapFree(GetProcessHeap(), 0, ptrToDestroy->remote_connections);
569 HeapFree(GetProcessHeap(), 0, ptrToDestroy->connections);
570 HeapFree(GetProcessHeap(), 0, ptrToDestroy);
573 /************************************************************************
574 * DataAdviseHolder_QueryInterface (IUnknown)
576 static HRESULT WINAPI DataAdviseHolder_QueryInterface(IDataAdviseHolder *iface,
577 REFIID riid, void **ppvObject)
579 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
580 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObject);
582 if ( (This==0) || (ppvObject==0) )
583 return E_INVALIDARG;
585 *ppvObject = 0;
587 if ( IsEqualIID(&IID_IUnknown, riid) ||
588 IsEqualIID(&IID_IDataAdviseHolder, riid) )
590 *ppvObject = iface;
593 if ((*ppvObject)==0)
595 return E_NOINTERFACE;
598 IUnknown_AddRef((IUnknown*)*ppvObject);
599 return S_OK;
602 /************************************************************************
603 * DataAdviseHolder_AddRef (IUnknown)
605 static ULONG WINAPI DataAdviseHolder_AddRef(IDataAdviseHolder *iface)
607 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
608 TRACE("(%p) (ref=%d)\n", This, This->ref);
609 return InterlockedIncrement(&This->ref);
612 /************************************************************************
613 * DataAdviseHolder_Release (IUnknown)
615 static ULONG WINAPI DataAdviseHolder_Release(IDataAdviseHolder *iface)
617 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
618 ULONG ref;
619 TRACE("(%p) (ref=%d)\n", This, This->ref);
621 ref = InterlockedDecrement(&This->ref);
622 if (ref==0) DataAdviseHolder_Destructor(This);
624 return ref;
627 /************************************************************************
628 * DataAdviseHolder_Advise
631 static HRESULT WINAPI DataAdviseHolder_Advise(IDataAdviseHolder *iface,
632 IDataObject *pDataObject, FORMATETC *pFetc,
633 DWORD advf, IAdviseSink *pAdvise,
634 DWORD *pdwConnection)
636 DWORD index;
637 STATDATA new_conn;
638 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
640 TRACE("(%p)->(%p, %p, %08x, %p, %p)\n", This, pDataObject, pFetc, advf,
641 pAdvise, pdwConnection);
643 if (pdwConnection==NULL)
644 return E_POINTER;
646 *pdwConnection = 0;
648 for (index = 0; index < This->maxCons; index++)
650 if (This->connections[index].pAdvSink == NULL)
651 break;
654 if (index == This->maxCons)
656 This->maxCons+=INITIAL_SINKS;
657 This->connections = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
658 This->connections,
659 This->maxCons * sizeof(*This->connections));
660 This->remote_connections = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
661 This->remote_connections,
662 This->maxCons * sizeof(*This->remote_connections));
665 new_conn.pAdvSink = pAdvise;
666 new_conn.advf = advf & ~WINE_ADVF_REMOTE;
667 new_conn.formatetc = *pFetc;
668 new_conn.dwConnection = index + 1; /* 0 is not a valid cookie, so increment the index */
670 copy_statdata(This->connections + index, &new_conn);
672 if (This->connections[index].pAdvSink != NULL)
674 /* if we are already connected advise the remote object */
675 if (This->delegate)
677 HRESULT hr;
679 hr = IDataObject_DAdvise(This->delegate, &new_conn.formatetc,
680 new_conn.advf, new_conn.pAdvSink,
681 &This->remote_connections[index]);
682 if (FAILED(hr))
684 IDataAdviseHolder_Unadvise(iface, new_conn.dwConnection);
685 return hr;
687 This->connections[index].advf |= WINE_ADVF_REMOTE;
689 else if(advf & ADVF_PRIMEFIRST)
690 /* only do this if we have no delegate, since in the above case the
691 * delegate will do the priming for us */
692 IDataAdviseHolder_SendOnDataChange(iface, pDataObject, 0, advf);
695 *pdwConnection = new_conn.dwConnection;
697 return S_OK;
700 /******************************************************************************
701 * DataAdviseHolder_Unadvise
703 static HRESULT WINAPI DataAdviseHolder_Unadvise(IDataAdviseHolder *iface,
704 DWORD dwConnection)
706 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
707 DWORD index;
708 TRACE("(%p)->(%u)\n", This, dwConnection);
710 /* The connection number is 1 more than the index, see DataAdviseHolder_Advise */
711 index = dwConnection - 1;
713 if (index >= This->maxCons || This->connections[index].pAdvSink == NULL)
714 return OLE_E_NOCONNECTION;
716 if (This->delegate && This->connections[index].advf & WINE_ADVF_REMOTE)
718 IDataObject_DUnadvise(This->delegate, This->remote_connections[index]);
719 This->remote_connections[index] = 0;
722 release_statdata(This->connections + index);
724 return S_OK;
727 /******************************************************************************
728 * DataAdviseHolder_EnumAdvise
730 static HRESULT WINAPI DataAdviseHolder_EnumAdvise(IDataAdviseHolder *iface,
731 IEnumSTATDATA **enum_advise)
733 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
734 IUnknown *unk;
735 HRESULT hr;
737 TRACE("(%p)->(%p)\n", This, enum_advise);
739 IDataAdviseHolder_QueryInterface(iface, &IID_IUnknown, (void**)&unk);
740 hr = EnumSTATDATA_Construct(unk, 0, This->maxCons, This->connections, enum_advise);
741 IUnknown_Release(unk);
742 return hr;
745 /******************************************************************************
746 * DataAdviseHolder_SendOnDataChange
748 static HRESULT WINAPI DataAdviseHolder_SendOnDataChange(IDataAdviseHolder *iface,
749 IDataObject *data_obj,
750 DWORD dwReserved, DWORD advf)
752 IEnumSTATDATA *pEnum;
753 HRESULT hr;
755 TRACE("(%p)->(%p, %08x, %08x)\n", iface, data_obj, dwReserved, advf);
757 hr = IDataAdviseHolder_EnumAdvise(iface, &pEnum);
758 if (SUCCEEDED(hr))
760 STATDATA statdata;
761 while (IEnumSTATDATA_Next(pEnum, 1, &statdata, NULL) == S_OK)
763 STGMEDIUM stg;
764 stg.tymed = TYMED_NULL;
765 stg.u.pstg = NULL;
766 stg.pUnkForRelease = NULL;
768 if(!(statdata.advf & ADVF_NODATA))
770 hr = IDataObject_GetData(data_obj, &statdata.formatetc, &stg);
773 IAdviseSink_OnDataChange(statdata.pAdvSink, &statdata.formatetc, &stg);
775 if(statdata.advf & ADVF_ONLYONCE)
777 IDataAdviseHolder_Unadvise(iface, statdata.dwConnection);
780 release_statdata(&statdata);
782 IEnumSTATDATA_Release(pEnum);
785 return S_OK;
788 /**************************************************************************
789 * DataAdviseHolderImpl_VTable
791 static const IDataAdviseHolderVtbl DataAdviseHolderImpl_VTable =
793 DataAdviseHolder_QueryInterface,
794 DataAdviseHolder_AddRef,
795 DataAdviseHolder_Release,
796 DataAdviseHolder_Advise,
797 DataAdviseHolder_Unadvise,
798 DataAdviseHolder_EnumAdvise,
799 DataAdviseHolder_SendOnDataChange
802 HRESULT DataAdviseHolder_OnConnect(IDataAdviseHolder *iface, IDataObject *pDelegate)
804 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
805 DWORD index;
806 HRESULT hr = S_OK;
808 for(index = 0; index < This->maxCons; index++)
810 if(This->connections[index].pAdvSink != NULL)
812 hr = IDataObject_DAdvise(pDelegate, &This->connections[index].formatetc,
813 This->connections[index].advf,
814 This->connections[index].pAdvSink,
815 &This->remote_connections[index]);
816 if (FAILED(hr)) break;
817 This->connections[index].advf |= WINE_ADVF_REMOTE;
820 This->delegate = pDelegate;
821 return hr;
824 void DataAdviseHolder_OnDisconnect(IDataAdviseHolder *iface)
826 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
827 DWORD index;
829 for(index = 0; index < This->maxCons; index++)
831 if((This->connections[index].pAdvSink != NULL) &&
832 (This->connections[index].advf & WINE_ADVF_REMOTE))
834 IDataObject_DUnadvise(This->delegate, This->remote_connections[index]);
835 This->remote_connections[index] = 0;
836 This->connections[index].advf &= ~WINE_ADVF_REMOTE;
839 This->delegate = NULL;
842 /******************************************************************************
843 * DataAdviseHolder_Constructor
845 static IDataAdviseHolder *DataAdviseHolder_Constructor(void)
847 DataAdviseHolder* newHolder;
849 newHolder = HeapAlloc(GetProcessHeap(), 0, sizeof(DataAdviseHolder));
851 newHolder->IDataAdviseHolder_iface.lpVtbl = &DataAdviseHolderImpl_VTable;
852 newHolder->ref = 1;
853 newHolder->maxCons = INITIAL_SINKS;
854 newHolder->connections = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
855 newHolder->maxCons * sizeof(*newHolder->connections));
856 newHolder->remote_connections = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
857 newHolder->maxCons * sizeof(*newHolder->remote_connections));
858 newHolder->delegate = NULL;
860 TRACE("returning %p\n", &newHolder->IDataAdviseHolder_iface);
861 return &newHolder->IDataAdviseHolder_iface;
864 /***********************************************************************
865 * API functions
868 /***********************************************************************
869 * CreateOleAdviseHolder [OLE32.@]
871 HRESULT WINAPI CreateOleAdviseHolder(IOleAdviseHolder **ppOAHolder)
873 TRACE("(%p)\n", ppOAHolder);
875 if (ppOAHolder==NULL)
876 return E_POINTER;
878 *ppOAHolder = OleAdviseHolderImpl_Constructor ();
880 if (*ppOAHolder != NULL)
881 return S_OK;
883 return E_OUTOFMEMORY;
886 /******************************************************************************
887 * CreateDataAdviseHolder [OLE32.@]
889 HRESULT WINAPI CreateDataAdviseHolder(IDataAdviseHolder **ppDAHolder)
891 TRACE("(%p)\n", ppDAHolder);
893 if (ppDAHolder==NULL)
894 return E_POINTER;
896 *ppDAHolder = DataAdviseHolder_Constructor();
898 if (*ppDAHolder != NULL)
899 return S_OK;
901 return E_OUTOFMEMORY;