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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(ole);
37 #define INITIAL_SINKS 10
39 /**************************************************************************
40 * OleAdviseHolderImpl Implementation
42 typedef struct OleAdviseHolderImpl
44 IOleAdviseHolderVtbl *lpVtbl;
49 IAdviseSink** arrayOfSinks;
51 } OleAdviseHolderImpl;
53 static LPOLEADVISEHOLDER OleAdviseHolderImpl_Constructor(void);
54 static void OleAdviseHolderImpl_Destructor(OleAdviseHolderImpl* ptrToDestroy);
55 static HRESULT WINAPI OleAdviseHolderImpl_QueryInterface(LPOLEADVISEHOLDER,REFIID,LPVOID*);
56 static ULONG WINAPI OleAdviseHolderImpl_AddRef(LPOLEADVISEHOLDER);
57 static ULONG WINAPI OleAdviseHolderImpl_Release(LPOLEADVISEHOLDER);
58 static HRESULT WINAPI OleAdviseHolderImpl_Advise(LPOLEADVISEHOLDER, IAdviseSink*, DWORD*);
59 static HRESULT WINAPI OleAdviseHolderImpl_Unadvise (LPOLEADVISEHOLDER, DWORD);
60 static HRESULT WINAPI OleAdviseHolderImpl_EnumAdvise (LPOLEADVISEHOLDER, IEnumSTATDATA **);
61 static HRESULT WINAPI OleAdviseHolderImpl_SendOnRename (LPOLEADVISEHOLDER, IMoniker *);
62 static HRESULT WINAPI OleAdviseHolderImpl_SendOnSave (LPOLEADVISEHOLDER);
63 static HRESULT WINAPI OleAdviseHolderImpl_SendOnClose (LPOLEADVISEHOLDER);
66 /**************************************************************************
67 * OleAdviseHolderImpl_VTable
69 static struct IOleAdviseHolderVtbl oahvt =
71 OleAdviseHolderImpl_QueryInterface,
72 OleAdviseHolderImpl_AddRef,
73 OleAdviseHolderImpl_Release,
74 OleAdviseHolderImpl_Advise,
75 OleAdviseHolderImpl_Unadvise,
76 OleAdviseHolderImpl_EnumAdvise,
77 OleAdviseHolderImpl_SendOnRename,
78 OleAdviseHolderImpl_SendOnSave,
79 OleAdviseHolderImpl_SendOnClose
82 /**************************************************************************
83 * OleAdviseHolderImpl_Constructor
86 static LPOLEADVISEHOLDER OleAdviseHolderImpl_Constructor()
88 OleAdviseHolderImpl* lpoah;
91 lpoah = HeapAlloc(GetProcessHeap(), 0, sizeof(OleAdviseHolderImpl));
93 lpoah->lpVtbl = &oahvt;
95 lpoah->maxSinks = INITIAL_SINKS;
96 lpoah->arrayOfSinks = HeapAlloc(GetProcessHeap(),
98 lpoah->maxSinks * sizeof(IAdviseSink*));
100 for (index = 0; index < lpoah->maxSinks; index++)
101 lpoah->arrayOfSinks[index]=0;
103 TRACE("returning %p\n", lpoah);
104 return (LPOLEADVISEHOLDER)lpoah;
107 /**************************************************************************
108 * OleAdviseHolderImpl_Destructor
110 static void OleAdviseHolderImpl_Destructor(
111 OleAdviseHolderImpl* ptrToDestroy)
114 TRACE("%p\n", ptrToDestroy);
116 for (index = 0; index < ptrToDestroy->maxSinks; index++)
118 if (ptrToDestroy->arrayOfSinks[index]!=0)
120 IAdviseSink_Release(ptrToDestroy->arrayOfSinks[index]);
121 ptrToDestroy->arrayOfSinks[index] = NULL;
125 HeapFree(GetProcessHeap(),
127 ptrToDestroy->arrayOfSinks);
130 HeapFree(GetProcessHeap(),
135 /**************************************************************************
136 * OleAdviseHolderImpl_QueryInterface
138 static HRESULT WINAPI OleAdviseHolderImpl_QueryInterface(
139 LPOLEADVISEHOLDER iface,
143 OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
144 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObj);
153 if (IsEqualIID(riid, &IID_IUnknown))
158 else if(IsEqualIID(riid, &IID_IOleAdviseHolder))
160 /* IOleAdviseHolder */
161 *ppvObj = (IOleAdviseHolder*) This;
165 return E_NOINTERFACE;
168 * A successful QI always increments the reference count.
170 IUnknown_AddRef((IUnknown*)*ppvObj);
175 /******************************************************************************
176 * OleAdviseHolderImpl_AddRef
178 static ULONG WINAPI OleAdviseHolderImpl_AddRef(
179 LPOLEADVISEHOLDER iface)
181 OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
182 ULONG ref = InterlockedIncrement(&This->ref);
184 TRACE("(%p)->(ref=%ld)\n", This, ref - 1);
189 /******************************************************************************
190 * OleAdviseHolderImpl_Release
192 static ULONG WINAPI OleAdviseHolderImpl_Release(
193 LPOLEADVISEHOLDER iface)
195 OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
197 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
198 ref = InterlockedDecrement(&This->ref);
200 if (ref == 0) OleAdviseHolderImpl_Destructor(This);
205 /******************************************************************************
206 * OleAdviseHolderImpl_Advise
208 static HRESULT WINAPI OleAdviseHolderImpl_Advise(
209 LPOLEADVISEHOLDER iface,
210 IAdviseSink* pAdvise,
211 DWORD* pdwConnection)
215 OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
217 TRACE("(%p)->(%p, %p)\n", This, pAdvise, pdwConnection);
222 if (pdwConnection==NULL)
228 * Find a free spot in the array.
230 for (index = 0; index < This->maxSinks; index++)
232 if (This->arrayOfSinks[index]==NULL)
237 * If the array is full, we need to grow it.
239 if (index == This->maxSinks)
243 This->maxSinks+=INITIAL_SINKS;
245 This->arrayOfSinks = HeapReAlloc(GetProcessHeap(),
248 This->maxSinks*sizeof(IAdviseSink*));
250 for (i=index;i < This->maxSinks; i++)
251 This->arrayOfSinks[i]=0;
257 This->arrayOfSinks[index] = pAdvise;
259 if (This->arrayOfSinks[index]!=NULL)
260 IAdviseSink_AddRef(This->arrayOfSinks[index]);
263 * Return the index as the cookie.
264 * Since 0 is not a valid cookie, we will increment by
265 * 1 the index in the table.
267 *pdwConnection = index+1;
272 /******************************************************************************
273 * OleAdviseHolderImpl_Unadvise
275 static HRESULT WINAPI OleAdviseHolderImpl_Unadvise(
276 LPOLEADVISEHOLDER iface,
279 OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
281 TRACE("(%p)->(%lu)\n", This, dwConnection);
284 * So we don't return 0 as a cookie, the index was
285 * incremented by 1 in OleAdviseHolderImpl_Advise
286 * we have to compensate.
291 * Check for invalid cookies.
293 if (dwConnection >= This->maxSinks)
294 return OLE_E_NOCONNECTION;
296 if (This->arrayOfSinks[dwConnection] == NULL)
297 return OLE_E_NOCONNECTION;
300 * Release the sink and mark the spot in the list as free.
302 IAdviseSink_Release(This->arrayOfSinks[dwConnection]);
303 This->arrayOfSinks[dwConnection] = NULL;
308 /******************************************************************************
309 * OleAdviseHolderImpl_EnumAdvise
311 static HRESULT WINAPI
312 OleAdviseHolderImpl_EnumAdvise (LPOLEADVISEHOLDER iface, IEnumSTATDATA **ppenumAdvise)
314 OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
315 FIXME("(%p)->(%p)\n", This, ppenumAdvise);
317 *ppenumAdvise = NULL;
322 /******************************************************************************
323 * OleAdviseHolderImpl_SendOnRename
325 static HRESULT WINAPI
326 OleAdviseHolderImpl_SendOnRename (LPOLEADVISEHOLDER iface, IMoniker *pmk)
328 OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
329 FIXME("(%p)->(%p)\n", This, pmk);
335 /******************************************************************************
336 * OleAdviseHolderImpl_SendOnSave
338 static HRESULT WINAPI
339 OleAdviseHolderImpl_SendOnSave (LPOLEADVISEHOLDER iface)
341 OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
342 FIXME("(%p)\n", This);
347 /******************************************************************************
348 * OleAdviseHolderImpl_SendOnClose
350 static HRESULT WINAPI
351 OleAdviseHolderImpl_SendOnClose (LPOLEADVISEHOLDER iface)
353 OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
354 FIXME("(%p)\n", This);
360 /**************************************************************************
361 * DataAdviseHolder Implementation
363 typedef struct DataAdviseConnection {
367 } DataAdviseConnection;
369 typedef struct DataAdviseHolder
371 IDataAdviseHolderVtbl *lpVtbl;
375 DataAdviseConnection* Connections;
378 /**************************************************************************
379 * DataAdviseHolder method prototypes
381 static IDataAdviseHolder* DataAdviseHolder_Constructor(void);
382 static void DataAdviseHolder_Destructor(DataAdviseHolder* ptrToDestroy);
383 static HRESULT WINAPI DataAdviseHolder_QueryInterface(
384 IDataAdviseHolder* iface,
387 static ULONG WINAPI DataAdviseHolder_AddRef(
388 IDataAdviseHolder* iface);
389 static ULONG WINAPI DataAdviseHolder_Release(
390 IDataAdviseHolder* iface);
391 static HRESULT WINAPI DataAdviseHolder_Advise(
392 IDataAdviseHolder* iface,
393 IDataObject* pDataObject,
396 IAdviseSink* pAdvise,
397 DWORD* pdwConnection);
398 static HRESULT WINAPI DataAdviseHolder_Unadvise(
399 IDataAdviseHolder* iface,
401 static HRESULT WINAPI DataAdviseHolder_EnumAdvise(
402 IDataAdviseHolder* iface,
403 IEnumSTATDATA** ppenumAdvise);
404 static HRESULT WINAPI DataAdviseHolder_SendOnDataChange(
405 IDataAdviseHolder* iface,
406 IDataObject* pDataObject,
410 /**************************************************************************
411 * DataAdviseHolderImpl_VTable
413 static struct IDataAdviseHolderVtbl DataAdviseHolderImpl_VTable =
415 DataAdviseHolder_QueryInterface,
416 DataAdviseHolder_AddRef,
417 DataAdviseHolder_Release,
418 DataAdviseHolder_Advise,
419 DataAdviseHolder_Unadvise,
420 DataAdviseHolder_EnumAdvise,
421 DataAdviseHolder_SendOnDataChange
424 /******************************************************************************
425 * DataAdviseHolder_Constructor
427 static IDataAdviseHolder* DataAdviseHolder_Constructor()
429 DataAdviseHolder* newHolder;
431 newHolder = HeapAlloc(GetProcessHeap(), 0, sizeof(DataAdviseHolder));
433 newHolder->lpVtbl = &DataAdviseHolderImpl_VTable;
435 newHolder->maxCons = INITIAL_SINKS;
436 newHolder->Connections = HeapAlloc(GetProcessHeap(),
439 sizeof(DataAdviseConnection));
441 TRACE("returning %p\n", newHolder);
442 return (IDataAdviseHolder*)newHolder;
445 /******************************************************************************
446 * DataAdviseHolder_Destructor
448 static void DataAdviseHolder_Destructor(DataAdviseHolder* ptrToDestroy)
451 TRACE("%p\n", ptrToDestroy);
453 for (index = 0; index < ptrToDestroy->maxCons; index++)
455 if (ptrToDestroy->Connections[index].sink != NULL)
457 IAdviseSink_Release(ptrToDestroy->Connections[index].sink);
458 ptrToDestroy->Connections[index].sink = NULL;
462 HeapFree(GetProcessHeap(), 0, ptrToDestroy->Connections);
463 HeapFree(GetProcessHeap(), 0, ptrToDestroy);
466 /************************************************************************
467 * DataAdviseHolder_QueryInterface (IUnknown)
469 * See Windows documentation for more details on IUnknown methods.
471 static HRESULT WINAPI DataAdviseHolder_QueryInterface(
472 IDataAdviseHolder* iface,
476 DataAdviseHolder *This = (DataAdviseHolder *)iface;
477 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObject);
479 * Perform a sanity check on the parameters.
481 if ( (This==0) || (ppvObject==0) )
485 * Initialize the return parameter.
490 * Compare the riid with the interface IDs implemented by this object.
492 if ( (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0) ||
493 (memcmp(&IID_IDataAdviseHolder, riid, sizeof(IID_IDataAdviseHolder)) == 0) )
499 * Check that we obtained an interface.
503 return E_NOINTERFACE;
507 * Query Interface always increases the reference count by one when it is
510 IUnknown_AddRef((IUnknown*)*ppvObject);
515 /************************************************************************
516 * DataAdviseHolder_AddRef (IUnknown)
518 * See Windows documentation for more details on IUnknown methods.
520 static ULONG WINAPI DataAdviseHolder_AddRef(
521 IDataAdviseHolder* iface)
523 DataAdviseHolder *This = (DataAdviseHolder *)iface;
524 TRACE("(%p) (ref=%ld)\n", This, This->ref);
525 return InterlockedIncrement(&This->ref);
528 /************************************************************************
529 * DataAdviseHolder_Release (IUnknown)
531 * See Windows documentation for more details on IUnknown methods.
533 static ULONG WINAPI DataAdviseHolder_Release(
534 IDataAdviseHolder* iface)
536 DataAdviseHolder *This = (DataAdviseHolder *)iface;
538 TRACE("(%p) (ref=%ld)\n", This, This->ref);
541 * Decrease the reference count on this object.
543 ref = InterlockedDecrement(&This->ref);
546 * If the reference count goes down to 0, perform suicide.
548 if (ref==0) DataAdviseHolder_Destructor(This);
553 /************************************************************************
554 * DataAdviseHolder_Advise
557 static HRESULT WINAPI DataAdviseHolder_Advise(
558 IDataAdviseHolder* iface,
559 IDataObject* pDataObject,
562 IAdviseSink* pAdvise,
563 DWORD* pdwConnection)
567 DataAdviseHolder *This = (DataAdviseHolder *)iface;
569 TRACE("(%p)->(%p, %p, %08lx, %p, %p)\n", This, pDataObject, pFetc, advf,
570 pAdvise, pdwConnection);
574 if (pdwConnection==NULL)
580 * Find a free spot in the array.
582 for (index = 0; index < This->maxCons; index++)
584 if (This->Connections[index].sink == NULL)
589 * If the array is full, we need to grow it.
591 if (index == This->maxCons)
593 This->maxCons+=INITIAL_SINKS;
594 This->Connections = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
596 This->maxCons*sizeof(DataAdviseConnection));
601 This->Connections[index].sink = pAdvise;
602 memcpy(&(This->Connections[index].fmat), pFetc, sizeof(FORMATETC));
603 This->Connections[index].advf = advf;
605 if (This->Connections[index].sink != NULL) {
606 IAdviseSink_AddRef(This->Connections[index].sink);
607 if(advf & ADVF_PRIMEFIRST) {
608 DataAdviseHolder_SendOnDataChange(iface, pDataObject, 0, advf);
612 * Return the index as the cookie.
613 * Since 0 is not a valid cookie, we will increment by
614 * 1 the index in the table.
616 *pdwConnection = index+1;
621 /******************************************************************************
622 * DataAdviseHolder_Unadvise
624 static HRESULT WINAPI DataAdviseHolder_Unadvise(
625 IDataAdviseHolder* iface,
628 DataAdviseHolder *This = (DataAdviseHolder *)iface;
630 TRACE("(%p)->(%lu)\n", This, dwConnection);
633 * So we don't return 0 as a cookie, the index was
634 * incremented by 1 in OleAdviseHolderImpl_Advise
635 * we have to compensate.
640 * Check for invalid cookies.
642 if (dwConnection >= This->maxCons)
643 return OLE_E_NOCONNECTION;
645 if (This->Connections[dwConnection].sink == NULL)
646 return OLE_E_NOCONNECTION;
649 * Release the sink and mark the spot in the list as free.
651 IAdviseSink_Release(This->Connections[dwConnection].sink);
652 memset(&(This->Connections[dwConnection]), 0, sizeof(DataAdviseConnection));
656 static HRESULT WINAPI DataAdviseHolder_EnumAdvise(
657 IDataAdviseHolder* iface,
658 IEnumSTATDATA** ppenumAdvise)
660 DataAdviseHolder *This = (DataAdviseHolder *)iface;
662 FIXME("(%p)->(%p)\n", This, ppenumAdvise);
666 /******************************************************************************
667 * DataAdviseHolder_SendOnDataChange
669 static HRESULT WINAPI DataAdviseHolder_SendOnDataChange(
670 IDataAdviseHolder* iface,
671 IDataObject* pDataObject,
675 DataAdviseHolder *This = (DataAdviseHolder *)iface;
680 TRACE("(%p)->(%p,%08lx,%08lx)\n", This, pDataObject, dwReserved, advf);
682 for(index = 0; index < This->maxCons; index++) {
683 if(This->Connections[index].sink != NULL) {
684 if(!(This->Connections[index].advf & ADVF_NODATA)) {
685 TRACE("Calling IDataObject_GetData\n");
686 res = IDataObject_GetData(pDataObject,
687 &(This->Connections[index].fmat),
689 TRACE("returns %08lx\n", res);
691 TRACE("Calling IAdviseSink_OnDataChange\n");
692 IAdviseSink_OnDataChange(This->Connections[index].sink,
693 &(This->Connections[index].fmat),
695 TRACE("Done IAdviseSink_OnDataChange\n");
696 if(This->Connections[index].advf & ADVF_ONLYONCE) {
697 TRACE("Removing connection\n");
698 DataAdviseHolder_Unadvise(iface, index+1);
705 /***********************************************************************
709 /***********************************************************************
710 * CreateOleAdviseHolder [OLE32.@]
712 HRESULT WINAPI CreateOleAdviseHolder(
713 LPOLEADVISEHOLDER *ppOAHolder)
715 TRACE("(%p)\n", ppOAHolder);
720 if (ppOAHolder==NULL)
723 *ppOAHolder = OleAdviseHolderImpl_Constructor ();
725 if (*ppOAHolder != NULL)
728 return E_OUTOFMEMORY;
731 /******************************************************************************
732 * CreateDataAdviseHolder [OLE32.@]
734 HRESULT WINAPI CreateDataAdviseHolder(
735 LPDATAADVISEHOLDER* ppDAHolder)
737 TRACE("(%p)\n", ppDAHolder);
742 if (ppDAHolder==NULL)
745 *ppDAHolder = DataAdviseHolder_Constructor();
747 if (*ppDAHolder != NULL)
750 return E_OUTOFMEMORY;