imagehlp: Use the IMAGE_FIRST_SECTION helper macro.
[wine.git] / dlls / ole32 / oleobj.c
blob028da1446fdc9871986be6b0462b305bf554ebfa
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 #include "windef.h"
28 #include "winbase.h"
29 #include "winuser.h"
30 #include "winerror.h"
31 #include "wine/debug.h"
32 #include "ole2.h"
34 #include "compobj_private.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(ole);
38 #define INITIAL_SINKS 10
40 static void release_statdata(STATDATA *data)
42 CoTaskMemFree(data->formatetc.ptd);
43 data->formatetc.ptd = NULL;
45 if(data->pAdvSink)
47 IAdviseSink_Release(data->pAdvSink);
48 data->pAdvSink = NULL;
52 static HRESULT copy_statdata(STATDATA *dst, const STATDATA *src)
54 HRESULT hr;
56 hr = copy_formatetc( &dst->formatetc, &src->formatetc );
57 if (FAILED(hr)) return hr;
58 dst->advf = src->advf;
59 dst->pAdvSink = src->pAdvSink;
60 if (dst->pAdvSink) IAdviseSink_AddRef( dst->pAdvSink );
61 dst->dwConnection = src->dwConnection;
62 return S_OK;
65 /**************************************************************************
66 * EnumSTATDATA Implementation
69 typedef struct
71 IEnumSTATDATA IEnumSTATDATA_iface;
72 LONG ref;
74 ULONG index;
75 DWORD num_of_elems;
76 STATDATA *statdata;
77 IUnknown *holder;
78 } EnumSTATDATA;
80 static inline EnumSTATDATA *impl_from_IEnumSTATDATA(IEnumSTATDATA *iface)
82 return CONTAINING_RECORD(iface, EnumSTATDATA, IEnumSTATDATA_iface);
85 static HRESULT WINAPI EnumSTATDATA_QueryInterface(IEnumSTATDATA *iface, REFIID riid, void **ppv)
87 TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
88 if (IsEqualIID(riid, &IID_IUnknown) ||
89 IsEqualIID(riid, &IID_IEnumSTATDATA))
91 IEnumSTATDATA_AddRef(iface);
92 *ppv = iface;
93 return S_OK;
95 return E_NOINTERFACE;
98 static ULONG WINAPI EnumSTATDATA_AddRef(IEnumSTATDATA *iface)
100 EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
101 TRACE("()\n");
102 return InterlockedIncrement(&This->ref);
105 static ULONG WINAPI EnumSTATDATA_Release(IEnumSTATDATA *iface)
107 EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
108 LONG refs = InterlockedDecrement(&This->ref);
109 TRACE("()\n");
110 if (!refs)
112 DWORD i;
113 for(i = 0; i < This->num_of_elems; i++)
114 release_statdata(This->statdata + i);
115 HeapFree(GetProcessHeap(), 0, This->statdata);
116 if (This->holder) IUnknown_Release(This->holder);
117 HeapFree(GetProcessHeap(), 0, This);
119 return refs;
122 static HRESULT WINAPI EnumSTATDATA_Next(IEnumSTATDATA *iface, ULONG num, LPSTATDATA data,
123 ULONG *fetched)
125 EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
126 DWORD count = 0;
127 HRESULT hr = S_OK;
129 TRACE("%p, %lu, %p, %p.\n", iface, num, data, fetched);
131 while(num--)
133 if (This->index >= This->num_of_elems)
135 hr = S_FALSE;
136 break;
139 copy_statdata(data + count, This->statdata + This->index);
141 count++;
142 This->index++;
145 if (fetched) *fetched = count;
147 return hr;
150 static HRESULT WINAPI EnumSTATDATA_Skip(IEnumSTATDATA *iface, ULONG num)
152 EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
154 TRACE("%p, %lu.\n", iface, num);
156 if(This->index + num >= This->num_of_elems)
158 This->index = This->num_of_elems;
159 return S_FALSE;
162 This->index += num;
163 return S_OK;
166 static HRESULT WINAPI EnumSTATDATA_Reset(IEnumSTATDATA *iface)
168 EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
170 TRACE("()\n");
172 This->index = 0;
173 return S_OK;
176 static HRESULT WINAPI EnumSTATDATA_Clone(IEnumSTATDATA *iface, IEnumSTATDATA **ppenum)
178 EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
180 return EnumSTATDATA_Construct(This->holder, This->index, This->num_of_elems, This->statdata,
181 TRUE, ppenum);
184 static const IEnumSTATDATAVtbl EnumSTATDATA_VTable =
186 EnumSTATDATA_QueryInterface,
187 EnumSTATDATA_AddRef,
188 EnumSTATDATA_Release,
189 EnumSTATDATA_Next,
190 EnumSTATDATA_Skip,
191 EnumSTATDATA_Reset,
192 EnumSTATDATA_Clone
195 HRESULT EnumSTATDATA_Construct(IUnknown *holder, ULONG index, DWORD array_len, STATDATA *data,
196 BOOL copy, IEnumSTATDATA **ppenum)
198 EnumSTATDATA *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
199 DWORD i, count;
201 if (!This) return E_OUTOFMEMORY;
203 This->IEnumSTATDATA_iface.lpVtbl = &EnumSTATDATA_VTable;
204 This->ref = 1;
205 This->index = index;
207 if (copy)
209 This->statdata = HeapAlloc(GetProcessHeap(), 0, array_len * sizeof(*This->statdata));
210 if(!This->statdata)
212 HeapFree(GetProcessHeap(), 0, This);
213 return E_OUTOFMEMORY;
216 for(i = 0, count = 0; i < array_len; i++)
218 if(data[i].pAdvSink)
220 copy_statdata(This->statdata + count, data + i);
221 count++;
225 else
227 This->statdata = data;
228 count = array_len;
231 This->num_of_elems = count;
232 This->holder = holder;
233 if (holder) IUnknown_AddRef(holder);
234 *ppenum = &This->IEnumSTATDATA_iface;
235 return S_OK;
238 /**************************************************************************
239 * OleAdviseHolder Implementation
241 typedef struct
243 IOleAdviseHolder IOleAdviseHolder_iface;
245 LONG ref;
247 DWORD max_cons;
248 STATDATA *connections;
249 } OleAdviseHolderImpl;
251 static inline OleAdviseHolderImpl *impl_from_IOleAdviseHolder(IOleAdviseHolder *iface)
253 return CONTAINING_RECORD(iface, OleAdviseHolderImpl, IOleAdviseHolder_iface);
256 /**************************************************************************
257 * OleAdviseHolderImpl_Destructor
259 static void OleAdviseHolderImpl_Destructor(OleAdviseHolderImpl *This)
261 DWORD index;
262 TRACE("%p\n", This);
264 for (index = 0; index < This->max_cons; index++)
266 if (This->connections[index].pAdvSink != NULL)
267 release_statdata(This->connections + index);
270 HeapFree(GetProcessHeap(), 0, This->connections);
271 HeapFree(GetProcessHeap(), 0, This);
274 /**************************************************************************
275 * OleAdviseHolderImpl_QueryInterface
277 static HRESULT WINAPI OleAdviseHolderImpl_QueryInterface(IOleAdviseHolder *iface,
278 REFIID iid, void **obj)
280 OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
281 TRACE("(%p)->(%s,%p)\n",This, debugstr_guid(iid), obj);
283 if (obj == NULL)
284 return E_POINTER;
286 *obj = NULL;
288 if (IsEqualIID(iid, &IID_IUnknown) ||
289 IsEqualIID(iid, &IID_IOleAdviseHolder))
291 *obj = &This->IOleAdviseHolder_iface;
294 if(*obj == NULL)
295 return E_NOINTERFACE;
297 IUnknown_AddRef((IUnknown*)*obj);
299 return S_OK;
302 /******************************************************************************
303 * OleAdviseHolderImpl_AddRef
305 static ULONG WINAPI OleAdviseHolderImpl_AddRef(IOleAdviseHolder *iface)
307 OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
308 ULONG ref = InterlockedIncrement(&This->ref);
310 TRACE("%p, refcount %lu.\n", iface, ref);
312 return ref;
315 /******************************************************************************
316 * OleAdviseHolderImpl_Release
318 static ULONG WINAPI OleAdviseHolderImpl_Release(IOleAdviseHolder *iface)
320 OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
321 ULONG ref = InterlockedDecrement(&This->ref);
323 TRACE("%p, refcount %lu.\n", iface, ref);
325 if (ref == 0) OleAdviseHolderImpl_Destructor(This);
327 return ref;
330 /******************************************************************************
331 * OleAdviseHolderImpl_Advise
333 static HRESULT WINAPI OleAdviseHolderImpl_Advise(IOleAdviseHolder *iface,
334 IAdviseSink *pAdvise,
335 DWORD *pdwConnection)
337 DWORD index;
338 OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
339 STATDATA new_conn;
340 static const FORMATETC empty_fmtetc = {0, NULL, 0, -1, 0};
342 TRACE("(%p)->(%p, %p)\n", This, pAdvise, pdwConnection);
344 if (pdwConnection==NULL)
345 return E_POINTER;
347 *pdwConnection = 0;
349 for (index = 0; index < This->max_cons; index++)
351 if (This->connections[index].pAdvSink == NULL)
352 break;
355 if (index == This->max_cons)
357 This->max_cons += INITIAL_SINKS;
358 This->connections = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->connections,
359 This->max_cons * sizeof(*This->connections));
362 new_conn.pAdvSink = pAdvise;
363 new_conn.advf = 0;
364 new_conn.formatetc = empty_fmtetc;
365 new_conn.dwConnection = index + 1; /* 0 is not a valid cookie, so increment the index */
367 copy_statdata(This->connections + index, &new_conn);
369 *pdwConnection = new_conn.dwConnection;
371 return S_OK;
374 /******************************************************************************
375 * OleAdviseHolderImpl_Unadvise
377 static HRESULT WINAPI OleAdviseHolderImpl_Unadvise(IOleAdviseHolder *iface,
378 DWORD dwConnection)
380 OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
381 DWORD index;
383 TRACE("%p, %lu.\n", iface, dwConnection);
385 /* The connection number is 1 more than the index, see OleAdviseHolder_Advise */
386 index = dwConnection - 1;
388 if (index >= This->max_cons || This->connections[index].pAdvSink == NULL)
389 return OLE_E_NOCONNECTION;
391 release_statdata(This->connections + index);
393 return S_OK;
396 /******************************************************************************
397 * OleAdviseHolderImpl_EnumAdvise
399 static HRESULT WINAPI OleAdviseHolderImpl_EnumAdvise(IOleAdviseHolder *iface, IEnumSTATDATA **enum_advise)
401 OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
402 IUnknown *unk;
403 HRESULT hr;
405 TRACE("(%p)->(%p)\n", This, enum_advise);
407 IOleAdviseHolder_QueryInterface(iface, &IID_IUnknown, (void**)&unk);
408 hr = EnumSTATDATA_Construct(unk, 0, This->max_cons, This->connections, TRUE, enum_advise);
409 IUnknown_Release(unk);
410 return hr;
413 /******************************************************************************
414 * OleAdviseHolderImpl_SendOnRename
416 static HRESULT WINAPI OleAdviseHolderImpl_SendOnRename(IOleAdviseHolder *iface, IMoniker *pmk)
418 IEnumSTATDATA *pEnum;
419 HRESULT hr;
421 TRACE("(%p)->(%p)\n", iface, pmk);
423 hr = IOleAdviseHolder_EnumAdvise(iface, &pEnum);
424 if (SUCCEEDED(hr))
426 STATDATA statdata;
427 while (IEnumSTATDATA_Next(pEnum, 1, &statdata, NULL) == S_OK)
429 IAdviseSink_OnRename(statdata.pAdvSink, pmk);
431 IAdviseSink_Release(statdata.pAdvSink);
433 IEnumSTATDATA_Release(pEnum);
436 return hr;
439 /******************************************************************************
440 * OleAdviseHolderImpl_SendOnSave
442 static HRESULT WINAPI OleAdviseHolderImpl_SendOnSave(IOleAdviseHolder *iface)
444 IEnumSTATDATA *pEnum;
445 HRESULT hr;
447 TRACE("(%p)->()\n", iface);
449 hr = IOleAdviseHolder_EnumAdvise(iface, &pEnum);
450 if (SUCCEEDED(hr))
452 STATDATA statdata;
453 while (IEnumSTATDATA_Next(pEnum, 1, &statdata, NULL) == S_OK)
455 IAdviseSink_OnSave(statdata.pAdvSink);
457 IAdviseSink_Release(statdata.pAdvSink);
459 IEnumSTATDATA_Release(pEnum);
462 return hr;
465 /******************************************************************************
466 * OleAdviseHolderImpl_SendOnClose
468 static HRESULT WINAPI OleAdviseHolderImpl_SendOnClose(IOleAdviseHolder *iface)
470 IEnumSTATDATA *pEnum;
471 HRESULT hr;
473 TRACE("(%p)->()\n", iface);
475 hr = IOleAdviseHolder_EnumAdvise(iface, &pEnum);
476 if (SUCCEEDED(hr))
478 STATDATA statdata;
479 while (IEnumSTATDATA_Next(pEnum, 1, &statdata, NULL) == S_OK)
481 IAdviseSink_OnClose(statdata.pAdvSink);
483 IAdviseSink_Release(statdata.pAdvSink);
485 IEnumSTATDATA_Release(pEnum);
488 return hr;
491 /**************************************************************************
492 * OleAdviseHolderImpl_VTable
494 static const IOleAdviseHolderVtbl oahvt =
496 OleAdviseHolderImpl_QueryInterface,
497 OleAdviseHolderImpl_AddRef,
498 OleAdviseHolderImpl_Release,
499 OleAdviseHolderImpl_Advise,
500 OleAdviseHolderImpl_Unadvise,
501 OleAdviseHolderImpl_EnumAdvise,
502 OleAdviseHolderImpl_SendOnRename,
503 OleAdviseHolderImpl_SendOnSave,
504 OleAdviseHolderImpl_SendOnClose
507 /**************************************************************************
508 * OleAdviseHolderImpl_Constructor
511 static IOleAdviseHolder *OleAdviseHolderImpl_Constructor(void)
513 OleAdviseHolderImpl* lpoah;
515 lpoah = HeapAlloc(GetProcessHeap(), 0, sizeof(OleAdviseHolderImpl));
517 lpoah->IOleAdviseHolder_iface.lpVtbl = &oahvt;
518 lpoah->ref = 1;
519 lpoah->max_cons = INITIAL_SINKS;
520 lpoah->connections = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
521 lpoah->max_cons * sizeof(*lpoah->connections));
523 TRACE("returning %p\n", &lpoah->IOleAdviseHolder_iface);
524 return &lpoah->IOleAdviseHolder_iface;
527 /**************************************************************************
528 * DataAdviseHolder Implementation
530 typedef struct
532 IDataAdviseHolder IDataAdviseHolder_iface;
534 LONG ref;
535 DWORD maxCons;
536 STATDATA* connections;
537 DWORD* remote_connections;
538 IDataObject* delegate;
539 } DataAdviseHolder;
541 /* this connection has also has been advised to the delegate data object */
542 #define WINE_ADVF_REMOTE 0x80000000
544 static inline DataAdviseHolder *impl_from_IDataAdviseHolder(IDataAdviseHolder *iface)
546 return CONTAINING_RECORD(iface, DataAdviseHolder, IDataAdviseHolder_iface);
549 /******************************************************************************
550 * DataAdviseHolder_Destructor
552 static void DataAdviseHolder_Destructor(DataAdviseHolder* ptrToDestroy)
554 DWORD index;
555 TRACE("%p\n", ptrToDestroy);
557 for (index = 0; index < ptrToDestroy->maxCons; index++)
559 if (ptrToDestroy->connections[index].pAdvSink != NULL)
561 if (ptrToDestroy->delegate &&
562 (ptrToDestroy->connections[index].advf & WINE_ADVF_REMOTE))
563 IDataObject_DUnadvise(ptrToDestroy->delegate,
564 ptrToDestroy->remote_connections[index]);
566 release_statdata(ptrToDestroy->connections + index);
570 HeapFree(GetProcessHeap(), 0, ptrToDestroy->remote_connections);
571 HeapFree(GetProcessHeap(), 0, ptrToDestroy->connections);
572 HeapFree(GetProcessHeap(), 0, ptrToDestroy);
575 /************************************************************************
576 * DataAdviseHolder_QueryInterface (IUnknown)
578 static HRESULT WINAPI DataAdviseHolder_QueryInterface(IDataAdviseHolder *iface,
579 REFIID riid, void **ppvObject)
581 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
582 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObject);
584 if ( (This==0) || (ppvObject==0) )
585 return E_INVALIDARG;
587 *ppvObject = 0;
589 if ( IsEqualIID(&IID_IUnknown, riid) ||
590 IsEqualIID(&IID_IDataAdviseHolder, riid) )
592 *ppvObject = iface;
595 if ((*ppvObject)==0)
597 return E_NOINTERFACE;
600 IUnknown_AddRef((IUnknown*)*ppvObject);
601 return S_OK;
604 /************************************************************************
605 * DataAdviseHolder_AddRef (IUnknown)
607 static ULONG WINAPI DataAdviseHolder_AddRef(IDataAdviseHolder *iface)
609 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
610 ULONG ref = InterlockedIncrement(&This->ref);
611 TRACE("%p, refcount %lu.\n", iface, ref);
612 return ref;
615 /************************************************************************
616 * DataAdviseHolder_Release (IUnknown)
618 static ULONG WINAPI DataAdviseHolder_Release(IDataAdviseHolder *iface)
620 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
621 ULONG ref = InterlockedDecrement(&This->ref);
623 TRACE("%p, refcount %lu.\n", iface, ref);
625 if (ref==0) DataAdviseHolder_Destructor(This);
627 return ref;
630 /************************************************************************
631 * DataAdviseHolder_Advise
634 static HRESULT WINAPI DataAdviseHolder_Advise(IDataAdviseHolder *iface,
635 IDataObject *pDataObject, FORMATETC *pFetc,
636 DWORD advf, IAdviseSink *pAdvise,
637 DWORD *pdwConnection)
639 DWORD index;
640 STATDATA new_conn;
641 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
643 TRACE("%p, %p, %p, %#lx, %p, %p.\n", iface, pDataObject, pFetc, advf, pAdvise, pdwConnection);
645 if (pdwConnection==NULL)
646 return E_POINTER;
648 *pdwConnection = 0;
650 for (index = 0; index < This->maxCons; index++)
652 if (This->connections[index].pAdvSink == NULL)
653 break;
656 if (index == This->maxCons)
658 This->maxCons+=INITIAL_SINKS;
659 This->connections = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
660 This->connections,
661 This->maxCons * sizeof(*This->connections));
662 This->remote_connections = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
663 This->remote_connections,
664 This->maxCons * sizeof(*This->remote_connections));
667 new_conn.pAdvSink = pAdvise;
668 new_conn.advf = advf & ~WINE_ADVF_REMOTE;
669 new_conn.formatetc = *pFetc;
670 new_conn.dwConnection = index + 1; /* 0 is not a valid cookie, so increment the index */
672 copy_statdata(This->connections + index, &new_conn);
674 if (This->connections[index].pAdvSink != NULL)
676 /* if we are already connected advise the remote object */
677 if (This->delegate)
679 HRESULT hr;
681 hr = IDataObject_DAdvise(This->delegate, &new_conn.formatetc,
682 new_conn.advf, new_conn.pAdvSink,
683 &This->remote_connections[index]);
684 if (FAILED(hr))
686 IDataAdviseHolder_Unadvise(iface, new_conn.dwConnection);
687 return hr;
689 This->connections[index].advf |= WINE_ADVF_REMOTE;
691 else if(advf & ADVF_PRIMEFIRST)
692 /* only do this if we have no delegate, since in the above case the
693 * delegate will do the priming for us */
694 IDataAdviseHolder_SendOnDataChange(iface, pDataObject, 0, advf);
697 *pdwConnection = new_conn.dwConnection;
699 return S_OK;
702 /******************************************************************************
703 * DataAdviseHolder_Unadvise
705 static HRESULT WINAPI DataAdviseHolder_Unadvise(IDataAdviseHolder *iface,
706 DWORD dwConnection)
708 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
709 DWORD index;
711 TRACE("%p, %lu.\n", iface, dwConnection);
713 /* The connection number is 1 more than the index, see DataAdviseHolder_Advise */
714 index = dwConnection - 1;
716 if (index >= This->maxCons || This->connections[index].pAdvSink == NULL)
717 return OLE_E_NOCONNECTION;
719 if (This->delegate && This->connections[index].advf & WINE_ADVF_REMOTE)
721 IDataObject_DUnadvise(This->delegate, This->remote_connections[index]);
722 This->remote_connections[index] = 0;
725 release_statdata(This->connections + index);
727 return S_OK;
730 /******************************************************************************
731 * DataAdviseHolder_EnumAdvise
733 static HRESULT WINAPI DataAdviseHolder_EnumAdvise(IDataAdviseHolder *iface,
734 IEnumSTATDATA **enum_advise)
736 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
737 IUnknown *unk;
738 HRESULT hr;
740 TRACE("(%p)->(%p)\n", This, enum_advise);
742 IDataAdviseHolder_QueryInterface(iface, &IID_IUnknown, (void**)&unk);
743 hr = EnumSTATDATA_Construct(unk, 0, This->maxCons, This->connections, TRUE, enum_advise);
744 IUnknown_Release(unk);
745 return hr;
748 /******************************************************************************
749 * DataAdviseHolder_SendOnDataChange
751 static HRESULT WINAPI DataAdviseHolder_SendOnDataChange(IDataAdviseHolder *iface,
752 IDataObject *data_obj,
753 DWORD dwReserved, DWORD advf)
755 IEnumSTATDATA *pEnum;
756 HRESULT hr;
758 TRACE("%p, %p, %#lx, %#lx.\n", iface, data_obj, dwReserved, advf);
760 hr = IDataAdviseHolder_EnumAdvise(iface, &pEnum);
761 if (SUCCEEDED(hr))
763 STATDATA statdata;
764 while (IEnumSTATDATA_Next(pEnum, 1, &statdata, NULL) == S_OK)
766 STGMEDIUM stg;
767 stg.tymed = TYMED_NULL;
768 stg.pstg = NULL;
769 stg.pUnkForRelease = NULL;
771 if(!(statdata.advf & ADVF_NODATA))
773 hr = IDataObject_GetData(data_obj, &statdata.formatetc, &stg);
776 IAdviseSink_OnDataChange(statdata.pAdvSink, &statdata.formatetc, &stg);
778 if(statdata.advf & ADVF_ONLYONCE)
780 IDataAdviseHolder_Unadvise(iface, statdata.dwConnection);
783 release_statdata(&statdata);
785 IEnumSTATDATA_Release(pEnum);
788 return S_OK;
791 /**************************************************************************
792 * DataAdviseHolderImpl_VTable
794 static const IDataAdviseHolderVtbl DataAdviseHolderImpl_VTable =
796 DataAdviseHolder_QueryInterface,
797 DataAdviseHolder_AddRef,
798 DataAdviseHolder_Release,
799 DataAdviseHolder_Advise,
800 DataAdviseHolder_Unadvise,
801 DataAdviseHolder_EnumAdvise,
802 DataAdviseHolder_SendOnDataChange
805 HRESULT DataAdviseHolder_OnConnect(IDataAdviseHolder *iface, IDataObject *pDelegate)
807 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
808 DWORD index;
809 HRESULT hr = S_OK;
811 for(index = 0; index < This->maxCons; index++)
813 if(This->connections[index].pAdvSink != NULL)
815 hr = IDataObject_DAdvise(pDelegate, &This->connections[index].formatetc,
816 This->connections[index].advf,
817 This->connections[index].pAdvSink,
818 &This->remote_connections[index]);
819 if (FAILED(hr)) break;
820 This->connections[index].advf |= WINE_ADVF_REMOTE;
823 This->delegate = pDelegate;
824 return hr;
827 void DataAdviseHolder_OnDisconnect(IDataAdviseHolder *iface)
829 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
830 DWORD index;
832 for(index = 0; index < This->maxCons; index++)
834 if((This->connections[index].pAdvSink != NULL) &&
835 (This->connections[index].advf & WINE_ADVF_REMOTE))
837 IDataObject_DUnadvise(This->delegate, This->remote_connections[index]);
838 This->remote_connections[index] = 0;
839 This->connections[index].advf &= ~WINE_ADVF_REMOTE;
842 This->delegate = NULL;
845 /******************************************************************************
846 * DataAdviseHolder_Constructor
848 static IDataAdviseHolder *DataAdviseHolder_Constructor(void)
850 DataAdviseHolder* newHolder;
852 newHolder = HeapAlloc(GetProcessHeap(), 0, sizeof(DataAdviseHolder));
854 newHolder->IDataAdviseHolder_iface.lpVtbl = &DataAdviseHolderImpl_VTable;
855 newHolder->ref = 1;
856 newHolder->maxCons = INITIAL_SINKS;
857 newHolder->connections = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
858 newHolder->maxCons * sizeof(*newHolder->connections));
859 newHolder->remote_connections = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
860 newHolder->maxCons * sizeof(*newHolder->remote_connections));
861 newHolder->delegate = NULL;
863 TRACE("returning %p\n", &newHolder->IDataAdviseHolder_iface);
864 return &newHolder->IDataAdviseHolder_iface;
867 /***********************************************************************
868 * API functions
871 /***********************************************************************
872 * CreateOleAdviseHolder [OLE32.@]
874 HRESULT WINAPI CreateOleAdviseHolder(IOleAdviseHolder **ppOAHolder)
876 TRACE("(%p)\n", ppOAHolder);
878 if (ppOAHolder==NULL)
879 return E_POINTER;
881 *ppOAHolder = OleAdviseHolderImpl_Constructor ();
883 if (*ppOAHolder != NULL)
884 return S_OK;
886 return E_OUTOFMEMORY;
889 /******************************************************************************
890 * CreateDataAdviseHolder [OLE32.@]
892 HRESULT WINAPI CreateDataAdviseHolder(IDataAdviseHolder **ppDAHolder)
894 TRACE("(%p)\n", ppDAHolder);
896 if (ppDAHolder==NULL)
897 return E_POINTER;
899 *ppDAHolder = DataAdviseHolder_Constructor();
901 if (*ppDAHolder != NULL)
902 return S_OK;
904 return E_OUTOFMEMORY;