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
26 #include "wine/debug.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(ole);
31 #define INITIAL_SINKS 10
33 /**************************************************************************
34 * OleAdviseHolderImpl Implementation
36 typedef struct OleAdviseHolderImpl
38 ICOM_VFIELD(IOleAdviseHolder);
43 IAdviseSink** arrayOfSinks;
45 } OleAdviseHolderImpl;
47 static LPOLEADVISEHOLDER OleAdviseHolderImpl_Constructor();
48 static void OleAdviseHolderImpl_Destructor(OleAdviseHolderImpl* ptrToDestroy);
49 static HRESULT WINAPI OleAdviseHolderImpl_QueryInterface(LPOLEADVISEHOLDER,REFIID,LPVOID*);
50 static ULONG WINAPI OleAdviseHolderImpl_AddRef(LPOLEADVISEHOLDER);
51 static ULONG WINAPI OleAdviseHolderImpl_Release(LPOLEADVISEHOLDER);
52 static HRESULT WINAPI OleAdviseHolderImpl_Advise(LPOLEADVISEHOLDER, IAdviseSink*, DWORD*);
53 static HRESULT WINAPI OleAdviseHolderImpl_Unadvise (LPOLEADVISEHOLDER, DWORD);
54 static HRESULT WINAPI OleAdviseHolderImpl_EnumAdvise (LPOLEADVISEHOLDER, IEnumSTATDATA **);
55 static HRESULT WINAPI OleAdviseHolderImpl_SendOnRename (LPOLEADVISEHOLDER, IMoniker *);
56 static HRESULT WINAPI OleAdviseHolderImpl_SendOnSave (LPOLEADVISEHOLDER);
57 static HRESULT WINAPI OleAdviseHolderImpl_SendOnClose (LPOLEADVISEHOLDER);
60 /**************************************************************************
61 * OleAdviseHolderImpl_VTable
63 static struct ICOM_VTABLE(IOleAdviseHolder) oahvt =
65 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
66 OleAdviseHolderImpl_QueryInterface,
67 OleAdviseHolderImpl_AddRef,
68 OleAdviseHolderImpl_Release,
69 OleAdviseHolderImpl_Advise,
70 OleAdviseHolderImpl_Unadvise,
71 OleAdviseHolderImpl_EnumAdvise,
72 OleAdviseHolderImpl_SendOnRename,
73 OleAdviseHolderImpl_SendOnSave,
74 OleAdviseHolderImpl_SendOnClose
77 /**************************************************************************
78 * OleAdviseHolderImpl_Constructor
81 static LPOLEADVISEHOLDER OleAdviseHolderImpl_Constructor()
83 OleAdviseHolderImpl* lpoah;
86 lpoah= (OleAdviseHolderImpl*)HeapAlloc(GetProcessHeap(),
88 sizeof(OleAdviseHolderImpl));
90 ICOM_VTBL(lpoah) = &oahvt;
92 lpoah->maxSinks = INITIAL_SINKS;
93 lpoah->arrayOfSinks = HeapAlloc(GetProcessHeap(),
95 lpoah->maxSinks * sizeof(IAdviseSink*));
97 for (index = 0; index < lpoah->maxSinks; index++)
98 lpoah->arrayOfSinks[index]=0;
100 TRACE("returning %p\n", lpoah);
101 return (LPOLEADVISEHOLDER)lpoah;
104 /**************************************************************************
105 * OleAdviseHolderImpl_Destructor
107 static void OleAdviseHolderImpl_Destructor(
108 OleAdviseHolderImpl* ptrToDestroy)
111 TRACE("%p\n", ptrToDestroy);
113 for (index = 0; index < ptrToDestroy->maxSinks; index++)
115 if (ptrToDestroy->arrayOfSinks[index]!=0)
117 IAdviseSink_Release(ptrToDestroy->arrayOfSinks[index]);
118 ptrToDestroy->arrayOfSinks[index] = NULL;
122 HeapFree(GetProcessHeap(),
124 ptrToDestroy->arrayOfSinks);
127 HeapFree(GetProcessHeap(),
132 /**************************************************************************
133 * OleAdviseHolderImpl_QueryInterface
135 static HRESULT WINAPI OleAdviseHolderImpl_QueryInterface(
136 LPOLEADVISEHOLDER iface,
140 ICOM_THIS(OleAdviseHolderImpl, iface);
141 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObj);
150 if (IsEqualIID(riid, &IID_IUnknown))
155 else if(IsEqualIID(riid, &IID_IOleAdviseHolder))
157 /* IOleAdviseHolder */
158 *ppvObj = (IOleAdviseHolder*) This;
162 return E_NOINTERFACE;
165 * A successful QI always increments the reference count.
167 IUnknown_AddRef((IUnknown*)*ppvObj);
172 /******************************************************************************
173 * OleAdviseHolderImpl_AddRef
175 static ULONG WINAPI OleAdviseHolderImpl_AddRef(
176 LPOLEADVISEHOLDER iface)
178 ICOM_THIS(OleAdviseHolderImpl, iface);
179 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
180 return ++(This->ref);
183 /******************************************************************************
184 * OleAdviseHolderImpl_Release
186 static ULONG WINAPI OleAdviseHolderImpl_Release(
187 LPOLEADVISEHOLDER iface)
189 ICOM_THIS(OleAdviseHolderImpl, iface);
190 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
195 OleAdviseHolderImpl_Destructor(This);
203 /******************************************************************************
204 * OleAdviseHolderImpl_Advise
206 static HRESULT WINAPI OleAdviseHolderImpl_Advise(
207 LPOLEADVISEHOLDER iface,
208 IAdviseSink* pAdvise,
209 DWORD* pdwConnection)
213 ICOM_THIS(OleAdviseHolderImpl, iface);
215 TRACE("(%p)->(%p, %p)\n", This, pAdvise, pdwConnection);
220 if (pdwConnection==NULL)
226 * Find a free spot in the array.
228 for (index = 0; index < This->maxSinks; index++)
230 if (This->arrayOfSinks[index]==NULL)
235 * If the array is full, we need to grow it.
237 if (index == This->maxSinks)
241 This->maxSinks+=INITIAL_SINKS;
243 This->arrayOfSinks = HeapReAlloc(GetProcessHeap(),
246 This->maxSinks*sizeof(IAdviseSink*));
248 for (i=index;i < This->maxSinks; i++)
249 This->arrayOfSinks[i]=0;
255 This->arrayOfSinks[index] = pAdvise;
257 if (This->arrayOfSinks[index]!=NULL)
258 IAdviseSink_AddRef(This->arrayOfSinks[index]);
261 * Return the index as the cookie.
262 * Since 0 is not a valid cookie, we will increment by
263 * 1 the index in the table.
265 *pdwConnection = index+1;
270 /******************************************************************************
271 * OleAdviseHolderImpl_Unadvise
273 static HRESULT WINAPI OleAdviseHolderImpl_Unadvise(
274 LPOLEADVISEHOLDER iface,
277 ICOM_THIS(OleAdviseHolderImpl, iface);
279 TRACE("(%p)->(%lu)\n", This, dwConnection);
282 * So we don't return 0 as a cookie, the index was
283 * incremented by 1 in OleAdviseHolderImpl_Advise
284 * we have to compensate.
289 * Check for invalid cookies.
291 if ( (dwConnection < 0) ||
292 (dwConnection >= This->maxSinks) )
293 return OLE_E_NOCONNECTION;
295 if (This->arrayOfSinks[dwConnection] == NULL)
296 return OLE_E_NOCONNECTION;
299 * Release the sink and mark the spot in the list as free.
301 IAdviseSink_Release(This->arrayOfSinks[dwConnection]);
302 This->arrayOfSinks[dwConnection] = NULL;
307 /******************************************************************************
308 * OleAdviseHolderImpl_EnumAdvise
310 static HRESULT WINAPI
311 OleAdviseHolderImpl_EnumAdvise (LPOLEADVISEHOLDER iface, IEnumSTATDATA **ppenumAdvise)
313 ICOM_THIS(OleAdviseHolderImpl, iface);
314 FIXME("(%p)->(%p)\n", This, ppenumAdvise);
316 *ppenumAdvise = NULL;
321 /******************************************************************************
322 * OleAdviseHolderImpl_SendOnRename
324 static HRESULT WINAPI
325 OleAdviseHolderImpl_SendOnRename (LPOLEADVISEHOLDER iface, IMoniker *pmk)
327 ICOM_THIS(OleAdviseHolderImpl, iface);
328 FIXME("(%p)->(%p)\n", This, pmk);
334 /******************************************************************************
335 * OleAdviseHolderImpl_SendOnSave
337 static HRESULT WINAPI
338 OleAdviseHolderImpl_SendOnSave (LPOLEADVISEHOLDER iface)
340 ICOM_THIS(OleAdviseHolderImpl, iface);
341 FIXME("(%p)\n", This);
346 /******************************************************************************
347 * OleAdviseHolderImpl_SendOnClose
349 static HRESULT WINAPI
350 OleAdviseHolderImpl_SendOnClose (LPOLEADVISEHOLDER iface)
352 ICOM_THIS(OleAdviseHolderImpl, iface);
353 FIXME("(%p)\n", This);
359 /**************************************************************************
360 * DataAdviseHolder Implementation
362 typedef struct DataAdviseConnection {
366 } DataAdviseConnection;
368 typedef struct DataAdviseHolder
370 ICOM_VFIELD(IDataAdviseHolder);
374 DataAdviseConnection* Connections;
377 /**************************************************************************
378 * DataAdviseHolder method prototypes
380 static IDataAdviseHolder* DataAdviseHolder_Constructor();
381 static void DataAdviseHolder_Destructor(DataAdviseHolder* ptrToDestroy);
382 static HRESULT WINAPI DataAdviseHolder_QueryInterface(
383 IDataAdviseHolder* iface,
386 static ULONG WINAPI DataAdviseHolder_AddRef(
387 IDataAdviseHolder* iface);
388 static ULONG WINAPI DataAdviseHolder_Release(
389 IDataAdviseHolder* iface);
390 static HRESULT WINAPI DataAdviseHolder_Advise(
391 IDataAdviseHolder* iface,
392 IDataObject* pDataObject,
395 IAdviseSink* pAdvise,
396 DWORD* pdwConnection);
397 static HRESULT WINAPI DataAdviseHolder_Unadvise(
398 IDataAdviseHolder* iface,
400 static HRESULT WINAPI DataAdviseHolder_EnumAdvise(
401 IDataAdviseHolder* iface,
402 IEnumSTATDATA** ppenumAdvise);
403 static HRESULT WINAPI DataAdviseHolder_SendOnDataChange(
404 IDataAdviseHolder* iface,
405 IDataObject* pDataObject,
409 /**************************************************************************
410 * DataAdviseHolderImpl_VTable
412 static struct ICOM_VTABLE(IDataAdviseHolder) DataAdviseHolderImpl_VTable =
414 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
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 = (DataAdviseHolder*)HeapAlloc(GetProcessHeap(),
433 sizeof(DataAdviseHolder));
435 ICOM_VTBL(newHolder) = &DataAdviseHolderImpl_VTable;
437 newHolder->maxCons = INITIAL_SINKS;
438 newHolder->Connections = HeapAlloc(GetProcessHeap(),
441 sizeof(DataAdviseConnection));
443 TRACE("returning %p\n", newHolder);
444 return (IDataAdviseHolder*)newHolder;
447 /******************************************************************************
448 * DataAdviseHolder_Destructor
450 static void DataAdviseHolder_Destructor(DataAdviseHolder* ptrToDestroy)
453 TRACE("%p\n", ptrToDestroy);
455 for (index = 0; index < ptrToDestroy->maxCons; index++)
457 if (ptrToDestroy->Connections[index].sink != NULL)
459 IAdviseSink_Release(ptrToDestroy->Connections[index].sink);
460 ptrToDestroy->Connections[index].sink = NULL;
464 HeapFree(GetProcessHeap(), 0, ptrToDestroy->Connections);
465 HeapFree(GetProcessHeap(), 0, ptrToDestroy);
468 /************************************************************************
469 * DataAdviseHolder_QueryInterface (IUnknown)
471 * See Windows documentation for more details on IUnknown methods.
473 static HRESULT WINAPI DataAdviseHolder_QueryInterface(
474 IDataAdviseHolder* iface,
478 ICOM_THIS(DataAdviseHolder, iface);
479 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObject);
481 * Perform a sanity check on the parameters.
483 if ( (This==0) || (ppvObject==0) )
487 * Initialize the return parameter.
492 * Compare the riid with the interface IDs implemented by this object.
494 if ( (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0) ||
495 (memcmp(&IID_IDataAdviseHolder, riid, sizeof(IID_IDataAdviseHolder)) == 0) )
501 * Check that we obtained an interface.
505 return E_NOINTERFACE;
509 * Query Interface always increases the reference count by one when it is
512 IUnknown_AddRef((IUnknown*)*ppvObject);
517 /************************************************************************
518 * DataAdviseHolder_AddRef (IUnknown)
520 * See Windows documentation for more details on IUnknown methods.
522 static ULONG WINAPI DataAdviseHolder_AddRef(
523 IDataAdviseHolder* iface)
525 ICOM_THIS(DataAdviseHolder, iface);
526 TRACE("(%p) (ref=%ld)\n", This, This->ref);
532 /************************************************************************
533 * DataAdviseHolder_Release (IUnknown)
535 * See Windows documentation for more details on IUnknown methods.
537 static ULONG WINAPI DataAdviseHolder_Release(
538 IDataAdviseHolder* iface)
540 ICOM_THIS(DataAdviseHolder, iface);
541 TRACE("(%p) (ref=%ld)\n", This, This->ref);
544 * Decrease the reference count on this object.
549 * If the reference count goes down to 0, perform suicide.
553 DataAdviseHolder_Destructor(This);
561 /************************************************************************
562 * DataAdviseHolder_Advise
565 static HRESULT WINAPI DataAdviseHolder_Advise(
566 IDataAdviseHolder* iface,
567 IDataObject* pDataObject,
570 IAdviseSink* pAdvise,
571 DWORD* pdwConnection)
575 ICOM_THIS(DataAdviseHolder, iface);
577 TRACE("(%p)->(%p, %p, %08lx, %p, %p)\n", This, pDataObject, pFetc, advf,
578 pAdvise, pdwConnection);
582 if (pdwConnection==NULL)
588 * Find a free spot in the array.
590 for (index = 0; index < This->maxCons; index++)
592 if (This->Connections[index].sink == NULL)
597 * If the array is full, we need to grow it.
599 if (index == This->maxCons)
601 This->maxCons+=INITIAL_SINKS;
602 This->Connections = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
604 This->maxCons*sizeof(DataAdviseConnection));
609 This->Connections[index].sink = pAdvise;
610 memcpy(&(This->Connections[index].fmat), pFetc, sizeof(FORMATETC));
611 This->Connections[index].advf = advf;
613 if (This->Connections[index].sink != NULL) {
614 IAdviseSink_AddRef(This->Connections[index].sink);
615 if(advf & ADVF_PRIMEFIRST) {
616 DataAdviseHolder_SendOnDataChange(iface, pDataObject, 0, advf);
620 * Return the index as the cookie.
621 * Since 0 is not a valid cookie, we will increment by
622 * 1 the index in the table.
624 *pdwConnection = index+1;
629 /******************************************************************************
630 * DataAdviseHolder_Unadvise
632 static HRESULT WINAPI DataAdviseHolder_Unadvise(
633 IDataAdviseHolder* iface,
636 ICOM_THIS(DataAdviseHolder, iface);
638 TRACE("(%p)->(%lu)\n", This, dwConnection);
641 * So we don't return 0 as a cookie, the index was
642 * incremented by 1 in OleAdviseHolderImpl_Advise
643 * we have to compensate.
648 * Check for invalid cookies.
650 if ( (dwConnection < 0) ||
651 (dwConnection >= This->maxCons) )
652 return OLE_E_NOCONNECTION;
654 if (This->Connections[dwConnection].sink == NULL)
655 return OLE_E_NOCONNECTION;
658 * Release the sink and mark the spot in the list as free.
660 IAdviseSink_Release(This->Connections[dwConnection].sink);
661 memset(&(This->Connections[dwConnection]), 0, sizeof(DataAdviseConnection));
665 static HRESULT WINAPI DataAdviseHolder_EnumAdvise(
666 IDataAdviseHolder* iface,
667 IEnumSTATDATA** ppenumAdvise)
669 ICOM_THIS(DataAdviseHolder, iface);
671 FIXME("(%p)->(%p)\n", This, ppenumAdvise);
675 /******************************************************************************
676 * DataAdviseHolder_SendOnDataChange
678 static HRESULT WINAPI DataAdviseHolder_SendOnDataChange(
679 IDataAdviseHolder* iface,
680 IDataObject* pDataObject,
684 ICOM_THIS(DataAdviseHolder, iface);
689 TRACE("(%p)->(%p,%08lx,%08lx)\n", This, pDataObject, dwReserved, advf);
691 for(index = 0; index < This->maxCons; index++) {
692 if(This->Connections[index].sink != NULL) {
693 if(!(This->Connections[index].advf & ADVF_NODATA)) {
694 TRACE("Calling IDataObject_GetData\n");
695 res = IDataObject_GetData(pDataObject,
696 &(This->Connections[index].fmat),
698 TRACE("returns %08lx\n", res);
700 TRACE("Calling IAdviseSink_OnDataChange\n");
701 IAdviseSink_OnDataChange(This->Connections[index].sink,
702 &(This->Connections[index].fmat),
704 TRACE("Done IAdviseSink_OnDataChange\n");
705 if(This->Connections[index].advf & ADVF_ONLYONCE) {
706 TRACE("Removing connection\n");
707 DataAdviseHolder_Unadvise(iface, index+1);
714 /***********************************************************************
718 /***********************************************************************
719 * CreateOleAdviseHolder [OLE32.59]
721 HRESULT WINAPI CreateOleAdviseHolder(
722 LPOLEADVISEHOLDER *ppOAHolder)
724 TRACE("(%p)\n", ppOAHolder);
729 if (ppOAHolder==NULL)
732 *ppOAHolder = OleAdviseHolderImpl_Constructor ();
734 if (*ppOAHolder != NULL)
737 return E_OUTOFMEMORY;
740 /******************************************************************************
741 * CreateDataAdviseHolder [OLE32.53]
743 HRESULT WINAPI CreateDataAdviseHolder(
744 LPDATAADVISEHOLDER* ppDAHolder)
746 TRACE("(%p)\n", ppDAHolder);
751 if (ppDAHolder==NULL)
754 *ppDAHolder = DataAdviseHolder_Constructor();
756 if (*ppDAHolder != NULL)
759 return E_OUTOFMEMORY;