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