widl: Always check the runtimeclass interfaces presence.
[wine/zf.git] / dlls / ole32 / oleobj.c
blob13a873655f5539f0ab749fec28e7efd9d958728d
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 CoTaskMemFree(data->formatetc.ptd);
45 data->formatetc.ptd = NULL;
47 if(data->pAdvSink)
49 IAdviseSink_Release(data->pAdvSink);
50 data->pAdvSink = NULL;
54 static HRESULT copy_statdata(STATDATA *dst, const STATDATA *src)
56 HRESULT hr;
58 hr = copy_formatetc( &dst->formatetc, &src->formatetc );
59 if (FAILED(hr)) return hr;
60 dst->advf = src->advf;
61 dst->pAdvSink = src->pAdvSink;
62 if (dst->pAdvSink) IAdviseSink_AddRef( dst->pAdvSink );
63 dst->dwConnection = src->dwConnection;
64 return S_OK;
67 /**************************************************************************
68 * EnumSTATDATA Implementation
71 typedef struct
73 IEnumSTATDATA IEnumSTATDATA_iface;
74 LONG ref;
76 ULONG index;
77 DWORD num_of_elems;
78 STATDATA *statdata;
79 IUnknown *holder;
80 } EnumSTATDATA;
82 static inline EnumSTATDATA *impl_from_IEnumSTATDATA(IEnumSTATDATA *iface)
84 return CONTAINING_RECORD(iface, EnumSTATDATA, IEnumSTATDATA_iface);
87 static HRESULT WINAPI EnumSTATDATA_QueryInterface(IEnumSTATDATA *iface, REFIID riid, void **ppv)
89 TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
90 if (IsEqualIID(riid, &IID_IUnknown) ||
91 IsEqualIID(riid, &IID_IEnumSTATDATA))
93 IEnumSTATDATA_AddRef(iface);
94 *ppv = iface;
95 return S_OK;
97 return E_NOINTERFACE;
100 static ULONG WINAPI EnumSTATDATA_AddRef(IEnumSTATDATA *iface)
102 EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
103 TRACE("()\n");
104 return InterlockedIncrement(&This->ref);
107 static ULONG WINAPI EnumSTATDATA_Release(IEnumSTATDATA *iface)
109 EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
110 LONG refs = InterlockedDecrement(&This->ref);
111 TRACE("()\n");
112 if (!refs)
114 DWORD i;
115 for(i = 0; i < This->num_of_elems; i++)
116 release_statdata(This->statdata + i);
117 HeapFree(GetProcessHeap(), 0, This->statdata);
118 if (This->holder) IUnknown_Release(This->holder);
119 HeapFree(GetProcessHeap(), 0, This);
121 return refs;
124 static HRESULT WINAPI EnumSTATDATA_Next(IEnumSTATDATA *iface, ULONG num, LPSTATDATA data,
125 ULONG *fetched)
127 EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
128 DWORD count = 0;
129 HRESULT hr = S_OK;
131 TRACE("(%d, %p, %p)\n", num, data, fetched);
133 while(num--)
135 if (This->index >= This->num_of_elems)
137 hr = S_FALSE;
138 break;
141 copy_statdata(data + count, This->statdata + This->index);
143 count++;
144 This->index++;
147 if (fetched) *fetched = count;
149 return hr;
152 static HRESULT WINAPI EnumSTATDATA_Skip(IEnumSTATDATA *iface, ULONG num)
154 EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
156 TRACE("(%d)\n", num);
158 if(This->index + num >= This->num_of_elems)
160 This->index = This->num_of_elems;
161 return S_FALSE;
164 This->index += num;
165 return S_OK;
168 static HRESULT WINAPI EnumSTATDATA_Reset(IEnumSTATDATA *iface)
170 EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
172 TRACE("()\n");
174 This->index = 0;
175 return S_OK;
178 static HRESULT WINAPI EnumSTATDATA_Clone(IEnumSTATDATA *iface, IEnumSTATDATA **ppenum)
180 EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
182 return EnumSTATDATA_Construct(This->holder, This->index, This->num_of_elems, This->statdata,
183 TRUE, ppenum);
186 static const IEnumSTATDATAVtbl EnumSTATDATA_VTable =
188 EnumSTATDATA_QueryInterface,
189 EnumSTATDATA_AddRef,
190 EnumSTATDATA_Release,
191 EnumSTATDATA_Next,
192 EnumSTATDATA_Skip,
193 EnumSTATDATA_Reset,
194 EnumSTATDATA_Clone
197 HRESULT EnumSTATDATA_Construct(IUnknown *holder, ULONG index, DWORD array_len, STATDATA *data,
198 BOOL copy, IEnumSTATDATA **ppenum)
200 EnumSTATDATA *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
201 DWORD i, count;
203 if (!This) return E_OUTOFMEMORY;
205 This->IEnumSTATDATA_iface.lpVtbl = &EnumSTATDATA_VTable;
206 This->ref = 1;
207 This->index = index;
209 if (copy)
211 This->statdata = HeapAlloc(GetProcessHeap(), 0, array_len * sizeof(*This->statdata));
212 if(!This->statdata)
214 HeapFree(GetProcessHeap(), 0, This);
215 return E_OUTOFMEMORY;
218 for(i = 0, count = 0; i < array_len; i++)
220 if(data[i].pAdvSink)
222 copy_statdata(This->statdata + count, data + i);
223 count++;
227 else
229 This->statdata = data;
230 count = array_len;
233 This->num_of_elems = count;
234 This->holder = holder;
235 if (holder) IUnknown_AddRef(holder);
236 *ppenum = &This->IEnumSTATDATA_iface;
237 return S_OK;
240 /**************************************************************************
241 * OleAdviseHolder Implementation
243 typedef struct
245 IOleAdviseHolder IOleAdviseHolder_iface;
247 LONG ref;
249 DWORD max_cons;
250 STATDATA *connections;
251 } OleAdviseHolderImpl;
253 static inline OleAdviseHolderImpl *impl_from_IOleAdviseHolder(IOleAdviseHolder *iface)
255 return CONTAINING_RECORD(iface, OleAdviseHolderImpl, IOleAdviseHolder_iface);
258 /**************************************************************************
259 * OleAdviseHolderImpl_Destructor
261 static void OleAdviseHolderImpl_Destructor(OleAdviseHolderImpl *This)
263 DWORD index;
264 TRACE("%p\n", This);
266 for (index = 0; index < This->max_cons; index++)
268 if (This->connections[index].pAdvSink != NULL)
269 release_statdata(This->connections + index);
272 HeapFree(GetProcessHeap(), 0, This->connections);
273 HeapFree(GetProcessHeap(), 0, This);
276 /**************************************************************************
277 * OleAdviseHolderImpl_QueryInterface
279 static HRESULT WINAPI OleAdviseHolderImpl_QueryInterface(IOleAdviseHolder *iface,
280 REFIID iid, void **obj)
282 OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
283 TRACE("(%p)->(%s,%p)\n",This, debugstr_guid(iid), obj);
285 if (obj == NULL)
286 return E_POINTER;
288 *obj = NULL;
290 if (IsEqualIID(iid, &IID_IUnknown) ||
291 IsEqualIID(iid, &IID_IOleAdviseHolder))
293 *obj = &This->IOleAdviseHolder_iface;
296 if(*obj == NULL)
297 return E_NOINTERFACE;
299 IUnknown_AddRef((IUnknown*)*obj);
301 return S_OK;
304 /******************************************************************************
305 * OleAdviseHolderImpl_AddRef
307 static ULONG WINAPI OleAdviseHolderImpl_AddRef(IOleAdviseHolder *iface)
309 OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
310 ULONG ref = InterlockedIncrement(&This->ref);
312 TRACE("(%p)->(ref=%d)\n", This, ref - 1);
314 return ref;
317 /******************************************************************************
318 * OleAdviseHolderImpl_Release
320 static ULONG WINAPI OleAdviseHolderImpl_Release(IOleAdviseHolder *iface)
322 OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
323 ULONG ref;
324 TRACE("(%p)->(ref=%d)\n", This, This->ref);
325 ref = InterlockedDecrement(&This->ref);
327 if (ref == 0) OleAdviseHolderImpl_Destructor(This);
329 return ref;
332 /******************************************************************************
333 * OleAdviseHolderImpl_Advise
335 static HRESULT WINAPI OleAdviseHolderImpl_Advise(IOleAdviseHolder *iface,
336 IAdviseSink *pAdvise,
337 DWORD *pdwConnection)
339 DWORD index;
340 OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
341 STATDATA new_conn;
342 static const FORMATETC empty_fmtetc = {0, NULL, 0, -1, 0};
344 TRACE("(%p)->(%p, %p)\n", This, pAdvise, pdwConnection);
346 if (pdwConnection==NULL)
347 return E_POINTER;
349 *pdwConnection = 0;
351 for (index = 0; index < This->max_cons; index++)
353 if (This->connections[index].pAdvSink == NULL)
354 break;
357 if (index == This->max_cons)
359 This->max_cons += INITIAL_SINKS;
360 This->connections = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->connections,
361 This->max_cons * sizeof(*This->connections));
364 new_conn.pAdvSink = pAdvise;
365 new_conn.advf = 0;
366 new_conn.formatetc = empty_fmtetc;
367 new_conn.dwConnection = index + 1; /* 0 is not a valid cookie, so increment the index */
369 copy_statdata(This->connections + index, &new_conn);
371 *pdwConnection = new_conn.dwConnection;
373 return S_OK;
376 /******************************************************************************
377 * OleAdviseHolderImpl_Unadvise
379 static HRESULT WINAPI OleAdviseHolderImpl_Unadvise(IOleAdviseHolder *iface,
380 DWORD dwConnection)
382 OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
383 DWORD index;
385 TRACE("(%p)->(%u)\n", This, dwConnection);
387 /* The connection number is 1 more than the index, see OleAdviseHolder_Advise */
388 index = dwConnection - 1;
390 if (index >= This->max_cons || This->connections[index].pAdvSink == NULL)
391 return OLE_E_NOCONNECTION;
393 release_statdata(This->connections + index);
395 return S_OK;
398 /******************************************************************************
399 * OleAdviseHolderImpl_EnumAdvise
401 static HRESULT WINAPI OleAdviseHolderImpl_EnumAdvise(IOleAdviseHolder *iface, IEnumSTATDATA **enum_advise)
403 OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
404 IUnknown *unk;
405 HRESULT hr;
407 TRACE("(%p)->(%p)\n", This, enum_advise);
409 IOleAdviseHolder_QueryInterface(iface, &IID_IUnknown, (void**)&unk);
410 hr = EnumSTATDATA_Construct(unk, 0, This->max_cons, This->connections, TRUE, enum_advise);
411 IUnknown_Release(unk);
412 return hr;
415 /******************************************************************************
416 * OleAdviseHolderImpl_SendOnRename
418 static HRESULT WINAPI OleAdviseHolderImpl_SendOnRename(IOleAdviseHolder *iface, IMoniker *pmk)
420 IEnumSTATDATA *pEnum;
421 HRESULT hr;
423 TRACE("(%p)->(%p)\n", iface, pmk);
425 hr = IOleAdviseHolder_EnumAdvise(iface, &pEnum);
426 if (SUCCEEDED(hr))
428 STATDATA statdata;
429 while (IEnumSTATDATA_Next(pEnum, 1, &statdata, NULL) == S_OK)
431 IAdviseSink_OnRename(statdata.pAdvSink, pmk);
433 IAdviseSink_Release(statdata.pAdvSink);
435 IEnumSTATDATA_Release(pEnum);
438 return hr;
441 /******************************************************************************
442 * OleAdviseHolderImpl_SendOnSave
444 static HRESULT WINAPI OleAdviseHolderImpl_SendOnSave(IOleAdviseHolder *iface)
446 IEnumSTATDATA *pEnum;
447 HRESULT hr;
449 TRACE("(%p)->()\n", iface);
451 hr = IOleAdviseHolder_EnumAdvise(iface, &pEnum);
452 if (SUCCEEDED(hr))
454 STATDATA statdata;
455 while (IEnumSTATDATA_Next(pEnum, 1, &statdata, NULL) == S_OK)
457 IAdviseSink_OnSave(statdata.pAdvSink);
459 IAdviseSink_Release(statdata.pAdvSink);
461 IEnumSTATDATA_Release(pEnum);
464 return hr;
467 /******************************************************************************
468 * OleAdviseHolderImpl_SendOnClose
470 static HRESULT WINAPI OleAdviseHolderImpl_SendOnClose(IOleAdviseHolder *iface)
472 IEnumSTATDATA *pEnum;
473 HRESULT hr;
475 TRACE("(%p)->()\n", iface);
477 hr = IOleAdviseHolder_EnumAdvise(iface, &pEnum);
478 if (SUCCEEDED(hr))
480 STATDATA statdata;
481 while (IEnumSTATDATA_Next(pEnum, 1, &statdata, NULL) == S_OK)
483 IAdviseSink_OnClose(statdata.pAdvSink);
485 IAdviseSink_Release(statdata.pAdvSink);
487 IEnumSTATDATA_Release(pEnum);
490 return hr;
493 /**************************************************************************
494 * OleAdviseHolderImpl_VTable
496 static const IOleAdviseHolderVtbl oahvt =
498 OleAdviseHolderImpl_QueryInterface,
499 OleAdviseHolderImpl_AddRef,
500 OleAdviseHolderImpl_Release,
501 OleAdviseHolderImpl_Advise,
502 OleAdviseHolderImpl_Unadvise,
503 OleAdviseHolderImpl_EnumAdvise,
504 OleAdviseHolderImpl_SendOnRename,
505 OleAdviseHolderImpl_SendOnSave,
506 OleAdviseHolderImpl_SendOnClose
509 /**************************************************************************
510 * OleAdviseHolderImpl_Constructor
513 static IOleAdviseHolder *OleAdviseHolderImpl_Constructor(void)
515 OleAdviseHolderImpl* lpoah;
517 lpoah = HeapAlloc(GetProcessHeap(), 0, sizeof(OleAdviseHolderImpl));
519 lpoah->IOleAdviseHolder_iface.lpVtbl = &oahvt;
520 lpoah->ref = 1;
521 lpoah->max_cons = INITIAL_SINKS;
522 lpoah->connections = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
523 lpoah->max_cons * sizeof(*lpoah->connections));
525 TRACE("returning %p\n", &lpoah->IOleAdviseHolder_iface);
526 return &lpoah->IOleAdviseHolder_iface;
529 /**************************************************************************
530 * DataAdviseHolder Implementation
532 typedef struct
534 IDataAdviseHolder IDataAdviseHolder_iface;
536 LONG ref;
537 DWORD maxCons;
538 STATDATA* connections;
539 DWORD* remote_connections;
540 IDataObject* delegate;
541 } DataAdviseHolder;
543 /* this connection has also has been advised to the delegate data object */
544 #define WINE_ADVF_REMOTE 0x80000000
546 static inline DataAdviseHolder *impl_from_IDataAdviseHolder(IDataAdviseHolder *iface)
548 return CONTAINING_RECORD(iface, DataAdviseHolder, IDataAdviseHolder_iface);
551 /******************************************************************************
552 * DataAdviseHolder_Destructor
554 static void DataAdviseHolder_Destructor(DataAdviseHolder* ptrToDestroy)
556 DWORD index;
557 TRACE("%p\n", ptrToDestroy);
559 for (index = 0; index < ptrToDestroy->maxCons; index++)
561 if (ptrToDestroy->connections[index].pAdvSink != NULL)
563 if (ptrToDestroy->delegate &&
564 (ptrToDestroy->connections[index].advf & WINE_ADVF_REMOTE))
565 IDataObject_DUnadvise(ptrToDestroy->delegate,
566 ptrToDestroy->remote_connections[index]);
568 release_statdata(ptrToDestroy->connections + index);
572 HeapFree(GetProcessHeap(), 0, ptrToDestroy->remote_connections);
573 HeapFree(GetProcessHeap(), 0, ptrToDestroy->connections);
574 HeapFree(GetProcessHeap(), 0, ptrToDestroy);
577 /************************************************************************
578 * DataAdviseHolder_QueryInterface (IUnknown)
580 static HRESULT WINAPI DataAdviseHolder_QueryInterface(IDataAdviseHolder *iface,
581 REFIID riid, void **ppvObject)
583 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
584 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObject);
586 if ( (This==0) || (ppvObject==0) )
587 return E_INVALIDARG;
589 *ppvObject = 0;
591 if ( IsEqualIID(&IID_IUnknown, riid) ||
592 IsEqualIID(&IID_IDataAdviseHolder, riid) )
594 *ppvObject = iface;
597 if ((*ppvObject)==0)
599 return E_NOINTERFACE;
602 IUnknown_AddRef((IUnknown*)*ppvObject);
603 return S_OK;
606 /************************************************************************
607 * DataAdviseHolder_AddRef (IUnknown)
609 static ULONG WINAPI DataAdviseHolder_AddRef(IDataAdviseHolder *iface)
611 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
612 TRACE("(%p) (ref=%d)\n", This, This->ref);
613 return InterlockedIncrement(&This->ref);
616 /************************************************************************
617 * DataAdviseHolder_Release (IUnknown)
619 static ULONG WINAPI DataAdviseHolder_Release(IDataAdviseHolder *iface)
621 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
622 ULONG ref;
623 TRACE("(%p) (ref=%d)\n", This, This->ref);
625 ref = InterlockedDecrement(&This->ref);
626 if (ref==0) DataAdviseHolder_Destructor(This);
628 return ref;
631 /************************************************************************
632 * DataAdviseHolder_Advise
635 static HRESULT WINAPI DataAdviseHolder_Advise(IDataAdviseHolder *iface,
636 IDataObject *pDataObject, FORMATETC *pFetc,
637 DWORD advf, IAdviseSink *pAdvise,
638 DWORD *pdwConnection)
640 DWORD index;
641 STATDATA new_conn;
642 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
644 TRACE("(%p)->(%p, %p, %08x, %p, %p)\n", This, pDataObject, pFetc, advf,
645 pAdvise, pdwConnection);
647 if (pdwConnection==NULL)
648 return E_POINTER;
650 *pdwConnection = 0;
652 for (index = 0; index < This->maxCons; index++)
654 if (This->connections[index].pAdvSink == NULL)
655 break;
658 if (index == This->maxCons)
660 This->maxCons+=INITIAL_SINKS;
661 This->connections = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
662 This->connections,
663 This->maxCons * sizeof(*This->connections));
664 This->remote_connections = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
665 This->remote_connections,
666 This->maxCons * sizeof(*This->remote_connections));
669 new_conn.pAdvSink = pAdvise;
670 new_conn.advf = advf & ~WINE_ADVF_REMOTE;
671 new_conn.formatetc = *pFetc;
672 new_conn.dwConnection = index + 1; /* 0 is not a valid cookie, so increment the index */
674 copy_statdata(This->connections + index, &new_conn);
676 if (This->connections[index].pAdvSink != NULL)
678 /* if we are already connected advise the remote object */
679 if (This->delegate)
681 HRESULT hr;
683 hr = IDataObject_DAdvise(This->delegate, &new_conn.formatetc,
684 new_conn.advf, new_conn.pAdvSink,
685 &This->remote_connections[index]);
686 if (FAILED(hr))
688 IDataAdviseHolder_Unadvise(iface, new_conn.dwConnection);
689 return hr;
691 This->connections[index].advf |= WINE_ADVF_REMOTE;
693 else if(advf & ADVF_PRIMEFIRST)
694 /* only do this if we have no delegate, since in the above case the
695 * delegate will do the priming for us */
696 IDataAdviseHolder_SendOnDataChange(iface, pDataObject, 0, advf);
699 *pdwConnection = new_conn.dwConnection;
701 return S_OK;
704 /******************************************************************************
705 * DataAdviseHolder_Unadvise
707 static HRESULT WINAPI DataAdviseHolder_Unadvise(IDataAdviseHolder *iface,
708 DWORD dwConnection)
710 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
711 DWORD index;
712 TRACE("(%p)->(%u)\n", This, dwConnection);
714 /* The connection number is 1 more than the index, see DataAdviseHolder_Advise */
715 index = dwConnection - 1;
717 if (index >= This->maxCons || This->connections[index].pAdvSink == NULL)
718 return OLE_E_NOCONNECTION;
720 if (This->delegate && This->connections[index].advf & WINE_ADVF_REMOTE)
722 IDataObject_DUnadvise(This->delegate, This->remote_connections[index]);
723 This->remote_connections[index] = 0;
726 release_statdata(This->connections + index);
728 return S_OK;
731 /******************************************************************************
732 * DataAdviseHolder_EnumAdvise
734 static HRESULT WINAPI DataAdviseHolder_EnumAdvise(IDataAdviseHolder *iface,
735 IEnumSTATDATA **enum_advise)
737 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
738 IUnknown *unk;
739 HRESULT hr;
741 TRACE("(%p)->(%p)\n", This, enum_advise);
743 IDataAdviseHolder_QueryInterface(iface, &IID_IUnknown, (void**)&unk);
744 hr = EnumSTATDATA_Construct(unk, 0, This->maxCons, This->connections, TRUE, enum_advise);
745 IUnknown_Release(unk);
746 return hr;
749 /******************************************************************************
750 * DataAdviseHolder_SendOnDataChange
752 static HRESULT WINAPI DataAdviseHolder_SendOnDataChange(IDataAdviseHolder *iface,
753 IDataObject *data_obj,
754 DWORD dwReserved, DWORD advf)
756 IEnumSTATDATA *pEnum;
757 HRESULT hr;
759 TRACE("(%p)->(%p, %08x, %08x)\n", iface, data_obj, dwReserved, advf);
761 hr = IDataAdviseHolder_EnumAdvise(iface, &pEnum);
762 if (SUCCEEDED(hr))
764 STATDATA statdata;
765 while (IEnumSTATDATA_Next(pEnum, 1, &statdata, NULL) == S_OK)
767 STGMEDIUM stg;
768 stg.tymed = TYMED_NULL;
769 stg.u.pstg = NULL;
770 stg.pUnkForRelease = NULL;
772 if(!(statdata.advf & ADVF_NODATA))
774 hr = IDataObject_GetData(data_obj, &statdata.formatetc, &stg);
777 IAdviseSink_OnDataChange(statdata.pAdvSink, &statdata.formatetc, &stg);
779 if(statdata.advf & ADVF_ONLYONCE)
781 IDataAdviseHolder_Unadvise(iface, statdata.dwConnection);
784 release_statdata(&statdata);
786 IEnumSTATDATA_Release(pEnum);
789 return S_OK;
792 /**************************************************************************
793 * DataAdviseHolderImpl_VTable
795 static const IDataAdviseHolderVtbl DataAdviseHolderImpl_VTable =
797 DataAdviseHolder_QueryInterface,
798 DataAdviseHolder_AddRef,
799 DataAdviseHolder_Release,
800 DataAdviseHolder_Advise,
801 DataAdviseHolder_Unadvise,
802 DataAdviseHolder_EnumAdvise,
803 DataAdviseHolder_SendOnDataChange
806 HRESULT DataAdviseHolder_OnConnect(IDataAdviseHolder *iface, IDataObject *pDelegate)
808 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
809 DWORD index;
810 HRESULT hr = S_OK;
812 for(index = 0; index < This->maxCons; index++)
814 if(This->connections[index].pAdvSink != NULL)
816 hr = IDataObject_DAdvise(pDelegate, &This->connections[index].formatetc,
817 This->connections[index].advf,
818 This->connections[index].pAdvSink,
819 &This->remote_connections[index]);
820 if (FAILED(hr)) break;
821 This->connections[index].advf |= WINE_ADVF_REMOTE;
824 This->delegate = pDelegate;
825 return hr;
828 void DataAdviseHolder_OnDisconnect(IDataAdviseHolder *iface)
830 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
831 DWORD index;
833 for(index = 0; index < This->maxCons; index++)
835 if((This->connections[index].pAdvSink != NULL) &&
836 (This->connections[index].advf & WINE_ADVF_REMOTE))
838 IDataObject_DUnadvise(This->delegate, This->remote_connections[index]);
839 This->remote_connections[index] = 0;
840 This->connections[index].advf &= ~WINE_ADVF_REMOTE;
843 This->delegate = NULL;
846 /******************************************************************************
847 * DataAdviseHolder_Constructor
849 static IDataAdviseHolder *DataAdviseHolder_Constructor(void)
851 DataAdviseHolder* newHolder;
853 newHolder = HeapAlloc(GetProcessHeap(), 0, sizeof(DataAdviseHolder));
855 newHolder->IDataAdviseHolder_iface.lpVtbl = &DataAdviseHolderImpl_VTable;
856 newHolder->ref = 1;
857 newHolder->maxCons = INITIAL_SINKS;
858 newHolder->connections = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
859 newHolder->maxCons * sizeof(*newHolder->connections));
860 newHolder->remote_connections = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
861 newHolder->maxCons * sizeof(*newHolder->remote_connections));
862 newHolder->delegate = NULL;
864 TRACE("returning %p\n", &newHolder->IDataAdviseHolder_iface);
865 return &newHolder->IDataAdviseHolder_iface;
868 /***********************************************************************
869 * API functions
872 /***********************************************************************
873 * CreateOleAdviseHolder [OLE32.@]
875 HRESULT WINAPI CreateOleAdviseHolder(IOleAdviseHolder **ppOAHolder)
877 TRACE("(%p)\n", ppOAHolder);
879 if (ppOAHolder==NULL)
880 return E_POINTER;
882 *ppOAHolder = OleAdviseHolderImpl_Constructor ();
884 if (*ppOAHolder != NULL)
885 return S_OK;
887 return E_OUTOFMEMORY;
890 /******************************************************************************
891 * CreateDataAdviseHolder [OLE32.@]
893 HRESULT WINAPI CreateDataAdviseHolder(IDataAdviseHolder **ppDAHolder)
895 TRACE("(%p)\n", ppDAHolder);
897 if (ppDAHolder==NULL)
898 return E_POINTER;
900 *ppDAHolder = DataAdviseHolder_Constructor();
902 if (*ppDAHolder != NULL)
903 return S_OK;
905 return E_OUTOFMEMORY;