ole32: Standardize the COM usage in clipboard.c.
[wine] / dlls / ole32 / oleobj.c
1 /*
2  *      OLE2 COM objects
3  *
4  *      Copyright 1998 Eric Kohl
5  *      Copyright 1999 Francis Beaudet
6  *
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.
11  *
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.
16  *
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
20  */
21
22
23 #include <stdarg.h>
24 #include <string.h>
25
26 #define COBJMACROS
27
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winuser.h"
31 #include "winerror.h"
32 #include "wine/debug.h"
33 #include "ole2.h"
34
35 #include "compobj_private.h"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(ole);
38
39 #define INITIAL_SINKS 10
40
41 /**************************************************************************
42  *  OleAdviseHolderImpl Implementation
43  */
44 typedef struct OleAdviseHolderImpl
45 {
46   const IOleAdviseHolderVtbl *lpVtbl;
47
48   LONG ref;
49
50   DWORD         maxSinks;
51   IAdviseSink** arrayOfSinks;
52
53 } OleAdviseHolderImpl;
54
55 static HRESULT EnumOleSTATDATA_Construct(OleAdviseHolderImpl *pOleAdviseHolder, ULONG index, IEnumSTATDATA **ppenum);
56
57 typedef struct
58 {
59     IEnumSTATDATA IEnumSTATDATA_iface;
60     LONG ref;
61
62     ULONG index;
63     OleAdviseHolderImpl *pOleAdviseHolder;
64 } EnumOleSTATDATA;
65
66 static inline EnumOleSTATDATA *impl_from_IEnumSTATDATA(IEnumSTATDATA *iface)
67 {
68     return CONTAINING_RECORD(iface, EnumOleSTATDATA, IEnumSTATDATA_iface);
69 }
70
71 static HRESULT WINAPI EnumOleSTATDATA_QueryInterface(
72     IEnumSTATDATA *iface, REFIID riid, void **ppv)
73 {
74     TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
75     if (IsEqualIID(riid, &IID_IUnknown) ||
76         IsEqualIID(riid, &IID_IEnumSTATDATA))
77     {
78         IUnknown_AddRef(iface);
79         *ppv = iface;
80         return S_OK;
81     }
82     return E_NOINTERFACE;
83 }
84
85 static ULONG WINAPI EnumOleSTATDATA_AddRef(
86     IEnumSTATDATA *iface)
87 {
88     EnumOleSTATDATA *This = impl_from_IEnumSTATDATA(iface);
89     TRACE("()\n");
90     return InterlockedIncrement(&This->ref);
91 }
92
93 static ULONG WINAPI EnumOleSTATDATA_Release(
94     IEnumSTATDATA *iface)
95 {
96     EnumOleSTATDATA *This = impl_from_IEnumSTATDATA(iface);
97     LONG refs = InterlockedDecrement(&This->ref);
98     TRACE("()\n");
99     if (!refs)
100     {
101         IOleAdviseHolder_Release((IOleAdviseHolder *)This->pOleAdviseHolder);
102         HeapFree(GetProcessHeap(), 0, This);
103     }
104     return refs;
105 }
106
107 static HRESULT WINAPI EnumOleSTATDATA_Next(
108     IEnumSTATDATA *iface, ULONG celt, LPSTATDATA rgelt,
109     ULONG *pceltFetched)
110 {
111     EnumOleSTATDATA *This = impl_from_IEnumSTATDATA(iface);
112     HRESULT hr = S_OK;
113
114     TRACE("(%d, %p, %p)\n", celt, rgelt, pceltFetched);
115
116     if (pceltFetched)
117         *pceltFetched = 0;
118
119     for (; celt; celt--, rgelt++)
120     {
121         while ((This->index < This->pOleAdviseHolder->maxSinks) && 
122                !This->pOleAdviseHolder->arrayOfSinks[This->index])
123         {
124             This->index++;
125         }
126         if (This->index >= This->pOleAdviseHolder->maxSinks)
127         {
128             hr = S_FALSE;
129             break;
130         }
131
132         memset(&rgelt->formatetc, 0, sizeof(rgelt->formatetc));
133         rgelt->advf = 0;
134         rgelt->pAdvSink = This->pOleAdviseHolder->arrayOfSinks[This->index];
135         IAdviseSink_AddRef(rgelt->pAdvSink);
136         rgelt->dwConnection = This->index;
137
138         if (pceltFetched)
139             (*pceltFetched)++;
140         This->index++;
141     }
142     return hr;
143 }
144
145 static HRESULT WINAPI EnumOleSTATDATA_Skip(
146     IEnumSTATDATA *iface, ULONG celt)
147 {
148     EnumOleSTATDATA *This = impl_from_IEnumSTATDATA(iface);
149
150     TRACE("(%d)\n", celt);
151
152     for (; celt; celt--)
153     {
154         while ((This->index < This->pOleAdviseHolder->maxSinks) && 
155                !This->pOleAdviseHolder->arrayOfSinks[This->index])
156         {
157             This->index++;
158         }
159         if (This->index >= This->pOleAdviseHolder->maxSinks)
160             return S_FALSE;
161         This->index++;
162     }
163     return S_OK;
164 }
165
166 static HRESULT WINAPI EnumOleSTATDATA_Reset(
167     IEnumSTATDATA *iface)
168 {
169     EnumOleSTATDATA *This = impl_from_IEnumSTATDATA(iface);
170
171     TRACE("()\n");
172
173     This->index = 0;
174     return S_OK;
175 }
176
177 static HRESULT WINAPI EnumOleSTATDATA_Clone(
178     IEnumSTATDATA *iface,
179     IEnumSTATDATA **ppenum)
180 {
181     EnumOleSTATDATA *This = impl_from_IEnumSTATDATA(iface);
182     return EnumOleSTATDATA_Construct(This->pOleAdviseHolder, This->index, ppenum);
183 }
184
185 static const IEnumSTATDATAVtbl EnumOleSTATDATA_VTable =
186 {
187     EnumOleSTATDATA_QueryInterface,
188     EnumOleSTATDATA_AddRef,
189     EnumOleSTATDATA_Release,
190     EnumOleSTATDATA_Next,
191     EnumOleSTATDATA_Skip,
192     EnumOleSTATDATA_Reset,
193     EnumOleSTATDATA_Clone
194 };
195
196 static HRESULT EnumOleSTATDATA_Construct(OleAdviseHolderImpl *pOleAdviseHolder, ULONG index, IEnumSTATDATA **ppenum)
197 {
198     EnumOleSTATDATA *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
199     if (!This)
200         return E_OUTOFMEMORY;
201     This->IEnumSTATDATA_iface.lpVtbl = &EnumOleSTATDATA_VTable;
202     This->ref = 1;
203     This->index = index;
204     This->pOleAdviseHolder = pOleAdviseHolder;
205     IOleAdviseHolder_AddRef((IOleAdviseHolder *)pOleAdviseHolder);
206     *ppenum = &This->IEnumSTATDATA_iface;
207     return S_OK;
208 }
209
210 /**************************************************************************
211  *  OleAdviseHolderImpl_Destructor
212  */
213 static void OleAdviseHolderImpl_Destructor(
214   OleAdviseHolderImpl* ptrToDestroy)
215 {
216   DWORD index;
217   TRACE("%p\n", ptrToDestroy);
218
219   for (index = 0; index < ptrToDestroy->maxSinks; index++)
220   {
221     if (ptrToDestroy->arrayOfSinks[index]!=0)
222     {
223       IAdviseSink_Release(ptrToDestroy->arrayOfSinks[index]);
224       ptrToDestroy->arrayOfSinks[index] = NULL;
225     }
226   }
227
228   HeapFree(GetProcessHeap(),
229            0,
230            ptrToDestroy->arrayOfSinks);
231
232
233   HeapFree(GetProcessHeap(),
234            0,
235            ptrToDestroy);
236 }
237
238 /**************************************************************************
239  *  OleAdviseHolderImpl_QueryInterface
240  */
241 static HRESULT WINAPI OleAdviseHolderImpl_QueryInterface(
242   LPOLEADVISEHOLDER iface,
243   REFIID            riid,
244   LPVOID*           ppvObj)
245 {
246   OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
247   TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObj);
248   /*
249    * Sanity check
250    */
251   if (ppvObj==NULL)
252     return E_POINTER;
253
254   *ppvObj = NULL;
255
256   if (IsEqualIID(riid, &IID_IUnknown))
257   {
258     /* IUnknown */
259     *ppvObj = This;
260   }
261   else if(IsEqualIID(riid, &IID_IOleAdviseHolder))
262   {
263     /* IOleAdviseHolder */
264     *ppvObj = This;
265   }
266
267   if(*ppvObj == NULL)
268     return E_NOINTERFACE;
269
270   /*
271    * A successful QI always increments the reference count.
272    */
273   IUnknown_AddRef((IUnknown*)*ppvObj);
274
275   return S_OK;
276 }
277
278 /******************************************************************************
279  * OleAdviseHolderImpl_AddRef
280  */
281 static ULONG WINAPI OleAdviseHolderImpl_AddRef(
282   LPOLEADVISEHOLDER iface)
283 {
284   OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
285   ULONG ref = InterlockedIncrement(&This->ref);
286
287   TRACE("(%p)->(ref=%d)\n", This, ref - 1);
288
289   return ref;
290 }
291
292 /******************************************************************************
293  * OleAdviseHolderImpl_Release
294  */
295 static ULONG WINAPI OleAdviseHolderImpl_Release(
296   LPOLEADVISEHOLDER iface)
297 {
298   OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
299   ULONG ref;
300   TRACE("(%p)->(ref=%d)\n", This, This->ref);
301   ref = InterlockedDecrement(&This->ref);
302
303   if (ref == 0) OleAdviseHolderImpl_Destructor(This);
304
305   return ref;
306 }
307
308 /******************************************************************************
309  * OleAdviseHolderImpl_Advise
310  */
311 static HRESULT WINAPI OleAdviseHolderImpl_Advise(
312   LPOLEADVISEHOLDER iface,
313   IAdviseSink*      pAdvise,
314   DWORD*            pdwConnection)
315 {
316   DWORD index;
317
318   OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
319
320   TRACE("(%p)->(%p, %p)\n", This, pAdvise, pdwConnection);
321
322   /*
323    * Sanity check
324    */
325   if (pdwConnection==NULL)
326     return E_POINTER;
327
328   *pdwConnection = 0;
329
330   /*
331    * Find a free spot in the array.
332    */
333   for (index = 0; index < This->maxSinks; index++)
334   {
335     if (This->arrayOfSinks[index]==NULL)
336       break;
337   }
338
339   /*
340    * If the array is full, we need to grow it.
341    */
342   if (index == This->maxSinks)
343   {
344     DWORD i;
345
346     This->maxSinks+=INITIAL_SINKS;
347
348     This->arrayOfSinks = HeapReAlloc(GetProcessHeap(),
349                                      0,
350                                      This->arrayOfSinks,
351                                      This->maxSinks*sizeof(IAdviseSink*));
352
353     for (i=index;i < This->maxSinks; i++)
354       This->arrayOfSinks[i]=0;
355   }
356
357   /*
358    * Store the new sink
359    */
360   This->arrayOfSinks[index] = pAdvise;
361
362   if (This->arrayOfSinks[index]!=NULL)
363     IAdviseSink_AddRef(This->arrayOfSinks[index]);
364
365   /*
366    * Return the index as the cookie.
367    * Since 0 is not a valid cookie, we will increment by
368    * 1 the index in the table.
369    */
370   *pdwConnection = index+1;
371
372   return S_OK;
373 }
374
375 /******************************************************************************
376  * OleAdviseHolderImpl_Unadvise
377  */
378 static HRESULT WINAPI OleAdviseHolderImpl_Unadvise(
379   LPOLEADVISEHOLDER iface,
380   DWORD             dwConnection)
381 {
382   OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
383
384   TRACE("(%p)->(%u)\n", This, dwConnection);
385
386   /*
387    * So we don't return 0 as a cookie, the index was
388    * incremented by 1 in OleAdviseHolderImpl_Advise
389    * we have to compensate.
390    */
391   dwConnection--;
392
393   /*
394    * Check for invalid cookies.
395    */
396   if (dwConnection >= This->maxSinks)
397     return OLE_E_NOCONNECTION;
398
399   if (This->arrayOfSinks[dwConnection] == NULL)
400     return OLE_E_NOCONNECTION;
401
402   /*
403    * Release the sink and mark the spot in the list as free.
404    */
405   IAdviseSink_Release(This->arrayOfSinks[dwConnection]);
406   This->arrayOfSinks[dwConnection] = NULL;
407
408   return S_OK;
409 }
410
411 /******************************************************************************
412  * OleAdviseHolderImpl_EnumAdvise
413  */
414 static HRESULT WINAPI
415 OleAdviseHolderImpl_EnumAdvise (LPOLEADVISEHOLDER iface, IEnumSTATDATA **ppenumAdvise)
416 {
417     OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
418
419     TRACE("(%p)->(%p)\n", This, ppenumAdvise);
420
421     *ppenumAdvise = NULL;
422
423     return EnumOleSTATDATA_Construct(This, 0, ppenumAdvise);
424 }
425
426 /******************************************************************************
427  * OleAdviseHolderImpl_SendOnRename
428  */
429 static HRESULT WINAPI
430 OleAdviseHolderImpl_SendOnRename (LPOLEADVISEHOLDER iface, IMoniker *pmk)
431 {
432     IEnumSTATDATA *pEnum;
433     HRESULT hr;
434
435     TRACE("(%p)->(%p)\n", iface, pmk);
436
437     hr = IOleAdviseHolder_EnumAdvise(iface, &pEnum);
438     if (SUCCEEDED(hr))
439     {
440         STATDATA statdata;
441         while (IEnumSTATDATA_Next(pEnum, 1, &statdata, NULL) == S_OK)
442         {
443             IAdviseSink_OnRename(statdata.pAdvSink, pmk);
444
445             IAdviseSink_Release(statdata.pAdvSink);
446         }
447         IEnumSTATDATA_Release(pEnum);
448     }
449
450     return hr;
451 }
452
453 /******************************************************************************
454  * OleAdviseHolderImpl_SendOnSave
455  */
456 static HRESULT WINAPI
457 OleAdviseHolderImpl_SendOnSave (LPOLEADVISEHOLDER iface)
458 {
459     IEnumSTATDATA *pEnum;
460     HRESULT hr;
461
462     TRACE("(%p)->()\n", iface);
463
464     hr = IOleAdviseHolder_EnumAdvise(iface, &pEnum);
465     if (SUCCEEDED(hr))
466     {
467         STATDATA statdata;
468         while (IEnumSTATDATA_Next(pEnum, 1, &statdata, NULL) == S_OK)
469         {
470             IAdviseSink_OnSave(statdata.pAdvSink);
471
472             IAdviseSink_Release(statdata.pAdvSink);
473         }
474         IEnumSTATDATA_Release(pEnum);
475     }
476
477     return hr;
478 }
479
480 /******************************************************************************
481  * OleAdviseHolderImpl_SendOnClose
482  */
483 static HRESULT WINAPI
484 OleAdviseHolderImpl_SendOnClose (LPOLEADVISEHOLDER iface)
485 {
486     IEnumSTATDATA *pEnum;
487     HRESULT hr;
488
489     TRACE("(%p)->()\n", iface);
490
491     hr = IOleAdviseHolder_EnumAdvise(iface, &pEnum);
492     if (SUCCEEDED(hr))
493     {
494         STATDATA statdata;
495         while (IEnumSTATDATA_Next(pEnum, 1, &statdata, NULL) == S_OK)
496         {
497             IAdviseSink_OnClose(statdata.pAdvSink);
498
499             IAdviseSink_Release(statdata.pAdvSink);
500         }
501         IEnumSTATDATA_Release(pEnum);
502     }
503
504     return hr;
505 }
506
507 /**************************************************************************
508  *  OleAdviseHolderImpl_VTable
509  */
510 static const IOleAdviseHolderVtbl oahvt =
511 {
512     OleAdviseHolderImpl_QueryInterface,
513     OleAdviseHolderImpl_AddRef,
514     OleAdviseHolderImpl_Release,
515     OleAdviseHolderImpl_Advise,
516     OleAdviseHolderImpl_Unadvise,
517     OleAdviseHolderImpl_EnumAdvise,
518     OleAdviseHolderImpl_SendOnRename,
519     OleAdviseHolderImpl_SendOnSave,
520     OleAdviseHolderImpl_SendOnClose
521 };
522
523 /**************************************************************************
524  *  OleAdviseHolderImpl_Constructor
525  */
526
527 static LPOLEADVISEHOLDER OleAdviseHolderImpl_Constructor(void)
528 {
529   OleAdviseHolderImpl* lpoah;
530   DWORD                index;
531
532   lpoah = HeapAlloc(GetProcessHeap(), 0, sizeof(OleAdviseHolderImpl));
533
534   lpoah->lpVtbl = &oahvt;
535   lpoah->ref = 1;
536   lpoah->maxSinks = INITIAL_SINKS;
537   lpoah->arrayOfSinks = HeapAlloc(GetProcessHeap(),
538                                   0,
539                                   lpoah->maxSinks * sizeof(IAdviseSink*));
540
541   for (index = 0; index < lpoah->maxSinks; index++)
542     lpoah->arrayOfSinks[index]=0;
543
544   TRACE("returning %p\n", lpoah);
545   return (LPOLEADVISEHOLDER)lpoah;
546 }
547
548 /**************************************************************************
549  *  DataAdviseHolder Implementation
550  */
551 typedef struct DataAdviseConnection {
552   IAdviseSink *sink;
553   FORMATETC fmat;
554   DWORD advf;
555   DWORD remote_connection;
556 } DataAdviseConnection;
557
558 typedef struct DataAdviseHolder
559 {
560   const IDataAdviseHolderVtbl *lpVtbl;
561
562   LONG                  ref;
563   DWORD                 maxCons;
564   DataAdviseConnection* Connections;
565   IDataObject*          delegate;
566 } DataAdviseHolder;
567
568 /* this connection has also has been advised to the delegate data object */
569 #define WINE_ADVF_REMOTE 0x80000000
570
571 /******************************************************************************
572  * DataAdviseHolder_Destructor
573  */
574 static void DataAdviseHolder_Destructor(DataAdviseHolder* ptrToDestroy)
575 {
576   DWORD index;
577   TRACE("%p\n", ptrToDestroy);
578
579   for (index = 0; index < ptrToDestroy->maxCons; index++)
580   {
581     if (ptrToDestroy->Connections[index].sink != NULL)
582     {
583       if (ptrToDestroy->delegate && 
584           (ptrToDestroy->Connections[index].advf & WINE_ADVF_REMOTE))
585         IDataObject_DUnadvise(ptrToDestroy->delegate,
586           ptrToDestroy->Connections[index].remote_connection);
587
588       IAdviseSink_Release(ptrToDestroy->Connections[index].sink);
589       ptrToDestroy->Connections[index].sink = NULL;
590     }
591   }
592
593   HeapFree(GetProcessHeap(), 0, ptrToDestroy->Connections);
594   HeapFree(GetProcessHeap(), 0, ptrToDestroy);
595 }
596
597 /************************************************************************
598  * DataAdviseHolder_QueryInterface (IUnknown)
599  *
600  * See Windows documentation for more details on IUnknown methods.
601  */
602 static HRESULT WINAPI DataAdviseHolder_QueryInterface(
603   IDataAdviseHolder*      iface,
604   REFIID                  riid,
605   void**                  ppvObject)
606 {
607   DataAdviseHolder *This = (DataAdviseHolder *)iface;
608   TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObject);
609   /*
610    * Perform a sanity check on the parameters.
611    */
612   if ( (This==0) || (ppvObject==0) )
613     return E_INVALIDARG;
614
615   /*
616    * Initialize the return parameter.
617    */
618   *ppvObject = 0;
619
620   /*
621    * Compare the riid with the interface IDs implemented by this object.
622    */
623   if ( IsEqualIID(&IID_IUnknown, riid) ||
624        IsEqualIID(&IID_IDataAdviseHolder, riid)  )
625   {
626     *ppvObject = iface;
627   }
628
629   /*
630    * Check that we obtained an interface.
631    */
632   if ((*ppvObject)==0)
633   {
634     return E_NOINTERFACE;
635   }
636
637   /*
638    * Query Interface always increases the reference count by one when it is
639    * successful.
640    */
641   IUnknown_AddRef((IUnknown*)*ppvObject);
642
643   return S_OK;
644 }
645
646 /************************************************************************
647  * DataAdviseHolder_AddRef (IUnknown)
648  *
649  * See Windows documentation for more details on IUnknown methods.
650  */
651 static ULONG WINAPI       DataAdviseHolder_AddRef(
652   IDataAdviseHolder*      iface)
653 {
654   DataAdviseHolder *This = (DataAdviseHolder *)iface;
655   TRACE("(%p) (ref=%d)\n", This, This->ref);
656   return InterlockedIncrement(&This->ref);
657 }
658
659 /************************************************************************
660  * DataAdviseHolder_Release (IUnknown)
661  *
662  * See Windows documentation for more details on IUnknown methods.
663  */
664 static ULONG WINAPI DataAdviseHolder_Release(
665   IDataAdviseHolder*      iface)
666 {
667   DataAdviseHolder *This = (DataAdviseHolder *)iface;
668   ULONG ref;
669   TRACE("(%p) (ref=%d)\n", This, This->ref);
670
671   /*
672    * Decrease the reference count on this object.
673    */
674   ref = InterlockedDecrement(&This->ref);
675
676   /*
677    * If the reference count goes down to 0, perform suicide.
678    */
679   if (ref==0) DataAdviseHolder_Destructor(This);
680
681   return ref;
682 }
683
684 /************************************************************************
685  * DataAdviseHolder_Advise
686  *
687  */
688 static HRESULT WINAPI DataAdviseHolder_Advise(
689   IDataAdviseHolder*      iface,
690   IDataObject*            pDataObject,
691   FORMATETC*              pFetc,
692   DWORD                   advf,
693   IAdviseSink*            pAdvise,
694   DWORD*                  pdwConnection)
695 {
696   DWORD index;
697
698   DataAdviseHolder *This = (DataAdviseHolder *)iface;
699
700   TRACE("(%p)->(%p, %p, %08x, %p, %p)\n", This, pDataObject, pFetc, advf,
701         pAdvise, pdwConnection);
702   /*
703    * Sanity check
704    */
705   if (pdwConnection==NULL)
706     return E_POINTER;
707
708   *pdwConnection = 0;
709
710   /*
711    * Find a free spot in the array.
712    */
713   for (index = 0; index < This->maxCons; index++)
714   {
715     if (This->Connections[index].sink == NULL)
716       break;
717   }
718
719   /*
720    * If the array is full, we need to grow it.
721    */
722   if (index == This->maxCons)
723   {
724     This->maxCons+=INITIAL_SINKS;
725     This->Connections = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
726                                     This->Connections,
727                                     This->maxCons*sizeof(DataAdviseConnection));
728   }
729   /*
730    * Store the new sink
731    */
732   This->Connections[index].sink = pAdvise;
733   This->Connections[index].advf = advf & ~WINE_ADVF_REMOTE;
734   This->Connections[index].fmat = *pFetc;
735   if (pFetc->ptd)
736   {
737     This->Connections[index].fmat.ptd = CoTaskMemAlloc(pFetc->ptd->tdSize);
738     if (!This->Connections[index].fmat.ptd)
739     {
740       IDataAdviseHolder_Unadvise(iface, index + 1);
741       return E_OUTOFMEMORY;
742     }
743     memcpy(This->Connections[index].fmat.ptd, pFetc->ptd, pFetc->ptd->tdSize);
744   }
745
746   if (This->Connections[index].sink != NULL) {
747     IAdviseSink_AddRef(This->Connections[index].sink);
748
749     /* if we are already connected advise the remote object */
750     if (This->delegate)
751     {
752         HRESULT hr;
753
754         hr = IDataObject_DAdvise(This->delegate, &This->Connections[index].fmat,
755                                  This->Connections[index].advf,
756                                  This->Connections[index].sink,
757                                  &This->Connections[index].remote_connection);
758         if (FAILED(hr))
759         {
760             IDataAdviseHolder_Unadvise(iface, index + 1);
761             return hr;
762         }
763         This->Connections[index].advf |= WINE_ADVF_REMOTE;
764     }
765     else if(advf & ADVF_PRIMEFIRST)
766       /* only do this if we have no delegate, since in the above case the
767        * delegate will do the priming for us */
768       IDataAdviseHolder_SendOnDataChange(iface, pDataObject, 0, advf);
769   }
770   /*
771    * Return the index as the cookie.
772    * Since 0 is not a valid cookie, we will increment by
773    * 1 the index in the table.
774    */
775   *pdwConnection = index+1;
776
777   return S_OK;
778 }
779
780 /******************************************************************************
781  * DataAdviseHolder_Unadvise
782  */
783 static HRESULT WINAPI     DataAdviseHolder_Unadvise(
784   IDataAdviseHolder*      iface,
785   DWORD                   dwConnection)
786 {
787   DataAdviseHolder *This = (DataAdviseHolder *)iface;
788
789   TRACE("(%p)->(%u)\n", This, dwConnection);
790
791   /*
792    * So we don't return 0 as a cookie, the index was
793    * incremented by 1 in OleAdviseHolderImpl_Advise
794    * we have to compensate.
795    */
796   dwConnection--;
797
798   /*
799    * Check for invalid cookies.
800    */
801   if (dwConnection >= This->maxCons)
802     return OLE_E_NOCONNECTION;
803
804   if (This->Connections[dwConnection].sink == NULL)
805     return OLE_E_NOCONNECTION;
806
807   if (This->delegate && This->Connections[dwConnection].advf & WINE_ADVF_REMOTE)
808     IDataObject_DUnadvise(This->delegate,
809       This->Connections[dwConnection].remote_connection);
810
811   /*
812    * Release the sink and mark the spot in the list as free.
813    */
814   IAdviseSink_Release(This->Connections[dwConnection].sink);
815   memset(&(This->Connections[dwConnection]), 0, sizeof(DataAdviseConnection));
816
817   return S_OK;
818 }
819
820 static HRESULT WINAPI     DataAdviseHolder_EnumAdvise(
821   IDataAdviseHolder*      iface,
822   IEnumSTATDATA**         ppenumAdvise)
823 {
824   DataAdviseHolder *This = (DataAdviseHolder *)iface;
825
826   FIXME("(%p)->(%p)\n", This, ppenumAdvise);
827   return E_NOTIMPL;
828 }
829
830 /******************************************************************************
831  * DataAdviseHolder_SendOnDataChange
832  */
833 static HRESULT WINAPI     DataAdviseHolder_SendOnDataChange(
834   IDataAdviseHolder*      iface,
835   IDataObject*            pDataObject,
836   DWORD                   dwReserved,
837   DWORD                   advf)
838 {
839   DataAdviseHolder *This = (DataAdviseHolder *)iface;
840   DWORD index;
841   STGMEDIUM stg;
842   HRESULT res;
843
844   TRACE("(%p)->(%p,%08x,%08x)\n", This, pDataObject, dwReserved, advf);
845
846   for(index = 0; index < This->maxCons; index++) {
847     if(This->Connections[index].sink != NULL) {
848       memset(&stg, 0, sizeof(stg));
849       if(!(This->Connections[index].advf & ADVF_NODATA)) {
850         TRACE("Calling IDataObject_GetData\n");
851         res = IDataObject_GetData(pDataObject,
852                                   &(This->Connections[index].fmat),
853                                   &stg);
854         TRACE("returns %08x\n", res);
855       }
856       TRACE("Calling IAdviseSink_OnDataChange\n");
857       IAdviseSink_OnDataChange(This->Connections[index].sink,
858                                      &(This->Connections[index].fmat),
859                                      &stg);
860       TRACE("Done IAdviseSink_OnDataChange\n");
861       if(This->Connections[index].advf & ADVF_ONLYONCE) {
862         TRACE("Removing connection\n");
863         DataAdviseHolder_Unadvise(iface, index+1);
864       }
865     }
866   }
867   return S_OK;
868 }
869
870 /**************************************************************************
871  *  DataAdviseHolderImpl_VTable
872  */
873 static const IDataAdviseHolderVtbl DataAdviseHolderImpl_VTable =
874 {
875   DataAdviseHolder_QueryInterface,
876   DataAdviseHolder_AddRef,
877   DataAdviseHolder_Release,
878   DataAdviseHolder_Advise,
879   DataAdviseHolder_Unadvise,
880   DataAdviseHolder_EnumAdvise,
881   DataAdviseHolder_SendOnDataChange
882 };
883
884 HRESULT DataAdviseHolder_OnConnect(IDataAdviseHolder *iface, IDataObject *pDelegate)
885 {
886   DataAdviseHolder *This = (DataAdviseHolder *)iface;
887   DWORD index;
888   HRESULT hr = S_OK;
889
890   for(index = 0; index < This->maxCons; index++)
891   {
892     if(This->Connections[index].sink != NULL)
893     {
894       hr = IDataObject_DAdvise(pDelegate, &This->Connections[index].fmat,
895                                This->Connections[index].advf,
896                                This->Connections[index].sink,
897                                &This->Connections[index].remote_connection);
898       if (FAILED(hr)) break;
899       This->Connections[index].advf |= WINE_ADVF_REMOTE;
900     }
901   }
902   This->delegate = pDelegate;
903   return hr;
904 }
905
906 void DataAdviseHolder_OnDisconnect(IDataAdviseHolder *iface)
907 {
908   DataAdviseHolder *This = (DataAdviseHolder *)iface;
909   DWORD index;
910
911   for(index = 0; index < This->maxCons; index++)
912   {
913     if((This->Connections[index].sink != NULL) &&
914        (This->Connections[index].advf & WINE_ADVF_REMOTE))
915     {
916       IDataObject_DUnadvise(This->delegate,
917         This->Connections[index].remote_connection);
918       This->Connections[index].advf &= ~WINE_ADVF_REMOTE;
919     }
920   }
921   This->delegate = NULL;
922 }
923
924 /******************************************************************************
925  * DataAdviseHolder_Constructor
926  */
927 static IDataAdviseHolder* DataAdviseHolder_Constructor(void)
928 {
929   DataAdviseHolder* newHolder;
930
931   newHolder = HeapAlloc(GetProcessHeap(), 0, sizeof(DataAdviseHolder));
932
933   newHolder->lpVtbl = &DataAdviseHolderImpl_VTable;
934   newHolder->ref = 1;
935   newHolder->maxCons = INITIAL_SINKS;
936   newHolder->Connections = HeapAlloc(GetProcessHeap(),
937                                      HEAP_ZERO_MEMORY,
938                                      newHolder->maxCons *
939                                      sizeof(DataAdviseConnection));
940   newHolder->delegate = NULL;
941
942   TRACE("returning %p\n", newHolder);
943   return (IDataAdviseHolder*)newHolder;
944 }
945
946 /***********************************************************************
947  * API functions
948  */
949
950 /***********************************************************************
951  * CreateOleAdviseHolder [OLE32.@]
952  */
953 HRESULT WINAPI CreateOleAdviseHolder(
954   LPOLEADVISEHOLDER *ppOAHolder)
955 {
956   TRACE("(%p)\n", ppOAHolder);
957
958   /*
959    * Sanity check,
960    */
961   if (ppOAHolder==NULL)
962     return E_POINTER;
963
964   *ppOAHolder = OleAdviseHolderImpl_Constructor ();
965
966   if (*ppOAHolder != NULL)
967     return S_OK;
968
969   return E_OUTOFMEMORY;
970 }
971
972 /******************************************************************************
973  *              CreateDataAdviseHolder        [OLE32.@]
974  */
975 HRESULT WINAPI CreateDataAdviseHolder(
976   LPDATAADVISEHOLDER* ppDAHolder)
977 {
978   TRACE("(%p)\n", ppDAHolder);
979
980   /*
981    * Sanity check,
982    */
983   if (ppDAHolder==NULL)
984     return E_POINTER;
985
986   *ppDAHolder = DataAdviseHolder_Constructor();
987
988   if (*ppDAHolder != NULL)
989     return S_OK;
990
991   return E_OUTOFMEMORY;
992 }