Release 1.1.37.
[wine/gsoc-2012-control.git] / dlls / ole32 / oleobj.c
blob584e796bf45f68242d7c2ee379143d17aaa8e2be
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
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"
35 #include "compobj_private.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(ole);
39 #define INITIAL_SINKS 10
41 /**************************************************************************
42 * OleAdviseHolderImpl Implementation
44 typedef struct OleAdviseHolderImpl
46 const IOleAdviseHolderVtbl *lpVtbl;
48 LONG ref;
50 DWORD maxSinks;
51 IAdviseSink** arrayOfSinks;
53 } OleAdviseHolderImpl;
55 static HRESULT EnumOleSTATDATA_Construct(OleAdviseHolderImpl *pOleAdviseHolder, ULONG index, IEnumSTATDATA **ppenum);
57 typedef struct
59 const IEnumSTATDATAVtbl *lpvtbl;
60 LONG ref;
62 ULONG index;
63 OleAdviseHolderImpl *pOleAdviseHolder;
64 } EnumOleSTATDATA;
66 static HRESULT WINAPI EnumOleSTATDATA_QueryInterface(
67 IEnumSTATDATA *iface, REFIID riid, void **ppv)
69 TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
70 if (IsEqualIID(riid, &IID_IUnknown) ||
71 IsEqualIID(riid, &IID_IEnumSTATDATA))
73 IUnknown_AddRef(iface);
74 *ppv = iface;
75 return S_OK;
77 return E_NOINTERFACE;
80 static ULONG WINAPI EnumOleSTATDATA_AddRef(
81 IEnumSTATDATA *iface)
83 EnumOleSTATDATA *This = (EnumOleSTATDATA *)iface;
84 TRACE("()\n");
85 return InterlockedIncrement(&This->ref);
88 static ULONG WINAPI EnumOleSTATDATA_Release(
89 IEnumSTATDATA *iface)
91 EnumOleSTATDATA *This = (EnumOleSTATDATA *)iface;
92 LONG refs = InterlockedDecrement(&This->ref);
93 TRACE("()\n");
94 if (!refs)
96 IOleAdviseHolder_Release((IOleAdviseHolder *)This->pOleAdviseHolder);
97 HeapFree(GetProcessHeap(), 0, This);
99 return refs;
102 static HRESULT WINAPI EnumOleSTATDATA_Next(
103 IEnumSTATDATA *iface, ULONG celt, LPSTATDATA rgelt,
104 ULONG *pceltFetched)
106 EnumOleSTATDATA *This = (EnumOleSTATDATA *)iface;
107 HRESULT hr = S_OK;
109 TRACE("(%d, %p, %p)\n", celt, rgelt, pceltFetched);
111 if (pceltFetched)
112 *pceltFetched = 0;
114 for (; celt; celt--, rgelt++)
116 while ((This->index < This->pOleAdviseHolder->maxSinks) &&
117 !This->pOleAdviseHolder->arrayOfSinks[This->index])
119 This->index++;
121 if (This->index >= This->pOleAdviseHolder->maxSinks)
123 hr = S_FALSE;
124 break;
127 memset(&rgelt->formatetc, 0, sizeof(rgelt->formatetc));
128 rgelt->advf = 0;
129 rgelt->pAdvSink = This->pOleAdviseHolder->arrayOfSinks[This->index];
130 IAdviseSink_AddRef(rgelt->pAdvSink);
131 rgelt->dwConnection = This->index;
133 if (pceltFetched)
134 (*pceltFetched)++;
135 This->index++;
137 return hr;
140 static HRESULT WINAPI EnumOleSTATDATA_Skip(
141 IEnumSTATDATA *iface, ULONG celt)
143 EnumOleSTATDATA *This = (EnumOleSTATDATA *)iface;
145 TRACE("(%d)\n", celt);
147 for (; celt; celt--)
149 while ((This->index < This->pOleAdviseHolder->maxSinks) &&
150 !This->pOleAdviseHolder->arrayOfSinks[This->index])
152 This->index++;
154 if (This->index >= This->pOleAdviseHolder->maxSinks)
155 return S_FALSE;
156 This->index++;
158 return S_OK;
161 static HRESULT WINAPI EnumOleSTATDATA_Reset(
162 IEnumSTATDATA *iface)
164 EnumOleSTATDATA *This = (EnumOleSTATDATA *)iface;
166 TRACE("()\n");
168 This->index = 0;
169 return S_OK;
172 static HRESULT WINAPI EnumOleSTATDATA_Clone(
173 IEnumSTATDATA *iface,
174 IEnumSTATDATA **ppenum)
176 EnumOleSTATDATA *This = (EnumOleSTATDATA *)iface;
177 return EnumOleSTATDATA_Construct(This->pOleAdviseHolder, This->index, ppenum);
180 static const IEnumSTATDATAVtbl EnumOleSTATDATA_VTable =
182 EnumOleSTATDATA_QueryInterface,
183 EnumOleSTATDATA_AddRef,
184 EnumOleSTATDATA_Release,
185 EnumOleSTATDATA_Next,
186 EnumOleSTATDATA_Skip,
187 EnumOleSTATDATA_Reset,
188 EnumOleSTATDATA_Clone
191 static HRESULT EnumOleSTATDATA_Construct(OleAdviseHolderImpl *pOleAdviseHolder, ULONG index, IEnumSTATDATA **ppenum)
193 EnumOleSTATDATA *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
194 if (!This)
195 return E_OUTOFMEMORY;
196 This->lpvtbl = &EnumOleSTATDATA_VTable;
197 This->ref = 1;
198 This->index = index;
199 This->pOleAdviseHolder = pOleAdviseHolder;
200 IOleAdviseHolder_AddRef((IOleAdviseHolder *)pOleAdviseHolder);
201 *ppenum = (IEnumSTATDATA *)&This->lpvtbl;
202 return S_OK;
205 /**************************************************************************
206 * OleAdviseHolderImpl_Destructor
208 static void OleAdviseHolderImpl_Destructor(
209 OleAdviseHolderImpl* ptrToDestroy)
211 DWORD index;
212 TRACE("%p\n", ptrToDestroy);
214 for (index = 0; index < ptrToDestroy->maxSinks; index++)
216 if (ptrToDestroy->arrayOfSinks[index]!=0)
218 IAdviseSink_Release(ptrToDestroy->arrayOfSinks[index]);
219 ptrToDestroy->arrayOfSinks[index] = NULL;
223 HeapFree(GetProcessHeap(),
225 ptrToDestroy->arrayOfSinks);
228 HeapFree(GetProcessHeap(),
230 ptrToDestroy);
233 /**************************************************************************
234 * OleAdviseHolderImpl_QueryInterface
236 static HRESULT WINAPI OleAdviseHolderImpl_QueryInterface(
237 LPOLEADVISEHOLDER iface,
238 REFIID riid,
239 LPVOID* ppvObj)
241 OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
242 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObj);
244 * Sanity check
246 if (ppvObj==NULL)
247 return E_POINTER;
249 *ppvObj = NULL;
251 if (IsEqualIID(riid, &IID_IUnknown))
253 /* IUnknown */
254 *ppvObj = This;
256 else if(IsEqualIID(riid, &IID_IOleAdviseHolder))
258 /* IOleAdviseHolder */
259 *ppvObj = This;
262 if(*ppvObj == NULL)
263 return E_NOINTERFACE;
266 * A successful QI always increments the reference count.
268 IUnknown_AddRef((IUnknown*)*ppvObj);
270 return S_OK;
273 /******************************************************************************
274 * OleAdviseHolderImpl_AddRef
276 static ULONG WINAPI OleAdviseHolderImpl_AddRef(
277 LPOLEADVISEHOLDER iface)
279 OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
280 ULONG ref = InterlockedIncrement(&This->ref);
282 TRACE("(%p)->(ref=%d)\n", This, ref - 1);
284 return ref;
287 /******************************************************************************
288 * OleAdviseHolderImpl_Release
290 static ULONG WINAPI OleAdviseHolderImpl_Release(
291 LPOLEADVISEHOLDER iface)
293 OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
294 ULONG ref;
295 TRACE("(%p)->(ref=%d)\n", This, This->ref);
296 ref = InterlockedDecrement(&This->ref);
298 if (ref == 0) OleAdviseHolderImpl_Destructor(This);
300 return ref;
303 /******************************************************************************
304 * OleAdviseHolderImpl_Advise
306 static HRESULT WINAPI OleAdviseHolderImpl_Advise(
307 LPOLEADVISEHOLDER iface,
308 IAdviseSink* pAdvise,
309 DWORD* pdwConnection)
311 DWORD index;
313 OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
315 TRACE("(%p)->(%p, %p)\n", This, pAdvise, pdwConnection);
318 * Sanity check
320 if (pdwConnection==NULL)
321 return E_POINTER;
323 *pdwConnection = 0;
326 * Find a free spot in the array.
328 for (index = 0; index < This->maxSinks; index++)
330 if (This->arrayOfSinks[index]==NULL)
331 break;
335 * If the array is full, we need to grow it.
337 if (index == This->maxSinks)
339 DWORD i;
341 This->maxSinks+=INITIAL_SINKS;
343 This->arrayOfSinks = HeapReAlloc(GetProcessHeap(),
345 This->arrayOfSinks,
346 This->maxSinks*sizeof(IAdviseSink*));
348 for (i=index;i < This->maxSinks; i++)
349 This->arrayOfSinks[i]=0;
353 * Store the new sink
355 This->arrayOfSinks[index] = pAdvise;
357 if (This->arrayOfSinks[index]!=NULL)
358 IAdviseSink_AddRef(This->arrayOfSinks[index]);
361 * Return the index as the cookie.
362 * Since 0 is not a valid cookie, we will increment by
363 * 1 the index in the table.
365 *pdwConnection = index+1;
367 return S_OK;
370 /******************************************************************************
371 * OleAdviseHolderImpl_Unadvise
373 static HRESULT WINAPI OleAdviseHolderImpl_Unadvise(
374 LPOLEADVISEHOLDER iface,
375 DWORD dwConnection)
377 OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
379 TRACE("(%p)->(%u)\n", This, dwConnection);
382 * So we don't return 0 as a cookie, the index was
383 * incremented by 1 in OleAdviseHolderImpl_Advise
384 * we have to compensate.
386 dwConnection--;
389 * Check for invalid cookies.
391 if (dwConnection >= This->maxSinks)
392 return OLE_E_NOCONNECTION;
394 if (This->arrayOfSinks[dwConnection] == NULL)
395 return OLE_E_NOCONNECTION;
398 * Release the sink and mark the spot in the list as free.
400 IAdviseSink_Release(This->arrayOfSinks[dwConnection]);
401 This->arrayOfSinks[dwConnection] = NULL;
403 return S_OK;
406 /******************************************************************************
407 * OleAdviseHolderImpl_EnumAdvise
409 static HRESULT WINAPI
410 OleAdviseHolderImpl_EnumAdvise (LPOLEADVISEHOLDER iface, IEnumSTATDATA **ppenumAdvise)
412 OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
414 TRACE("(%p)->(%p)\n", This, ppenumAdvise);
416 *ppenumAdvise = NULL;
418 return EnumOleSTATDATA_Construct(This, 0, ppenumAdvise);
421 /******************************************************************************
422 * OleAdviseHolderImpl_SendOnRename
424 static HRESULT WINAPI
425 OleAdviseHolderImpl_SendOnRename (LPOLEADVISEHOLDER iface, IMoniker *pmk)
427 IEnumSTATDATA *pEnum;
428 HRESULT hr;
430 TRACE("(%p)->(%p)\n", iface, pmk);
432 hr = IOleAdviseHolder_EnumAdvise(iface, &pEnum);
433 if (SUCCEEDED(hr))
435 STATDATA statdata;
436 while (IEnumSTATDATA_Next(pEnum, 1, &statdata, NULL) == S_OK)
438 IAdviseSink_OnRename(statdata.pAdvSink, pmk);
440 IAdviseSink_Release(statdata.pAdvSink);
442 IEnumSTATDATA_Release(pEnum);
445 return hr;
448 /******************************************************************************
449 * OleAdviseHolderImpl_SendOnSave
451 static HRESULT WINAPI
452 OleAdviseHolderImpl_SendOnSave (LPOLEADVISEHOLDER iface)
454 IEnumSTATDATA *pEnum;
455 HRESULT hr;
457 TRACE("(%p)->()\n", iface);
459 hr = IOleAdviseHolder_EnumAdvise(iface, &pEnum);
460 if (SUCCEEDED(hr))
462 STATDATA statdata;
463 while (IEnumSTATDATA_Next(pEnum, 1, &statdata, NULL) == S_OK)
465 IAdviseSink_OnSave(statdata.pAdvSink);
467 IAdviseSink_Release(statdata.pAdvSink);
469 IEnumSTATDATA_Release(pEnum);
472 return hr;
475 /******************************************************************************
476 * OleAdviseHolderImpl_SendOnClose
478 static HRESULT WINAPI
479 OleAdviseHolderImpl_SendOnClose (LPOLEADVISEHOLDER iface)
481 IEnumSTATDATA *pEnum;
482 HRESULT hr;
484 TRACE("(%p)->()\n", iface);
486 hr = IOleAdviseHolder_EnumAdvise(iface, &pEnum);
487 if (SUCCEEDED(hr))
489 STATDATA statdata;
490 while (IEnumSTATDATA_Next(pEnum, 1, &statdata, NULL) == S_OK)
492 IAdviseSink_OnClose(statdata.pAdvSink);
494 IAdviseSink_Release(statdata.pAdvSink);
496 IEnumSTATDATA_Release(pEnum);
499 return hr;
502 /**************************************************************************
503 * OleAdviseHolderImpl_VTable
505 static const IOleAdviseHolderVtbl oahvt =
507 OleAdviseHolderImpl_QueryInterface,
508 OleAdviseHolderImpl_AddRef,
509 OleAdviseHolderImpl_Release,
510 OleAdviseHolderImpl_Advise,
511 OleAdviseHolderImpl_Unadvise,
512 OleAdviseHolderImpl_EnumAdvise,
513 OleAdviseHolderImpl_SendOnRename,
514 OleAdviseHolderImpl_SendOnSave,
515 OleAdviseHolderImpl_SendOnClose
518 /**************************************************************************
519 * OleAdviseHolderImpl_Constructor
522 static LPOLEADVISEHOLDER OleAdviseHolderImpl_Constructor(void)
524 OleAdviseHolderImpl* lpoah;
525 DWORD index;
527 lpoah = HeapAlloc(GetProcessHeap(), 0, sizeof(OleAdviseHolderImpl));
529 lpoah->lpVtbl = &oahvt;
530 lpoah->ref = 1;
531 lpoah->maxSinks = INITIAL_SINKS;
532 lpoah->arrayOfSinks = HeapAlloc(GetProcessHeap(),
534 lpoah->maxSinks * sizeof(IAdviseSink*));
536 for (index = 0; index < lpoah->maxSinks; index++)
537 lpoah->arrayOfSinks[index]=0;
539 TRACE("returning %p\n", lpoah);
540 return (LPOLEADVISEHOLDER)lpoah;
543 /**************************************************************************
544 * DataAdviseHolder Implementation
546 typedef struct DataAdviseConnection {
547 IAdviseSink *sink;
548 FORMATETC fmat;
549 DWORD advf;
550 DWORD remote_connection;
551 } DataAdviseConnection;
553 typedef struct DataAdviseHolder
555 const IDataAdviseHolderVtbl *lpVtbl;
557 LONG ref;
558 DWORD maxCons;
559 DataAdviseConnection* Connections;
560 IDataObject* delegate;
561 } DataAdviseHolder;
563 /* this connection has also has been advised to the delegate data object */
564 #define WINE_ADVF_REMOTE 0x80000000
566 /******************************************************************************
567 * DataAdviseHolder_Destructor
569 static void DataAdviseHolder_Destructor(DataAdviseHolder* ptrToDestroy)
571 DWORD index;
572 TRACE("%p\n", ptrToDestroy);
574 for (index = 0; index < ptrToDestroy->maxCons; index++)
576 if (ptrToDestroy->Connections[index].sink != NULL)
578 if (ptrToDestroy->delegate &&
579 (ptrToDestroy->Connections[index].advf & WINE_ADVF_REMOTE))
580 IDataObject_DUnadvise(ptrToDestroy->delegate,
581 ptrToDestroy->Connections[index].remote_connection);
583 IAdviseSink_Release(ptrToDestroy->Connections[index].sink);
584 ptrToDestroy->Connections[index].sink = NULL;
588 HeapFree(GetProcessHeap(), 0, ptrToDestroy->Connections);
589 HeapFree(GetProcessHeap(), 0, ptrToDestroy);
592 /************************************************************************
593 * DataAdviseHolder_QueryInterface (IUnknown)
595 * See Windows documentation for more details on IUnknown methods.
597 static HRESULT WINAPI DataAdviseHolder_QueryInterface(
598 IDataAdviseHolder* iface,
599 REFIID riid,
600 void** ppvObject)
602 DataAdviseHolder *This = (DataAdviseHolder *)iface;
603 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObject);
605 * Perform a sanity check on the parameters.
607 if ( (This==0) || (ppvObject==0) )
608 return E_INVALIDARG;
611 * Initialize the return parameter.
613 *ppvObject = 0;
616 * Compare the riid with the interface IDs implemented by this object.
618 if ( (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0) ||
619 (memcmp(&IID_IDataAdviseHolder, riid, sizeof(IID_IDataAdviseHolder)) == 0) )
621 *ppvObject = iface;
625 * Check that we obtained an interface.
627 if ((*ppvObject)==0)
629 return E_NOINTERFACE;
633 * Query Interface always increases the reference count by one when it is
634 * successful.
636 IUnknown_AddRef((IUnknown*)*ppvObject);
638 return S_OK;
641 /************************************************************************
642 * DataAdviseHolder_AddRef (IUnknown)
644 * See Windows documentation for more details on IUnknown methods.
646 static ULONG WINAPI DataAdviseHolder_AddRef(
647 IDataAdviseHolder* iface)
649 DataAdviseHolder *This = (DataAdviseHolder *)iface;
650 TRACE("(%p) (ref=%d)\n", This, This->ref);
651 return InterlockedIncrement(&This->ref);
654 /************************************************************************
655 * DataAdviseHolder_Release (IUnknown)
657 * See Windows documentation for more details on IUnknown methods.
659 static ULONG WINAPI DataAdviseHolder_Release(
660 IDataAdviseHolder* iface)
662 DataAdviseHolder *This = (DataAdviseHolder *)iface;
663 ULONG ref;
664 TRACE("(%p) (ref=%d)\n", This, This->ref);
667 * Decrease the reference count on this object.
669 ref = InterlockedDecrement(&This->ref);
672 * If the reference count goes down to 0, perform suicide.
674 if (ref==0) DataAdviseHolder_Destructor(This);
676 return ref;
679 /************************************************************************
680 * DataAdviseHolder_Advise
683 static HRESULT WINAPI DataAdviseHolder_Advise(
684 IDataAdviseHolder* iface,
685 IDataObject* pDataObject,
686 FORMATETC* pFetc,
687 DWORD advf,
688 IAdviseSink* pAdvise,
689 DWORD* pdwConnection)
691 DWORD index;
693 DataAdviseHolder *This = (DataAdviseHolder *)iface;
695 TRACE("(%p)->(%p, %p, %08x, %p, %p)\n", This, pDataObject, pFetc, advf,
696 pAdvise, pdwConnection);
698 * Sanity check
700 if (pdwConnection==NULL)
701 return E_POINTER;
703 *pdwConnection = 0;
706 * Find a free spot in the array.
708 for (index = 0; index < This->maxCons; index++)
710 if (This->Connections[index].sink == NULL)
711 break;
715 * If the array is full, we need to grow it.
717 if (index == This->maxCons)
719 This->maxCons+=INITIAL_SINKS;
720 This->Connections = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
721 This->Connections,
722 This->maxCons*sizeof(DataAdviseConnection));
725 * Store the new sink
727 This->Connections[index].sink = pAdvise;
728 This->Connections[index].advf = advf & ~WINE_ADVF_REMOTE;
729 This->Connections[index].fmat = *pFetc;
730 if (pFetc->ptd)
732 This->Connections[index].fmat.ptd = CoTaskMemAlloc(pFetc->ptd->tdSize);
733 if (!This->Connections[index].fmat.ptd)
735 IDataAdviseHolder_Unadvise(iface, index + 1);
736 return E_OUTOFMEMORY;
738 memcpy(This->Connections[index].fmat.ptd, pFetc->ptd, pFetc->ptd->tdSize);
741 if (This->Connections[index].sink != NULL) {
742 IAdviseSink_AddRef(This->Connections[index].sink);
744 /* if we are already connected advise the remote object */
745 if (This->delegate)
747 HRESULT hr;
749 hr = IDataObject_DAdvise(This->delegate, &This->Connections[index].fmat,
750 This->Connections[index].advf,
751 This->Connections[index].sink,
752 &This->Connections[index].remote_connection);
753 if (FAILED(hr))
755 IDataAdviseHolder_Unadvise(iface, index + 1);
756 return hr;
758 This->Connections[index].advf |= WINE_ADVF_REMOTE;
760 else if(advf & ADVF_PRIMEFIRST)
761 /* only do this if we have no delegate, since in the above case the
762 * delegate will do the priming for us */
763 IDataAdviseHolder_SendOnDataChange(iface, pDataObject, 0, advf);
766 * Return the index as the cookie.
767 * Since 0 is not a valid cookie, we will increment by
768 * 1 the index in the table.
770 *pdwConnection = index+1;
772 return S_OK;
775 /******************************************************************************
776 * DataAdviseHolder_Unadvise
778 static HRESULT WINAPI DataAdviseHolder_Unadvise(
779 IDataAdviseHolder* iface,
780 DWORD dwConnection)
782 DataAdviseHolder *This = (DataAdviseHolder *)iface;
784 TRACE("(%p)->(%u)\n", This, dwConnection);
787 * So we don't return 0 as a cookie, the index was
788 * incremented by 1 in OleAdviseHolderImpl_Advise
789 * we have to compensate.
791 dwConnection--;
794 * Check for invalid cookies.
796 if (dwConnection >= This->maxCons)
797 return OLE_E_NOCONNECTION;
799 if (This->Connections[dwConnection].sink == NULL)
800 return OLE_E_NOCONNECTION;
802 if (This->delegate && This->Connections[dwConnection].advf & WINE_ADVF_REMOTE)
803 IDataObject_DUnadvise(This->delegate,
804 This->Connections[dwConnection].remote_connection);
807 * Release the sink and mark the spot in the list as free.
809 IAdviseSink_Release(This->Connections[dwConnection].sink);
810 memset(&(This->Connections[dwConnection]), 0, sizeof(DataAdviseConnection));
812 return S_OK;
815 static HRESULT WINAPI DataAdviseHolder_EnumAdvise(
816 IDataAdviseHolder* iface,
817 IEnumSTATDATA** ppenumAdvise)
819 DataAdviseHolder *This = (DataAdviseHolder *)iface;
821 FIXME("(%p)->(%p)\n", This, ppenumAdvise);
822 return E_NOTIMPL;
825 /******************************************************************************
826 * DataAdviseHolder_SendOnDataChange
828 static HRESULT WINAPI DataAdviseHolder_SendOnDataChange(
829 IDataAdviseHolder* iface,
830 IDataObject* pDataObject,
831 DWORD dwReserved,
832 DWORD advf)
834 DataAdviseHolder *This = (DataAdviseHolder *)iface;
835 DWORD index;
836 STGMEDIUM stg;
837 HRESULT res;
839 TRACE("(%p)->(%p,%08x,%08x)\n", This, pDataObject, dwReserved, advf);
841 for(index = 0; index < This->maxCons; index++) {
842 if(This->Connections[index].sink != NULL) {
843 memset(&stg, 0, sizeof(stg));
844 if(!(This->Connections[index].advf & ADVF_NODATA)) {
845 TRACE("Calling IDataObject_GetData\n");
846 res = IDataObject_GetData(pDataObject,
847 &(This->Connections[index].fmat),
848 &stg);
849 TRACE("returns %08x\n", res);
851 TRACE("Calling IAdviseSink_OnDataChange\n");
852 IAdviseSink_OnDataChange(This->Connections[index].sink,
853 &(This->Connections[index].fmat),
854 &stg);
855 TRACE("Done IAdviseSink_OnDataChange\n");
856 if(This->Connections[index].advf & ADVF_ONLYONCE) {
857 TRACE("Removing connection\n");
858 DataAdviseHolder_Unadvise(iface, index+1);
862 return S_OK;
865 /**************************************************************************
866 * DataAdviseHolderImpl_VTable
868 static const IDataAdviseHolderVtbl DataAdviseHolderImpl_VTable =
870 DataAdviseHolder_QueryInterface,
871 DataAdviseHolder_AddRef,
872 DataAdviseHolder_Release,
873 DataAdviseHolder_Advise,
874 DataAdviseHolder_Unadvise,
875 DataAdviseHolder_EnumAdvise,
876 DataAdviseHolder_SendOnDataChange
879 HRESULT DataAdviseHolder_OnConnect(IDataAdviseHolder *iface, IDataObject *pDelegate)
881 DataAdviseHolder *This = (DataAdviseHolder *)iface;
882 DWORD index;
883 HRESULT hr = S_OK;
885 for(index = 0; index < This->maxCons; index++)
887 if(This->Connections[index].sink != NULL)
889 hr = IDataObject_DAdvise(pDelegate, &This->Connections[index].fmat,
890 This->Connections[index].advf,
891 This->Connections[index].sink,
892 &This->Connections[index].remote_connection);
893 if (FAILED(hr)) break;
894 This->Connections[index].advf |= WINE_ADVF_REMOTE;
897 This->delegate = pDelegate;
898 return hr;
901 void DataAdviseHolder_OnDisconnect(IDataAdviseHolder *iface)
903 DataAdviseHolder *This = (DataAdviseHolder *)iface;
904 DWORD index;
906 for(index = 0; index < This->maxCons; index++)
908 if((This->Connections[index].sink != NULL) &&
909 (This->Connections[index].advf & WINE_ADVF_REMOTE))
911 IDataObject_DUnadvise(This->delegate,
912 This->Connections[index].remote_connection);
913 This->Connections[index].advf &= ~WINE_ADVF_REMOTE;
916 This->delegate = NULL;
919 /******************************************************************************
920 * DataAdviseHolder_Constructor
922 static IDataAdviseHolder* DataAdviseHolder_Constructor(void)
924 DataAdviseHolder* newHolder;
926 newHolder = HeapAlloc(GetProcessHeap(), 0, sizeof(DataAdviseHolder));
928 newHolder->lpVtbl = &DataAdviseHolderImpl_VTable;
929 newHolder->ref = 1;
930 newHolder->maxCons = INITIAL_SINKS;
931 newHolder->Connections = HeapAlloc(GetProcessHeap(),
932 HEAP_ZERO_MEMORY,
933 newHolder->maxCons *
934 sizeof(DataAdviseConnection));
935 newHolder->delegate = NULL;
937 TRACE("returning %p\n", newHolder);
938 return (IDataAdviseHolder*)newHolder;
941 /***********************************************************************
942 * API functions
945 /***********************************************************************
946 * CreateOleAdviseHolder [OLE32.@]
948 HRESULT WINAPI CreateOleAdviseHolder(
949 LPOLEADVISEHOLDER *ppOAHolder)
951 TRACE("(%p)\n", ppOAHolder);
954 * Sanity check,
956 if (ppOAHolder==NULL)
957 return E_POINTER;
959 *ppOAHolder = OleAdviseHolderImpl_Constructor ();
961 if (*ppOAHolder != NULL)
962 return S_OK;
964 return E_OUTOFMEMORY;
967 /******************************************************************************
968 * CreateDataAdviseHolder [OLE32.@]
970 HRESULT WINAPI CreateDataAdviseHolder(
971 LPDATAADVISEHOLDER* ppDAHolder)
973 TRACE("(%p)\n", ppDAHolder);
976 * Sanity check,
978 if (ppDAHolder==NULL)
979 return E_POINTER;
981 *ppDAHolder = DataAdviseHolder_Constructor();
983 if (*ppDAHolder != NULL)
984 return S_OK;
986 return E_OUTOFMEMORY;