setupapi: Fix string conversion in SetupGetInfInformationA().
[wine.git] / dlls / ole32 / oleobj.c
blob968456d3108b6ca33ead7367946fa5b7b0a16fee
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
28 #define NONAMELESSSTRUCT
30 #include "windef.h"
31 #include "winbase.h"
32 #include "winuser.h"
33 #include "winerror.h"
34 #include "wine/debug.h"
35 #include "ole2.h"
37 #include "compobj_private.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(ole);
41 #define INITIAL_SINKS 10
43 static void release_statdata(STATDATA *data)
45 if(data->formatetc.ptd)
47 CoTaskMemFree(data->formatetc.ptd);
48 data->formatetc.ptd = NULL;
51 if(data->pAdvSink)
53 IAdviseSink_Release(data->pAdvSink);
54 data->pAdvSink = NULL;
58 static HRESULT copy_statdata(STATDATA *dst, const STATDATA *src)
60 *dst = *src;
61 if(src->formatetc.ptd)
63 dst->formatetc.ptd = CoTaskMemAlloc(src->formatetc.ptd->tdSize);
64 if(!dst->formatetc.ptd) return E_OUTOFMEMORY;
65 memcpy(dst->formatetc.ptd, src->formatetc.ptd, src->formatetc.ptd->tdSize);
67 if(dst->pAdvSink) IAdviseSink_AddRef(dst->pAdvSink);
68 return S_OK;
71 /**************************************************************************
72 * EnumSTATDATA Implementation
75 static HRESULT EnumSTATDATA_Construct(IUnknown *holder, ULONG index, DWORD array_len, STATDATA *data, IEnumSTATDATA **ppenum);
77 typedef struct
79 IEnumSTATDATA IEnumSTATDATA_iface;
80 LONG ref;
82 ULONG index;
83 DWORD num_of_elems;
84 STATDATA *statdata;
85 IUnknown *holder;
86 } EnumSTATDATA;
88 static inline EnumSTATDATA *impl_from_IEnumSTATDATA(IEnumSTATDATA *iface)
90 return CONTAINING_RECORD(iface, EnumSTATDATA, IEnumSTATDATA_iface);
93 static HRESULT WINAPI EnumSTATDATA_QueryInterface(IEnumSTATDATA *iface, REFIID riid, void **ppv)
95 TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
96 if (IsEqualIID(riid, &IID_IUnknown) ||
97 IsEqualIID(riid, &IID_IEnumSTATDATA))
99 IEnumSTATDATA_AddRef(iface);
100 *ppv = iface;
101 return S_OK;
103 return E_NOINTERFACE;
106 static ULONG WINAPI EnumSTATDATA_AddRef(IEnumSTATDATA *iface)
108 EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
109 TRACE("()\n");
110 return InterlockedIncrement(&This->ref);
113 static ULONG WINAPI EnumSTATDATA_Release(IEnumSTATDATA *iface)
115 EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
116 LONG refs = InterlockedDecrement(&This->ref);
117 TRACE("()\n");
118 if (!refs)
120 DWORD i;
121 for(i = 0; i < This->num_of_elems; i++)
122 release_statdata(This->statdata + i);
123 HeapFree(GetProcessHeap(), 0, This->statdata);
124 IUnknown_Release(This->holder);
125 HeapFree(GetProcessHeap(), 0, This);
127 return refs;
130 static HRESULT WINAPI EnumSTATDATA_Next(IEnumSTATDATA *iface, ULONG num, LPSTATDATA data,
131 ULONG *fetched)
133 EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
134 DWORD count = 0;
135 HRESULT hr = S_OK;
137 TRACE("(%d, %p, %p)\n", num, data, fetched);
139 while(num--)
141 if (This->index >= This->num_of_elems)
143 hr = S_FALSE;
144 break;
147 copy_statdata(data + count, This->statdata + This->index);
149 count++;
150 This->index++;
153 if (fetched) *fetched = count;
155 return hr;
158 static HRESULT WINAPI EnumSTATDATA_Skip(IEnumSTATDATA *iface, ULONG num)
160 EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
162 TRACE("(%d)\n", num);
164 if(This->index + num >= This->num_of_elems)
166 This->index = This->num_of_elems;
167 return S_FALSE;
170 This->index += num;
171 return S_OK;
174 static HRESULT WINAPI EnumSTATDATA_Reset(IEnumSTATDATA *iface)
176 EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
178 TRACE("()\n");
180 This->index = 0;
181 return S_OK;
184 static HRESULT WINAPI EnumSTATDATA_Clone(IEnumSTATDATA *iface, IEnumSTATDATA **ppenum)
186 EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
188 return EnumSTATDATA_Construct(This->holder, This->index, This->num_of_elems, This->statdata, ppenum);
191 static const IEnumSTATDATAVtbl EnumSTATDATA_VTable =
193 EnumSTATDATA_QueryInterface,
194 EnumSTATDATA_AddRef,
195 EnumSTATDATA_Release,
196 EnumSTATDATA_Next,
197 EnumSTATDATA_Skip,
198 EnumSTATDATA_Reset,
199 EnumSTATDATA_Clone
202 static HRESULT EnumSTATDATA_Construct(IUnknown *holder, ULONG index, DWORD array_len, STATDATA *data,
203 IEnumSTATDATA **ppenum)
205 EnumSTATDATA *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
206 DWORD i, count;
208 if (!This) return E_OUTOFMEMORY;
210 This->IEnumSTATDATA_iface.lpVtbl = &EnumSTATDATA_VTable;
211 This->ref = 1;
212 This->index = index;
214 This->statdata = HeapAlloc(GetProcessHeap(), 0, array_len * sizeof(*This->statdata));
215 if(!This->statdata)
217 HeapFree(GetProcessHeap(), 0, This);
218 return E_OUTOFMEMORY;
221 for(i = 0, count = 0; i < array_len; i++)
223 if(data[i].pAdvSink)
225 copy_statdata(This->statdata + count, data + i);
226 count++;
230 This->num_of_elems = count;
231 This->holder = holder;
232 IUnknown_AddRef(holder);
233 *ppenum = &This->IEnumSTATDATA_iface;
234 return S_OK;
237 /**************************************************************************
238 * OleAdviseHolder Implementation
240 typedef struct
242 IOleAdviseHolder IOleAdviseHolder_iface;
244 LONG ref;
246 DWORD max_cons;
247 STATDATA *connections;
248 } OleAdviseHolderImpl;
250 static inline OleAdviseHolderImpl *impl_from_IOleAdviseHolder(IOleAdviseHolder *iface)
252 return CONTAINING_RECORD(iface, OleAdviseHolderImpl, IOleAdviseHolder_iface);
255 /**************************************************************************
256 * OleAdviseHolderImpl_Destructor
258 static void OleAdviseHolderImpl_Destructor(OleAdviseHolderImpl *This)
260 DWORD index;
261 TRACE("%p\n", This);
263 for (index = 0; index < This->max_cons; index++)
265 if (This->connections[index].pAdvSink != NULL)
266 release_statdata(This->connections + index);
269 HeapFree(GetProcessHeap(), 0, This->connections);
270 HeapFree(GetProcessHeap(), 0, This);
273 /**************************************************************************
274 * OleAdviseHolderImpl_QueryInterface
276 static HRESULT WINAPI OleAdviseHolderImpl_QueryInterface(IOleAdviseHolder *iface,
277 REFIID iid, void **obj)
279 OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
280 TRACE("(%p)->(%s,%p)\n",This, debugstr_guid(iid), obj);
282 if (obj == NULL)
283 return E_POINTER;
285 *obj = NULL;
287 if (IsEqualIID(iid, &IID_IUnknown) ||
288 IsEqualIID(iid, &IID_IOleAdviseHolder))
290 *obj = &This->IOleAdviseHolder_iface;
293 if(*obj == NULL)
294 return E_NOINTERFACE;
296 IUnknown_AddRef((IUnknown*)*obj);
298 return S_OK;
301 /******************************************************************************
302 * OleAdviseHolderImpl_AddRef
304 static ULONG WINAPI OleAdviseHolderImpl_AddRef(IOleAdviseHolder *iface)
306 OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
307 ULONG ref = InterlockedIncrement(&This->ref);
309 TRACE("(%p)->(ref=%d)\n", This, ref - 1);
311 return ref;
314 /******************************************************************************
315 * OleAdviseHolderImpl_Release
317 static ULONG WINAPI OleAdviseHolderImpl_Release(IOleAdviseHolder *iface)
319 OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
320 ULONG ref;
321 TRACE("(%p)->(ref=%d)\n", This, This->ref);
322 ref = InterlockedDecrement(&This->ref);
324 if (ref == 0) OleAdviseHolderImpl_Destructor(This);
326 return ref;
329 /******************************************************************************
330 * OleAdviseHolderImpl_Advise
332 static HRESULT WINAPI OleAdviseHolderImpl_Advise(IOleAdviseHolder *iface,
333 IAdviseSink *pAdvise,
334 DWORD *pdwConnection)
336 DWORD index;
337 OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
338 STATDATA new_conn;
339 static const FORMATETC empty_fmtetc = {0, NULL, 0, -1, 0};
341 TRACE("(%p)->(%p, %p)\n", This, pAdvise, pdwConnection);
343 if (pdwConnection==NULL)
344 return E_POINTER;
346 *pdwConnection = 0;
348 for (index = 0; index < This->max_cons; index++)
350 if (This->connections[index].pAdvSink == NULL)
351 break;
354 if (index == This->max_cons)
356 This->max_cons += INITIAL_SINKS;
357 This->connections = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->connections,
358 This->max_cons * sizeof(*This->connections));
361 new_conn.pAdvSink = pAdvise;
362 new_conn.advf = 0;
363 new_conn.formatetc = empty_fmtetc;
364 new_conn.dwConnection = index + 1; /* 0 is not a valid cookie, so increment the index */
366 copy_statdata(This->connections + index, &new_conn);
368 *pdwConnection = new_conn.dwConnection;
370 return S_OK;
373 /******************************************************************************
374 * OleAdviseHolderImpl_Unadvise
376 static HRESULT WINAPI OleAdviseHolderImpl_Unadvise(IOleAdviseHolder *iface,
377 DWORD dwConnection)
379 OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
380 DWORD index;
382 TRACE("(%p)->(%u)\n", This, dwConnection);
384 /* The connection number is 1 more than the index, see OleAdviseHolder_Advise */
385 index = dwConnection - 1;
387 if (index >= This->max_cons || This->connections[index].pAdvSink == NULL)
388 return OLE_E_NOCONNECTION;
390 release_statdata(This->connections + index);
392 return S_OK;
395 /******************************************************************************
396 * OleAdviseHolderImpl_EnumAdvise
398 static HRESULT WINAPI OleAdviseHolderImpl_EnumAdvise(IOleAdviseHolder *iface, IEnumSTATDATA **enum_advise)
400 OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
401 IUnknown *unk;
402 HRESULT hr;
404 TRACE("(%p)->(%p)\n", This, enum_advise);
406 IOleAdviseHolder_QueryInterface(iface, &IID_IUnknown, (void**)&unk);
407 hr = EnumSTATDATA_Construct(unk, 0, This->max_cons, This->connections, enum_advise);
408 IUnknown_Release(unk);
409 return hr;
412 /******************************************************************************
413 * OleAdviseHolderImpl_SendOnRename
415 static HRESULT WINAPI OleAdviseHolderImpl_SendOnRename(IOleAdviseHolder *iface, IMoniker *pmk)
417 IEnumSTATDATA *pEnum;
418 HRESULT hr;
420 TRACE("(%p)->(%p)\n", iface, pmk);
422 hr = IOleAdviseHolder_EnumAdvise(iface, &pEnum);
423 if (SUCCEEDED(hr))
425 STATDATA statdata;
426 while (IEnumSTATDATA_Next(pEnum, 1, &statdata, NULL) == S_OK)
428 IAdviseSink_OnRename(statdata.pAdvSink, pmk);
430 IAdviseSink_Release(statdata.pAdvSink);
432 IEnumSTATDATA_Release(pEnum);
435 return hr;
438 /******************************************************************************
439 * OleAdviseHolderImpl_SendOnSave
441 static HRESULT WINAPI OleAdviseHolderImpl_SendOnSave(IOleAdviseHolder *iface)
443 IEnumSTATDATA *pEnum;
444 HRESULT hr;
446 TRACE("(%p)->()\n", iface);
448 hr = IOleAdviseHolder_EnumAdvise(iface, &pEnum);
449 if (SUCCEEDED(hr))
451 STATDATA statdata;
452 while (IEnumSTATDATA_Next(pEnum, 1, &statdata, NULL) == S_OK)
454 IAdviseSink_OnSave(statdata.pAdvSink);
456 IAdviseSink_Release(statdata.pAdvSink);
458 IEnumSTATDATA_Release(pEnum);
461 return hr;
464 /******************************************************************************
465 * OleAdviseHolderImpl_SendOnClose
467 static HRESULT WINAPI OleAdviseHolderImpl_SendOnClose(IOleAdviseHolder *iface)
469 IEnumSTATDATA *pEnum;
470 HRESULT hr;
472 TRACE("(%p)->()\n", iface);
474 hr = IOleAdviseHolder_EnumAdvise(iface, &pEnum);
475 if (SUCCEEDED(hr))
477 STATDATA statdata;
478 while (IEnumSTATDATA_Next(pEnum, 1, &statdata, NULL) == S_OK)
480 IAdviseSink_OnClose(statdata.pAdvSink);
482 IAdviseSink_Release(statdata.pAdvSink);
484 IEnumSTATDATA_Release(pEnum);
487 return hr;
490 /**************************************************************************
491 * OleAdviseHolderImpl_VTable
493 static const IOleAdviseHolderVtbl oahvt =
495 OleAdviseHolderImpl_QueryInterface,
496 OleAdviseHolderImpl_AddRef,
497 OleAdviseHolderImpl_Release,
498 OleAdviseHolderImpl_Advise,
499 OleAdviseHolderImpl_Unadvise,
500 OleAdviseHolderImpl_EnumAdvise,
501 OleAdviseHolderImpl_SendOnRename,
502 OleAdviseHolderImpl_SendOnSave,
503 OleAdviseHolderImpl_SendOnClose
506 /**************************************************************************
507 * OleAdviseHolderImpl_Constructor
510 static IOleAdviseHolder *OleAdviseHolderImpl_Constructor(void)
512 OleAdviseHolderImpl* lpoah;
514 lpoah = HeapAlloc(GetProcessHeap(), 0, sizeof(OleAdviseHolderImpl));
516 lpoah->IOleAdviseHolder_iface.lpVtbl = &oahvt;
517 lpoah->ref = 1;
518 lpoah->max_cons = INITIAL_SINKS;
519 lpoah->connections = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
520 lpoah->max_cons * sizeof(*lpoah->connections));
522 TRACE("returning %p\n", &lpoah->IOleAdviseHolder_iface);
523 return &lpoah->IOleAdviseHolder_iface;
526 /**************************************************************************
527 * DataAdviseHolder Implementation
529 typedef struct
531 IDataAdviseHolder IDataAdviseHolder_iface;
533 LONG ref;
534 DWORD maxCons;
535 STATDATA* connections;
536 DWORD* remote_connections;
537 IDataObject* delegate;
538 } DataAdviseHolder;
540 /* this connection has also has been advised to the delegate data object */
541 #define WINE_ADVF_REMOTE 0x80000000
543 static inline DataAdviseHolder *impl_from_IDataAdviseHolder(IDataAdviseHolder *iface)
545 return CONTAINING_RECORD(iface, DataAdviseHolder, IDataAdviseHolder_iface);
548 /******************************************************************************
549 * DataAdviseHolder_Destructor
551 static void DataAdviseHolder_Destructor(DataAdviseHolder* ptrToDestroy)
553 DWORD index;
554 TRACE("%p\n", ptrToDestroy);
556 for (index = 0; index < ptrToDestroy->maxCons; index++)
558 if (ptrToDestroy->connections[index].pAdvSink != NULL)
560 if (ptrToDestroy->delegate &&
561 (ptrToDestroy->connections[index].advf & WINE_ADVF_REMOTE))
562 IDataObject_DUnadvise(ptrToDestroy->delegate,
563 ptrToDestroy->remote_connections[index]);
565 release_statdata(ptrToDestroy->connections + index);
569 HeapFree(GetProcessHeap(), 0, ptrToDestroy->remote_connections);
570 HeapFree(GetProcessHeap(), 0, ptrToDestroy->connections);
571 HeapFree(GetProcessHeap(), 0, ptrToDestroy);
574 /************************************************************************
575 * DataAdviseHolder_QueryInterface (IUnknown)
577 static HRESULT WINAPI DataAdviseHolder_QueryInterface(IDataAdviseHolder *iface,
578 REFIID riid, void **ppvObject)
580 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
581 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObject);
583 if ( (This==0) || (ppvObject==0) )
584 return E_INVALIDARG;
586 *ppvObject = 0;
588 if ( IsEqualIID(&IID_IUnknown, riid) ||
589 IsEqualIID(&IID_IDataAdviseHolder, riid) )
591 *ppvObject = iface;
594 if ((*ppvObject)==0)
596 return E_NOINTERFACE;
599 IUnknown_AddRef((IUnknown*)*ppvObject);
600 return S_OK;
603 /************************************************************************
604 * DataAdviseHolder_AddRef (IUnknown)
606 static ULONG WINAPI DataAdviseHolder_AddRef(IDataAdviseHolder *iface)
608 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
609 TRACE("(%p) (ref=%d)\n", This, This->ref);
610 return InterlockedIncrement(&This->ref);
613 /************************************************************************
614 * DataAdviseHolder_Release (IUnknown)
616 static ULONG WINAPI DataAdviseHolder_Release(IDataAdviseHolder *iface)
618 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
619 ULONG ref;
620 TRACE("(%p) (ref=%d)\n", This, This->ref);
622 ref = InterlockedDecrement(&This->ref);
623 if (ref==0) DataAdviseHolder_Destructor(This);
625 return ref;
628 /************************************************************************
629 * DataAdviseHolder_Advise
632 static HRESULT WINAPI DataAdviseHolder_Advise(IDataAdviseHolder *iface,
633 IDataObject *pDataObject, FORMATETC *pFetc,
634 DWORD advf, IAdviseSink *pAdvise,
635 DWORD *pdwConnection)
637 DWORD index;
638 STATDATA new_conn;
639 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
641 TRACE("(%p)->(%p, %p, %08x, %p, %p)\n", This, pDataObject, pFetc, advf,
642 pAdvise, pdwConnection);
644 if (pdwConnection==NULL)
645 return E_POINTER;
647 *pdwConnection = 0;
649 for (index = 0; index < This->maxCons; index++)
651 if (This->connections[index].pAdvSink == NULL)
652 break;
655 if (index == This->maxCons)
657 This->maxCons+=INITIAL_SINKS;
658 This->connections = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
659 This->connections,
660 This->maxCons * sizeof(*This->connections));
661 This->remote_connections = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
662 This->remote_connections,
663 This->maxCons * sizeof(*This->remote_connections));
666 new_conn.pAdvSink = pAdvise;
667 new_conn.advf = advf & ~WINE_ADVF_REMOTE;
668 new_conn.formatetc = *pFetc;
669 new_conn.dwConnection = index + 1; /* 0 is not a valid cookie, so increment the index */
671 copy_statdata(This->connections + index, &new_conn);
673 if (This->connections[index].pAdvSink != NULL)
675 /* if we are already connected advise the remote object */
676 if (This->delegate)
678 HRESULT hr;
680 hr = IDataObject_DAdvise(This->delegate, &new_conn.formatetc,
681 new_conn.advf, new_conn.pAdvSink,
682 &This->remote_connections[index]);
683 if (FAILED(hr))
685 IDataAdviseHolder_Unadvise(iface, new_conn.dwConnection);
686 return hr;
688 This->connections[index].advf |= WINE_ADVF_REMOTE;
690 else if(advf & ADVF_PRIMEFIRST)
691 /* only do this if we have no delegate, since in the above case the
692 * delegate will do the priming for us */
693 IDataAdviseHolder_SendOnDataChange(iface, pDataObject, 0, advf);
696 *pdwConnection = new_conn.dwConnection;
698 return S_OK;
701 /******************************************************************************
702 * DataAdviseHolder_Unadvise
704 static HRESULT WINAPI DataAdviseHolder_Unadvise(IDataAdviseHolder *iface,
705 DWORD dwConnection)
707 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
708 DWORD index;
709 TRACE("(%p)->(%u)\n", This, dwConnection);
711 /* The connection number is 1 more than the index, see DataAdviseHolder_Advise */
712 index = dwConnection - 1;
714 if (index >= This->maxCons || This->connections[index].pAdvSink == NULL)
715 return OLE_E_NOCONNECTION;
717 if (This->delegate && This->connections[index].advf & WINE_ADVF_REMOTE)
719 IDataObject_DUnadvise(This->delegate, This->remote_connections[index]);
720 This->remote_connections[index] = 0;
723 release_statdata(This->connections + index);
725 return S_OK;
728 /******************************************************************************
729 * DataAdviseHolder_EnumAdvise
731 static HRESULT WINAPI DataAdviseHolder_EnumAdvise(IDataAdviseHolder *iface,
732 IEnumSTATDATA **enum_advise)
734 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
735 IUnknown *unk;
736 HRESULT hr;
738 TRACE("(%p)->(%p)\n", This, enum_advise);
740 IDataAdviseHolder_QueryInterface(iface, &IID_IUnknown, (void**)&unk);
741 hr = EnumSTATDATA_Construct(unk, 0, This->maxCons, This->connections, enum_advise);
742 IUnknown_Release(unk);
743 return hr;
746 /******************************************************************************
747 * DataAdviseHolder_SendOnDataChange
749 static HRESULT WINAPI DataAdviseHolder_SendOnDataChange(IDataAdviseHolder *iface,
750 IDataObject *data_obj,
751 DWORD dwReserved, DWORD advf)
753 IEnumSTATDATA *pEnum;
754 HRESULT hr;
756 TRACE("(%p)->(%p, %08x, %08x)\n", iface, data_obj, dwReserved, advf);
758 hr = IDataAdviseHolder_EnumAdvise(iface, &pEnum);
759 if (SUCCEEDED(hr))
761 STATDATA statdata;
762 while (IEnumSTATDATA_Next(pEnum, 1, &statdata, NULL) == S_OK)
764 STGMEDIUM stg;
765 stg.tymed = TYMED_NULL;
766 stg.u.pstg = NULL;
767 stg.pUnkForRelease = NULL;
769 if(!(statdata.advf & ADVF_NODATA))
771 hr = IDataObject_GetData(data_obj, &statdata.formatetc, &stg);
774 IAdviseSink_OnDataChange(statdata.pAdvSink, &statdata.formatetc, &stg);
776 if(statdata.advf & ADVF_ONLYONCE)
778 IDataAdviseHolder_Unadvise(iface, statdata.dwConnection);
781 release_statdata(&statdata);
783 IEnumSTATDATA_Release(pEnum);
786 return S_OK;
789 /**************************************************************************
790 * DataAdviseHolderImpl_VTable
792 static const IDataAdviseHolderVtbl DataAdviseHolderImpl_VTable =
794 DataAdviseHolder_QueryInterface,
795 DataAdviseHolder_AddRef,
796 DataAdviseHolder_Release,
797 DataAdviseHolder_Advise,
798 DataAdviseHolder_Unadvise,
799 DataAdviseHolder_EnumAdvise,
800 DataAdviseHolder_SendOnDataChange
803 HRESULT DataAdviseHolder_OnConnect(IDataAdviseHolder *iface, IDataObject *pDelegate)
805 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
806 DWORD index;
807 HRESULT hr = S_OK;
809 for(index = 0; index < This->maxCons; index++)
811 if(This->connections[index].pAdvSink != NULL)
813 hr = IDataObject_DAdvise(pDelegate, &This->connections[index].formatetc,
814 This->connections[index].advf,
815 This->connections[index].pAdvSink,
816 &This->remote_connections[index]);
817 if (FAILED(hr)) break;
818 This->connections[index].advf |= WINE_ADVF_REMOTE;
821 This->delegate = pDelegate;
822 return hr;
825 void DataAdviseHolder_OnDisconnect(IDataAdviseHolder *iface)
827 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
828 DWORD index;
830 for(index = 0; index < This->maxCons; index++)
832 if((This->connections[index].pAdvSink != NULL) &&
833 (This->connections[index].advf & WINE_ADVF_REMOTE))
835 IDataObject_DUnadvise(This->delegate, This->remote_connections[index]);
836 This->remote_connections[index] = 0;
837 This->connections[index].advf &= ~WINE_ADVF_REMOTE;
840 This->delegate = NULL;
843 /******************************************************************************
844 * DataAdviseHolder_Constructor
846 static IDataAdviseHolder *DataAdviseHolder_Constructor(void)
848 DataAdviseHolder* newHolder;
850 newHolder = HeapAlloc(GetProcessHeap(), 0, sizeof(DataAdviseHolder));
852 newHolder->IDataAdviseHolder_iface.lpVtbl = &DataAdviseHolderImpl_VTable;
853 newHolder->ref = 1;
854 newHolder->maxCons = INITIAL_SINKS;
855 newHolder->connections = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
856 newHolder->maxCons * sizeof(*newHolder->connections));
857 newHolder->remote_connections = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
858 newHolder->maxCons * sizeof(*newHolder->remote_connections));
859 newHolder->delegate = NULL;
861 TRACE("returning %p\n", &newHolder->IDataAdviseHolder_iface);
862 return &newHolder->IDataAdviseHolder_iface;
865 /***********************************************************************
866 * API functions
869 /***********************************************************************
870 * CreateOleAdviseHolder [OLE32.@]
872 HRESULT WINAPI CreateOleAdviseHolder(IOleAdviseHolder **ppOAHolder)
874 TRACE("(%p)\n", ppOAHolder);
876 if (ppOAHolder==NULL)
877 return E_POINTER;
879 *ppOAHolder = OleAdviseHolderImpl_Constructor ();
881 if (*ppOAHolder != NULL)
882 return S_OK;
884 return E_OUTOFMEMORY;
887 /******************************************************************************
888 * CreateDataAdviseHolder [OLE32.@]
890 HRESULT WINAPI CreateDataAdviseHolder(IDataAdviseHolder **ppDAHolder)
892 TRACE("(%p)\n", ppDAHolder);
894 if (ppDAHolder==NULL)
895 return E_POINTER;
897 *ppDAHolder = DataAdviseHolder_Constructor();
899 if (*ppDAHolder != NULL)
900 return S_OK;
902 return E_OUTOFMEMORY;