ddraw/tests: Add another invalid arguments test for surface QI.
[wine.git] / dlls / ole32 / oleobj.c
blob44e15e551f5c0834ebad283dd38e6509e3a7061f
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 HRESULT hr;
61 hr = copy_formatetc( &dst->formatetc, &src->formatetc );
62 if (FAILED(hr)) return hr;
63 dst->advf = src->advf;
64 dst->pAdvSink = src->pAdvSink;
65 if (dst->pAdvSink) IAdviseSink_AddRef( dst->pAdvSink );
66 dst->dwConnection = src->dwConnection;
67 return S_OK;
70 /**************************************************************************
71 * EnumSTATDATA Implementation
74 typedef struct
76 IEnumSTATDATA IEnumSTATDATA_iface;
77 LONG ref;
79 ULONG index;
80 DWORD num_of_elems;
81 STATDATA *statdata;
82 IUnknown *holder;
83 } EnumSTATDATA;
85 static inline EnumSTATDATA *impl_from_IEnumSTATDATA(IEnumSTATDATA *iface)
87 return CONTAINING_RECORD(iface, EnumSTATDATA, IEnumSTATDATA_iface);
90 static HRESULT WINAPI EnumSTATDATA_QueryInterface(IEnumSTATDATA *iface, REFIID riid, void **ppv)
92 TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
93 if (IsEqualIID(riid, &IID_IUnknown) ||
94 IsEqualIID(riid, &IID_IEnumSTATDATA))
96 IEnumSTATDATA_AddRef(iface);
97 *ppv = iface;
98 return S_OK;
100 return E_NOINTERFACE;
103 static ULONG WINAPI EnumSTATDATA_AddRef(IEnumSTATDATA *iface)
105 EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
106 TRACE("()\n");
107 return InterlockedIncrement(&This->ref);
110 static ULONG WINAPI EnumSTATDATA_Release(IEnumSTATDATA *iface)
112 EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
113 LONG refs = InterlockedDecrement(&This->ref);
114 TRACE("()\n");
115 if (!refs)
117 DWORD i;
118 for(i = 0; i < This->num_of_elems; i++)
119 release_statdata(This->statdata + i);
120 HeapFree(GetProcessHeap(), 0, This->statdata);
121 if (This->holder) IUnknown_Release(This->holder);
122 HeapFree(GetProcessHeap(), 0, This);
124 return refs;
127 static HRESULT WINAPI EnumSTATDATA_Next(IEnumSTATDATA *iface, ULONG num, LPSTATDATA data,
128 ULONG *fetched)
130 EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
131 DWORD count = 0;
132 HRESULT hr = S_OK;
134 TRACE("(%d, %p, %p)\n", num, data, fetched);
136 while(num--)
138 if (This->index >= This->num_of_elems)
140 hr = S_FALSE;
141 break;
144 copy_statdata(data + count, This->statdata + This->index);
146 count++;
147 This->index++;
150 if (fetched) *fetched = count;
152 return hr;
155 static HRESULT WINAPI EnumSTATDATA_Skip(IEnumSTATDATA *iface, ULONG num)
157 EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
159 TRACE("(%d)\n", num);
161 if(This->index + num >= This->num_of_elems)
163 This->index = This->num_of_elems;
164 return S_FALSE;
167 This->index += num;
168 return S_OK;
171 static HRESULT WINAPI EnumSTATDATA_Reset(IEnumSTATDATA *iface)
173 EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
175 TRACE("()\n");
177 This->index = 0;
178 return S_OK;
181 static HRESULT WINAPI EnumSTATDATA_Clone(IEnumSTATDATA *iface, IEnumSTATDATA **ppenum)
183 EnumSTATDATA *This = impl_from_IEnumSTATDATA(iface);
185 return EnumSTATDATA_Construct(This->holder, This->index, This->num_of_elems, This->statdata,
186 TRUE, ppenum);
189 static const IEnumSTATDATAVtbl EnumSTATDATA_VTable =
191 EnumSTATDATA_QueryInterface,
192 EnumSTATDATA_AddRef,
193 EnumSTATDATA_Release,
194 EnumSTATDATA_Next,
195 EnumSTATDATA_Skip,
196 EnumSTATDATA_Reset,
197 EnumSTATDATA_Clone
200 HRESULT EnumSTATDATA_Construct(IUnknown *holder, ULONG index, DWORD array_len, STATDATA *data,
201 BOOL copy, IEnumSTATDATA **ppenum)
203 EnumSTATDATA *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
204 DWORD i, count;
206 if (!This) return E_OUTOFMEMORY;
208 This->IEnumSTATDATA_iface.lpVtbl = &EnumSTATDATA_VTable;
209 This->ref = 1;
210 This->index = index;
212 if (copy)
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 else
232 This->statdata = data;
233 count = array_len;
236 This->num_of_elems = count;
237 This->holder = holder;
238 if (holder) IUnknown_AddRef(holder);
239 *ppenum = &This->IEnumSTATDATA_iface;
240 return S_OK;
243 /**************************************************************************
244 * OleAdviseHolder Implementation
246 typedef struct
248 IOleAdviseHolder IOleAdviseHolder_iface;
250 LONG ref;
252 DWORD max_cons;
253 STATDATA *connections;
254 } OleAdviseHolderImpl;
256 static inline OleAdviseHolderImpl *impl_from_IOleAdviseHolder(IOleAdviseHolder *iface)
258 return CONTAINING_RECORD(iface, OleAdviseHolderImpl, IOleAdviseHolder_iface);
261 /**************************************************************************
262 * OleAdviseHolderImpl_Destructor
264 static void OleAdviseHolderImpl_Destructor(OleAdviseHolderImpl *This)
266 DWORD index;
267 TRACE("%p\n", This);
269 for (index = 0; index < This->max_cons; index++)
271 if (This->connections[index].pAdvSink != NULL)
272 release_statdata(This->connections + index);
275 HeapFree(GetProcessHeap(), 0, This->connections);
276 HeapFree(GetProcessHeap(), 0, This);
279 /**************************************************************************
280 * OleAdviseHolderImpl_QueryInterface
282 static HRESULT WINAPI OleAdviseHolderImpl_QueryInterface(IOleAdviseHolder *iface,
283 REFIID iid, void **obj)
285 OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
286 TRACE("(%p)->(%s,%p)\n",This, debugstr_guid(iid), obj);
288 if (obj == NULL)
289 return E_POINTER;
291 *obj = NULL;
293 if (IsEqualIID(iid, &IID_IUnknown) ||
294 IsEqualIID(iid, &IID_IOleAdviseHolder))
296 *obj = &This->IOleAdviseHolder_iface;
299 if(*obj == NULL)
300 return E_NOINTERFACE;
302 IUnknown_AddRef((IUnknown*)*obj);
304 return S_OK;
307 /******************************************************************************
308 * OleAdviseHolderImpl_AddRef
310 static ULONG WINAPI OleAdviseHolderImpl_AddRef(IOleAdviseHolder *iface)
312 OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
313 ULONG ref = InterlockedIncrement(&This->ref);
315 TRACE("(%p)->(ref=%d)\n", This, ref - 1);
317 return ref;
320 /******************************************************************************
321 * OleAdviseHolderImpl_Release
323 static ULONG WINAPI OleAdviseHolderImpl_Release(IOleAdviseHolder *iface)
325 OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
326 ULONG ref;
327 TRACE("(%p)->(ref=%d)\n", This, This->ref);
328 ref = InterlockedDecrement(&This->ref);
330 if (ref == 0) OleAdviseHolderImpl_Destructor(This);
332 return ref;
335 /******************************************************************************
336 * OleAdviseHolderImpl_Advise
338 static HRESULT WINAPI OleAdviseHolderImpl_Advise(IOleAdviseHolder *iface,
339 IAdviseSink *pAdvise,
340 DWORD *pdwConnection)
342 DWORD index;
343 OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
344 STATDATA new_conn;
345 static const FORMATETC empty_fmtetc = {0, NULL, 0, -1, 0};
347 TRACE("(%p)->(%p, %p)\n", This, pAdvise, pdwConnection);
349 if (pdwConnection==NULL)
350 return E_POINTER;
352 *pdwConnection = 0;
354 for (index = 0; index < This->max_cons; index++)
356 if (This->connections[index].pAdvSink == NULL)
357 break;
360 if (index == This->max_cons)
362 This->max_cons += INITIAL_SINKS;
363 This->connections = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->connections,
364 This->max_cons * sizeof(*This->connections));
367 new_conn.pAdvSink = pAdvise;
368 new_conn.advf = 0;
369 new_conn.formatetc = empty_fmtetc;
370 new_conn.dwConnection = index + 1; /* 0 is not a valid cookie, so increment the index */
372 copy_statdata(This->connections + index, &new_conn);
374 *pdwConnection = new_conn.dwConnection;
376 return S_OK;
379 /******************************************************************************
380 * OleAdviseHolderImpl_Unadvise
382 static HRESULT WINAPI OleAdviseHolderImpl_Unadvise(IOleAdviseHolder *iface,
383 DWORD dwConnection)
385 OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
386 DWORD index;
388 TRACE("(%p)->(%u)\n", This, dwConnection);
390 /* The connection number is 1 more than the index, see OleAdviseHolder_Advise */
391 index = dwConnection - 1;
393 if (index >= This->max_cons || This->connections[index].pAdvSink == NULL)
394 return OLE_E_NOCONNECTION;
396 release_statdata(This->connections + index);
398 return S_OK;
401 /******************************************************************************
402 * OleAdviseHolderImpl_EnumAdvise
404 static HRESULT WINAPI OleAdviseHolderImpl_EnumAdvise(IOleAdviseHolder *iface, IEnumSTATDATA **enum_advise)
406 OleAdviseHolderImpl *This = impl_from_IOleAdviseHolder(iface);
407 IUnknown *unk;
408 HRESULT hr;
410 TRACE("(%p)->(%p)\n", This, enum_advise);
412 IOleAdviseHolder_QueryInterface(iface, &IID_IUnknown, (void**)&unk);
413 hr = EnumSTATDATA_Construct(unk, 0, This->max_cons, This->connections, TRUE, enum_advise);
414 IUnknown_Release(unk);
415 return hr;
418 /******************************************************************************
419 * OleAdviseHolderImpl_SendOnRename
421 static HRESULT WINAPI OleAdviseHolderImpl_SendOnRename(IOleAdviseHolder *iface, IMoniker *pmk)
423 IEnumSTATDATA *pEnum;
424 HRESULT hr;
426 TRACE("(%p)->(%p)\n", iface, pmk);
428 hr = IOleAdviseHolder_EnumAdvise(iface, &pEnum);
429 if (SUCCEEDED(hr))
431 STATDATA statdata;
432 while (IEnumSTATDATA_Next(pEnum, 1, &statdata, NULL) == S_OK)
434 IAdviseSink_OnRename(statdata.pAdvSink, pmk);
436 IAdviseSink_Release(statdata.pAdvSink);
438 IEnumSTATDATA_Release(pEnum);
441 return hr;
444 /******************************************************************************
445 * OleAdviseHolderImpl_SendOnSave
447 static HRESULT WINAPI OleAdviseHolderImpl_SendOnSave(IOleAdviseHolder *iface)
449 IEnumSTATDATA *pEnum;
450 HRESULT hr;
452 TRACE("(%p)->()\n", iface);
454 hr = IOleAdviseHolder_EnumAdvise(iface, &pEnum);
455 if (SUCCEEDED(hr))
457 STATDATA statdata;
458 while (IEnumSTATDATA_Next(pEnum, 1, &statdata, NULL) == S_OK)
460 IAdviseSink_OnSave(statdata.pAdvSink);
462 IAdviseSink_Release(statdata.pAdvSink);
464 IEnumSTATDATA_Release(pEnum);
467 return hr;
470 /******************************************************************************
471 * OleAdviseHolderImpl_SendOnClose
473 static HRESULT WINAPI OleAdviseHolderImpl_SendOnClose(IOleAdviseHolder *iface)
475 IEnumSTATDATA *pEnum;
476 HRESULT hr;
478 TRACE("(%p)->()\n", iface);
480 hr = IOleAdviseHolder_EnumAdvise(iface, &pEnum);
481 if (SUCCEEDED(hr))
483 STATDATA statdata;
484 while (IEnumSTATDATA_Next(pEnum, 1, &statdata, NULL) == S_OK)
486 IAdviseSink_OnClose(statdata.pAdvSink);
488 IAdviseSink_Release(statdata.pAdvSink);
490 IEnumSTATDATA_Release(pEnum);
493 return hr;
496 /**************************************************************************
497 * OleAdviseHolderImpl_VTable
499 static const IOleAdviseHolderVtbl oahvt =
501 OleAdviseHolderImpl_QueryInterface,
502 OleAdviseHolderImpl_AddRef,
503 OleAdviseHolderImpl_Release,
504 OleAdviseHolderImpl_Advise,
505 OleAdviseHolderImpl_Unadvise,
506 OleAdviseHolderImpl_EnumAdvise,
507 OleAdviseHolderImpl_SendOnRename,
508 OleAdviseHolderImpl_SendOnSave,
509 OleAdviseHolderImpl_SendOnClose
512 /**************************************************************************
513 * OleAdviseHolderImpl_Constructor
516 static IOleAdviseHolder *OleAdviseHolderImpl_Constructor(void)
518 OleAdviseHolderImpl* lpoah;
520 lpoah = HeapAlloc(GetProcessHeap(), 0, sizeof(OleAdviseHolderImpl));
522 lpoah->IOleAdviseHolder_iface.lpVtbl = &oahvt;
523 lpoah->ref = 1;
524 lpoah->max_cons = INITIAL_SINKS;
525 lpoah->connections = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
526 lpoah->max_cons * sizeof(*lpoah->connections));
528 TRACE("returning %p\n", &lpoah->IOleAdviseHolder_iface);
529 return &lpoah->IOleAdviseHolder_iface;
532 /**************************************************************************
533 * DataAdviseHolder Implementation
535 typedef struct
537 IDataAdviseHolder IDataAdviseHolder_iface;
539 LONG ref;
540 DWORD maxCons;
541 STATDATA* connections;
542 DWORD* remote_connections;
543 IDataObject* delegate;
544 } DataAdviseHolder;
546 /* this connection has also has been advised to the delegate data object */
547 #define WINE_ADVF_REMOTE 0x80000000
549 static inline DataAdviseHolder *impl_from_IDataAdviseHolder(IDataAdviseHolder *iface)
551 return CONTAINING_RECORD(iface, DataAdviseHolder, IDataAdviseHolder_iface);
554 /******************************************************************************
555 * DataAdviseHolder_Destructor
557 static void DataAdviseHolder_Destructor(DataAdviseHolder* ptrToDestroy)
559 DWORD index;
560 TRACE("%p\n", ptrToDestroy);
562 for (index = 0; index < ptrToDestroy->maxCons; index++)
564 if (ptrToDestroy->connections[index].pAdvSink != NULL)
566 if (ptrToDestroy->delegate &&
567 (ptrToDestroy->connections[index].advf & WINE_ADVF_REMOTE))
568 IDataObject_DUnadvise(ptrToDestroy->delegate,
569 ptrToDestroy->remote_connections[index]);
571 release_statdata(ptrToDestroy->connections + index);
575 HeapFree(GetProcessHeap(), 0, ptrToDestroy->remote_connections);
576 HeapFree(GetProcessHeap(), 0, ptrToDestroy->connections);
577 HeapFree(GetProcessHeap(), 0, ptrToDestroy);
580 /************************************************************************
581 * DataAdviseHolder_QueryInterface (IUnknown)
583 static HRESULT WINAPI DataAdviseHolder_QueryInterface(IDataAdviseHolder *iface,
584 REFIID riid, void **ppvObject)
586 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
587 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObject);
589 if ( (This==0) || (ppvObject==0) )
590 return E_INVALIDARG;
592 *ppvObject = 0;
594 if ( IsEqualIID(&IID_IUnknown, riid) ||
595 IsEqualIID(&IID_IDataAdviseHolder, riid) )
597 *ppvObject = iface;
600 if ((*ppvObject)==0)
602 return E_NOINTERFACE;
605 IUnknown_AddRef((IUnknown*)*ppvObject);
606 return S_OK;
609 /************************************************************************
610 * DataAdviseHolder_AddRef (IUnknown)
612 static ULONG WINAPI DataAdviseHolder_AddRef(IDataAdviseHolder *iface)
614 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
615 TRACE("(%p) (ref=%d)\n", This, This->ref);
616 return InterlockedIncrement(&This->ref);
619 /************************************************************************
620 * DataAdviseHolder_Release (IUnknown)
622 static ULONG WINAPI DataAdviseHolder_Release(IDataAdviseHolder *iface)
624 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
625 ULONG ref;
626 TRACE("(%p) (ref=%d)\n", This, This->ref);
628 ref = InterlockedDecrement(&This->ref);
629 if (ref==0) DataAdviseHolder_Destructor(This);
631 return ref;
634 /************************************************************************
635 * DataAdviseHolder_Advise
638 static HRESULT WINAPI DataAdviseHolder_Advise(IDataAdviseHolder *iface,
639 IDataObject *pDataObject, FORMATETC *pFetc,
640 DWORD advf, IAdviseSink *pAdvise,
641 DWORD *pdwConnection)
643 DWORD index;
644 STATDATA new_conn;
645 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
647 TRACE("(%p)->(%p, %p, %08x, %p, %p)\n", This, pDataObject, pFetc, advf,
648 pAdvise, pdwConnection);
650 if (pdwConnection==NULL)
651 return E_POINTER;
653 *pdwConnection = 0;
655 for (index = 0; index < This->maxCons; index++)
657 if (This->connections[index].pAdvSink == NULL)
658 break;
661 if (index == This->maxCons)
663 This->maxCons+=INITIAL_SINKS;
664 This->connections = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
665 This->connections,
666 This->maxCons * sizeof(*This->connections));
667 This->remote_connections = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
668 This->remote_connections,
669 This->maxCons * sizeof(*This->remote_connections));
672 new_conn.pAdvSink = pAdvise;
673 new_conn.advf = advf & ~WINE_ADVF_REMOTE;
674 new_conn.formatetc = *pFetc;
675 new_conn.dwConnection = index + 1; /* 0 is not a valid cookie, so increment the index */
677 copy_statdata(This->connections + index, &new_conn);
679 if (This->connections[index].pAdvSink != NULL)
681 /* if we are already connected advise the remote object */
682 if (This->delegate)
684 HRESULT hr;
686 hr = IDataObject_DAdvise(This->delegate, &new_conn.formatetc,
687 new_conn.advf, new_conn.pAdvSink,
688 &This->remote_connections[index]);
689 if (FAILED(hr))
691 IDataAdviseHolder_Unadvise(iface, new_conn.dwConnection);
692 return hr;
694 This->connections[index].advf |= WINE_ADVF_REMOTE;
696 else if(advf & ADVF_PRIMEFIRST)
697 /* only do this if we have no delegate, since in the above case the
698 * delegate will do the priming for us */
699 IDataAdviseHolder_SendOnDataChange(iface, pDataObject, 0, advf);
702 *pdwConnection = new_conn.dwConnection;
704 return S_OK;
707 /******************************************************************************
708 * DataAdviseHolder_Unadvise
710 static HRESULT WINAPI DataAdviseHolder_Unadvise(IDataAdviseHolder *iface,
711 DWORD dwConnection)
713 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
714 DWORD index;
715 TRACE("(%p)->(%u)\n", This, dwConnection);
717 /* The connection number is 1 more than the index, see DataAdviseHolder_Advise */
718 index = dwConnection - 1;
720 if (index >= This->maxCons || This->connections[index].pAdvSink == NULL)
721 return OLE_E_NOCONNECTION;
723 if (This->delegate && This->connections[index].advf & WINE_ADVF_REMOTE)
725 IDataObject_DUnadvise(This->delegate, This->remote_connections[index]);
726 This->remote_connections[index] = 0;
729 release_statdata(This->connections + index);
731 return S_OK;
734 /******************************************************************************
735 * DataAdviseHolder_EnumAdvise
737 static HRESULT WINAPI DataAdviseHolder_EnumAdvise(IDataAdviseHolder *iface,
738 IEnumSTATDATA **enum_advise)
740 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
741 IUnknown *unk;
742 HRESULT hr;
744 TRACE("(%p)->(%p)\n", This, enum_advise);
746 IDataAdviseHolder_QueryInterface(iface, &IID_IUnknown, (void**)&unk);
747 hr = EnumSTATDATA_Construct(unk, 0, This->maxCons, This->connections, TRUE, enum_advise);
748 IUnknown_Release(unk);
749 return hr;
752 /******************************************************************************
753 * DataAdviseHolder_SendOnDataChange
755 static HRESULT WINAPI DataAdviseHolder_SendOnDataChange(IDataAdviseHolder *iface,
756 IDataObject *data_obj,
757 DWORD dwReserved, DWORD advf)
759 IEnumSTATDATA *pEnum;
760 HRESULT hr;
762 TRACE("(%p)->(%p, %08x, %08x)\n", iface, data_obj, dwReserved, advf);
764 hr = IDataAdviseHolder_EnumAdvise(iface, &pEnum);
765 if (SUCCEEDED(hr))
767 STATDATA statdata;
768 while (IEnumSTATDATA_Next(pEnum, 1, &statdata, NULL) == S_OK)
770 STGMEDIUM stg;
771 stg.tymed = TYMED_NULL;
772 stg.u.pstg = NULL;
773 stg.pUnkForRelease = NULL;
775 if(!(statdata.advf & ADVF_NODATA))
777 hr = IDataObject_GetData(data_obj, &statdata.formatetc, &stg);
780 IAdviseSink_OnDataChange(statdata.pAdvSink, &statdata.formatetc, &stg);
782 if(statdata.advf & ADVF_ONLYONCE)
784 IDataAdviseHolder_Unadvise(iface, statdata.dwConnection);
787 release_statdata(&statdata);
789 IEnumSTATDATA_Release(pEnum);
792 return S_OK;
795 /**************************************************************************
796 * DataAdviseHolderImpl_VTable
798 static const IDataAdviseHolderVtbl DataAdviseHolderImpl_VTable =
800 DataAdviseHolder_QueryInterface,
801 DataAdviseHolder_AddRef,
802 DataAdviseHolder_Release,
803 DataAdviseHolder_Advise,
804 DataAdviseHolder_Unadvise,
805 DataAdviseHolder_EnumAdvise,
806 DataAdviseHolder_SendOnDataChange
809 HRESULT DataAdviseHolder_OnConnect(IDataAdviseHolder *iface, IDataObject *pDelegate)
811 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
812 DWORD index;
813 HRESULT hr = S_OK;
815 for(index = 0; index < This->maxCons; index++)
817 if(This->connections[index].pAdvSink != NULL)
819 hr = IDataObject_DAdvise(pDelegate, &This->connections[index].formatetc,
820 This->connections[index].advf,
821 This->connections[index].pAdvSink,
822 &This->remote_connections[index]);
823 if (FAILED(hr)) break;
824 This->connections[index].advf |= WINE_ADVF_REMOTE;
827 This->delegate = pDelegate;
828 return hr;
831 void DataAdviseHolder_OnDisconnect(IDataAdviseHolder *iface)
833 DataAdviseHolder *This = impl_from_IDataAdviseHolder(iface);
834 DWORD index;
836 for(index = 0; index < This->maxCons; index++)
838 if((This->connections[index].pAdvSink != NULL) &&
839 (This->connections[index].advf & WINE_ADVF_REMOTE))
841 IDataObject_DUnadvise(This->delegate, This->remote_connections[index]);
842 This->remote_connections[index] = 0;
843 This->connections[index].advf &= ~WINE_ADVF_REMOTE;
846 This->delegate = NULL;
849 /******************************************************************************
850 * DataAdviseHolder_Constructor
852 static IDataAdviseHolder *DataAdviseHolder_Constructor(void)
854 DataAdviseHolder* newHolder;
856 newHolder = HeapAlloc(GetProcessHeap(), 0, sizeof(DataAdviseHolder));
858 newHolder->IDataAdviseHolder_iface.lpVtbl = &DataAdviseHolderImpl_VTable;
859 newHolder->ref = 1;
860 newHolder->maxCons = INITIAL_SINKS;
861 newHolder->connections = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
862 newHolder->maxCons * sizeof(*newHolder->connections));
863 newHolder->remote_connections = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
864 newHolder->maxCons * sizeof(*newHolder->remote_connections));
865 newHolder->delegate = NULL;
867 TRACE("returning %p\n", &newHolder->IDataAdviseHolder_iface);
868 return &newHolder->IDataAdviseHolder_iface;
871 /***********************************************************************
872 * API functions
875 /***********************************************************************
876 * CreateOleAdviseHolder [OLE32.@]
878 HRESULT WINAPI CreateOleAdviseHolder(IOleAdviseHolder **ppOAHolder)
880 TRACE("(%p)\n", ppOAHolder);
882 if (ppOAHolder==NULL)
883 return E_POINTER;
885 *ppOAHolder = OleAdviseHolderImpl_Constructor ();
887 if (*ppOAHolder != NULL)
888 return S_OK;
890 return E_OUTOFMEMORY;
893 /******************************************************************************
894 * CreateDataAdviseHolder [OLE32.@]
896 HRESULT WINAPI CreateDataAdviseHolder(IDataAdviseHolder **ppDAHolder)
898 TRACE("(%p)\n", ppDAHolder);
900 if (ppDAHolder==NULL)
901 return E_POINTER;
903 *ppDAHolder = DataAdviseHolder_Constructor();
905 if (*ppDAHolder != NULL)
906 return S_OK;
908 return E_OUTOFMEMORY;