4 * Copyright 1998 Eric Kohl
5 * Copyright 1999 Francis Beaudet
12 #include "debugtools.h"
15 DEFAULT_DEBUG_CHANNEL(ole);
17 #define INITIAL_SINKS 10
19 /**************************************************************************
20 * OleAdviseHolderImpl Implementation
22 typedef struct OleAdviseHolderImpl
24 ICOM_VFIELD(IOleAdviseHolder);
29 IAdviseSink** arrayOfSinks;
31 } OleAdviseHolderImpl;
33 static LPOLEADVISEHOLDER OleAdviseHolderImpl_Constructor();
34 static void OleAdviseHolderImpl_Destructor(OleAdviseHolderImpl* ptrToDestroy);
35 static HRESULT WINAPI OleAdviseHolderImpl_QueryInterface(LPOLEADVISEHOLDER,REFIID,LPVOID*);
36 static ULONG WINAPI OleAdviseHolderImpl_AddRef(LPOLEADVISEHOLDER);
37 static ULONG WINAPI OleAdviseHolderImpl_Release(LPOLEADVISEHOLDER);
38 static HRESULT WINAPI OleAdviseHolderImpl_Advise(LPOLEADVISEHOLDER, IAdviseSink*, DWORD*);
39 static HRESULT WINAPI OleAdviseHolderImpl_Unadvise (LPOLEADVISEHOLDER, DWORD);
40 static HRESULT WINAPI OleAdviseHolderImpl_EnumAdvise (LPOLEADVISEHOLDER, IEnumSTATDATA **);
41 static HRESULT WINAPI OleAdviseHolderImpl_SendOnRename (LPOLEADVISEHOLDER, IMoniker *);
42 static HRESULT WINAPI OleAdviseHolderImpl_SendOnSave (LPOLEADVISEHOLDER);
43 static HRESULT WINAPI OleAdviseHolderImpl_SendOnClose (LPOLEADVISEHOLDER);
46 /**************************************************************************
47 * OleAdviseHolderImpl_VTable
49 static struct ICOM_VTABLE(IOleAdviseHolder) oahvt =
51 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
52 OleAdviseHolderImpl_QueryInterface,
53 OleAdviseHolderImpl_AddRef,
54 OleAdviseHolderImpl_Release,
55 OleAdviseHolderImpl_Advise,
56 OleAdviseHolderImpl_Unadvise,
57 OleAdviseHolderImpl_EnumAdvise,
58 OleAdviseHolderImpl_SendOnRename,
59 OleAdviseHolderImpl_SendOnSave,
60 OleAdviseHolderImpl_SendOnClose
63 /**************************************************************************
64 * OleAdviseHolderImpl_Constructor
67 static LPOLEADVISEHOLDER OleAdviseHolderImpl_Constructor()
69 OleAdviseHolderImpl* lpoah;
72 lpoah= (OleAdviseHolderImpl*)HeapAlloc(GetProcessHeap(),
74 sizeof(OleAdviseHolderImpl));
76 ICOM_VTBL(lpoah) = &oahvt;
78 lpoah->maxSinks = INITIAL_SINKS;
79 lpoah->arrayOfSinks = HeapAlloc(GetProcessHeap(),
81 lpoah->maxSinks * sizeof(IAdviseSink*));
83 for (index = 0; index < lpoah->maxSinks; index++)
84 lpoah->arrayOfSinks[index]=0;
86 TRACE("returning %p\n", lpoah);
87 return (LPOLEADVISEHOLDER)lpoah;
90 /**************************************************************************
91 * OleAdviseHolderImpl_Destructor
93 static void OleAdviseHolderImpl_Destructor(
94 OleAdviseHolderImpl* ptrToDestroy)
97 TRACE("%p\n", ptrToDestroy);
99 for (index = 0; index < ptrToDestroy->maxSinks; index++)
101 if (ptrToDestroy->arrayOfSinks[index]!=0)
103 IAdviseSink_Release(ptrToDestroy->arrayOfSinks[index]);
104 ptrToDestroy->arrayOfSinks[index] = NULL;
108 HeapFree(GetProcessHeap(),
110 ptrToDestroy->arrayOfSinks);
113 HeapFree(GetProcessHeap(),
118 /**************************************************************************
119 * OleAdviseHolderImpl_QueryInterface
121 static HRESULT WINAPI OleAdviseHolderImpl_QueryInterface(
122 LPOLEADVISEHOLDER iface,
126 ICOM_THIS(OleAdviseHolderImpl, iface);
127 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObj);
136 if (IsEqualIID(riid, &IID_IUnknown))
141 else if(IsEqualIID(riid, &IID_IOleAdviseHolder))
143 /* IOleAdviseHolder */
144 *ppvObj = (IOleAdviseHolder*) This;
148 return E_NOINTERFACE;
151 * A successful QI always increments the reference count.
153 IUnknown_AddRef((IUnknown*)*ppvObj);
158 /******************************************************************************
159 * OleAdviseHolderImpl_AddRef
161 static ULONG WINAPI OleAdviseHolderImpl_AddRef(
162 LPOLEADVISEHOLDER iface)
164 ICOM_THIS(OleAdviseHolderImpl, iface);
165 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
166 return ++(This->ref);
169 /******************************************************************************
170 * OleAdviseHolderImpl_Release
172 static ULONG WINAPI OleAdviseHolderImpl_Release(
173 LPOLEADVISEHOLDER iface)
175 ICOM_THIS(OleAdviseHolderImpl, iface);
176 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
181 OleAdviseHolderImpl_Destructor(This);
189 /******************************************************************************
190 * OleAdviseHolderImpl_Advise
192 static HRESULT WINAPI OleAdviseHolderImpl_Advise(
193 LPOLEADVISEHOLDER iface,
194 IAdviseSink* pAdvise,
195 DWORD* pdwConnection)
199 ICOM_THIS(OleAdviseHolderImpl, iface);
201 TRACE("(%p)->(%p, %p)\n", This, pAdvise, pdwConnection);
206 if (pdwConnection==NULL)
212 * Find a free spot in the array.
214 for (index = 0; index < This->maxSinks; index++)
216 if (This->arrayOfSinks[index]==NULL)
221 * If the array is full, we need to grow it.
223 if (index == This->maxSinks)
227 This->maxSinks+=INITIAL_SINKS;
229 This->arrayOfSinks = HeapReAlloc(GetProcessHeap(),
232 This->maxSinks*sizeof(IAdviseSink*));
234 for (i=index;i < This->maxSinks; i++)
235 This->arrayOfSinks[i]=0;
241 This->arrayOfSinks[index] = pAdvise;
243 if (This->arrayOfSinks[index]!=NULL)
244 IAdviseSink_AddRef(This->arrayOfSinks[index]);
247 * Return the index as the cookie.
248 * Since 0 is not a valid cookie, we will increment by
249 * 1 the index in the table.
251 *pdwConnection = index+1;
256 /******************************************************************************
257 * OleAdviseHolderImpl_Unadvise
259 static HRESULT WINAPI OleAdviseHolderImpl_Unadvise(
260 LPOLEADVISEHOLDER iface,
263 ICOM_THIS(OleAdviseHolderImpl, iface);
265 TRACE("(%p)->(%lu)\n", This, dwConnection);
268 * So we don't return 0 as a cookie, the index was
269 * incremented by 1 in OleAdviseHolderImpl_Advise
270 * we have to compensate.
275 * Check for invalid cookies.
277 if ( (dwConnection < 0) ||
278 (dwConnection >= This->maxSinks) )
279 return OLE_E_NOCONNECTION;
281 if (This->arrayOfSinks[dwConnection] == NULL)
282 return OLE_E_NOCONNECTION;
285 * Release the sink and mark the spot in the list as free.
287 IAdviseSink_Release(This->arrayOfSinks[dwConnection]);
288 This->arrayOfSinks[dwConnection] = NULL;
293 /******************************************************************************
294 * OleAdviseHolderImpl_EnumAdvise
296 static HRESULT WINAPI
297 OleAdviseHolderImpl_EnumAdvise (LPOLEADVISEHOLDER iface, IEnumSTATDATA **ppenumAdvise)
299 ICOM_THIS(OleAdviseHolderImpl, iface);
300 FIXME("(%p)->(%p)\n", This, ppenumAdvise);
302 *ppenumAdvise = NULL;
307 /******************************************************************************
308 * OleAdviseHolderImpl_SendOnRename
310 static HRESULT WINAPI
311 OleAdviseHolderImpl_SendOnRename (LPOLEADVISEHOLDER iface, IMoniker *pmk)
313 ICOM_THIS(OleAdviseHolderImpl, iface);
314 FIXME("(%p)->(%p)\n", This, pmk);
320 /******************************************************************************
321 * OleAdviseHolderImpl_SendOnSave
323 static HRESULT WINAPI
324 OleAdviseHolderImpl_SendOnSave (LPOLEADVISEHOLDER iface)
326 ICOM_THIS(OleAdviseHolderImpl, iface);
327 FIXME("(%p)\n", This);
332 /******************************************************************************
333 * OleAdviseHolderImpl_SendOnClose
335 static HRESULT WINAPI
336 OleAdviseHolderImpl_SendOnClose (LPOLEADVISEHOLDER iface)
338 ICOM_THIS(OleAdviseHolderImpl, iface);
339 FIXME("(%p)\n", This);
345 /**************************************************************************
346 * DataAdviseHolder Implementation
348 typedef struct DataAdviseConnection {
352 } DataAdviseConnection;
354 typedef struct DataAdviseHolder
356 ICOM_VFIELD(IDataAdviseHolder);
360 DataAdviseConnection* Connections;
363 /**************************************************************************
364 * DataAdviseHolder method prototypes
366 static IDataAdviseHolder* DataAdviseHolder_Constructor();
367 static void DataAdviseHolder_Destructor(DataAdviseHolder* ptrToDestroy);
368 static HRESULT WINAPI DataAdviseHolder_QueryInterface(
369 IDataAdviseHolder* iface,
372 static ULONG WINAPI DataAdviseHolder_AddRef(
373 IDataAdviseHolder* iface);
374 static ULONG WINAPI DataAdviseHolder_Release(
375 IDataAdviseHolder* iface);
376 static HRESULT WINAPI DataAdviseHolder_Advise(
377 IDataAdviseHolder* iface,
378 IDataObject* pDataObject,
381 IAdviseSink* pAdvise,
382 DWORD* pdwConnection);
383 static HRESULT WINAPI DataAdviseHolder_Unadvise(
384 IDataAdviseHolder* iface,
386 static HRESULT WINAPI DataAdviseHolder_EnumAdvise(
387 IDataAdviseHolder* iface,
388 IEnumSTATDATA** ppenumAdvise);
389 static HRESULT WINAPI DataAdviseHolder_SendOnDataChange(
390 IDataAdviseHolder* iface,
391 IDataObject* pDataObject,
395 /**************************************************************************
396 * DataAdviseHolderImpl_VTable
398 static struct ICOM_VTABLE(IDataAdviseHolder) DataAdviseHolderImpl_VTable =
400 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
401 DataAdviseHolder_QueryInterface,
402 DataAdviseHolder_AddRef,
403 DataAdviseHolder_Release,
404 DataAdviseHolder_Advise,
405 DataAdviseHolder_Unadvise,
406 DataAdviseHolder_EnumAdvise,
407 DataAdviseHolder_SendOnDataChange
410 /******************************************************************************
411 * DataAdviseHolder_Constructor
413 static IDataAdviseHolder* DataAdviseHolder_Constructor()
415 DataAdviseHolder* newHolder;
417 newHolder = (DataAdviseHolder*)HeapAlloc(GetProcessHeap(),
419 sizeof(DataAdviseHolder));
421 ICOM_VTBL(newHolder) = &DataAdviseHolderImpl_VTable;
423 newHolder->maxCons = INITIAL_SINKS;
424 newHolder->Connections = HeapAlloc(GetProcessHeap(),
427 sizeof(DataAdviseConnection));
429 TRACE("returning %p\n", newHolder);
430 return (IDataAdviseHolder*)newHolder;
433 /******************************************************************************
434 * DataAdviseHolder_Destructor
436 static void DataAdviseHolder_Destructor(DataAdviseHolder* ptrToDestroy)
439 TRACE("%p\n", ptrToDestroy);
441 for (index = 0; index < ptrToDestroy->maxCons; index++)
443 if (ptrToDestroy->Connections[index].sink != NULL)
445 IAdviseSink_Release(ptrToDestroy->Connections[index].sink);
446 ptrToDestroy->Connections[index].sink = NULL;
450 HeapFree(GetProcessHeap(), 0, ptrToDestroy->Connections);
451 HeapFree(GetProcessHeap(), 0, ptrToDestroy);
454 /************************************************************************
455 * DataAdviseHolder_QueryInterface (IUnknown)
457 * See Windows documentation for more details on IUnknown methods.
459 static HRESULT WINAPI DataAdviseHolder_QueryInterface(
460 IDataAdviseHolder* iface,
464 ICOM_THIS(DataAdviseHolder, iface);
465 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObject);
467 * Perform a sanity check on the parameters.
469 if ( (This==0) || (ppvObject==0) )
473 * Initialize the return parameter.
478 * Compare the riid with the interface IDs implemented by this object.
480 if ( (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0) ||
481 (memcmp(&IID_IDataAdviseHolder, riid, sizeof(IID_IDataAdviseHolder)) == 0) )
487 * Check that we obtained an interface.
491 return E_NOINTERFACE;
495 * Query Interface always increases the reference count by one when it is
498 IUnknown_AddRef((IUnknown*)*ppvObject);
503 /************************************************************************
504 * DataAdviseHolder_AddRef (IUnknown)
506 * See Windows documentation for more details on IUnknown methods.
508 static ULONG WINAPI DataAdviseHolder_AddRef(
509 IDataAdviseHolder* iface)
511 ICOM_THIS(DataAdviseHolder, iface);
512 TRACE("(%p) (ref=%ld)\n", This, This->ref);
518 /************************************************************************
519 * DataAdviseHolder_Release (IUnknown)
521 * See Windows documentation for more details on IUnknown methods.
523 static ULONG WINAPI DataAdviseHolder_Release(
524 IDataAdviseHolder* iface)
526 ICOM_THIS(DataAdviseHolder, iface);
527 TRACE("(%p) (ref=%ld)\n", This, This->ref);
530 * Decrease the reference count on this object.
535 * If the reference count goes down to 0, perform suicide.
539 DataAdviseHolder_Destructor(This);
547 /************************************************************************
548 * DataAdviseHolder_Advise
551 static HRESULT WINAPI DataAdviseHolder_Advise(
552 IDataAdviseHolder* iface,
553 IDataObject* pDataObject,
556 IAdviseSink* pAdvise,
557 DWORD* pdwConnection)
561 ICOM_THIS(DataAdviseHolder, iface);
563 TRACE("(%p)->(%p, %p, %08lx, %p, %p)\n", This, pDataObject, pFetc, advf,
564 pAdvise, pdwConnection);
568 if (pdwConnection==NULL)
574 * Find a free spot in the array.
576 for (index = 0; index < This->maxCons; index++)
578 if (This->Connections[index].sink == NULL)
583 * If the array is full, we need to grow it.
585 if (index == This->maxCons)
587 This->maxCons+=INITIAL_SINKS;
588 This->Connections = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
590 This->maxCons*sizeof(DataAdviseConnection));
595 This->Connections[index].sink = pAdvise;
596 memcpy(&(This->Connections[index].fmat), pFetc, sizeof(FORMATETC));
597 This->Connections[index].advf = advf;
599 if (This->Connections[index].sink != NULL) {
600 IAdviseSink_AddRef(This->Connections[index].sink);
601 if(advf & ADVF_PRIMEFIRST) {
602 DataAdviseHolder_SendOnDataChange(iface, pDataObject, 0, advf);
606 * Return the index as the cookie.
607 * Since 0 is not a valid cookie, we will increment by
608 * 1 the index in the table.
610 *pdwConnection = index+1;
615 /******************************************************************************
616 * DataAdviseHolder_Unadvise
618 static HRESULT WINAPI DataAdviseHolder_Unadvise(
619 IDataAdviseHolder* iface,
622 ICOM_THIS(DataAdviseHolder, iface);
624 TRACE("(%p)->(%lu)\n", This, dwConnection);
627 * So we don't return 0 as a cookie, the index was
628 * incremented by 1 in OleAdviseHolderImpl_Advise
629 * we have to compensate.
634 * Check for invalid cookies.
636 if ( (dwConnection < 0) ||
637 (dwConnection >= This->maxCons) )
638 return OLE_E_NOCONNECTION;
640 if (This->Connections[dwConnection].sink == NULL)
641 return OLE_E_NOCONNECTION;
644 * Release the sink and mark the spot in the list as free.
646 IAdviseSink_Release(This->Connections[dwConnection].sink);
647 memset(&(This->Connections[dwConnection]), 0, sizeof(DataAdviseConnection));
651 static HRESULT WINAPI DataAdviseHolder_EnumAdvise(
652 IDataAdviseHolder* iface,
653 IEnumSTATDATA** ppenumAdvise)
655 ICOM_THIS(DataAdviseHolder, iface);
657 FIXME("(%p)->(%p)\n", This, ppenumAdvise);
661 /******************************************************************************
662 * DataAdviseHolder_SendOnDataChange
664 static HRESULT WINAPI DataAdviseHolder_SendOnDataChange(
665 IDataAdviseHolder* iface,
666 IDataObject* pDataObject,
670 ICOM_THIS(DataAdviseHolder, iface);
675 TRACE("(%p)->(%p,%08lx,%08lx)\n", This, pDataObject, dwReserved, advf);
677 for(index = 0; index < This->maxCons; index++) {
678 if(This->Connections[index].sink != NULL) {
679 if(!(This->Connections[index].advf & ADVF_NODATA)) {
680 TRACE("Calling IDataObject_GetData\n");
681 res = IDataObject_GetData(pDataObject,
682 &(This->Connections[index].fmat),
684 TRACE("returns %08lx\n", res);
686 TRACE("Calling IAdviseSink_OnDataChange\n");
687 IAdviseSink_OnDataChange(This->Connections[index].sink,
688 &(This->Connections[index].fmat),
690 TRACE("Done IAdviseSink_OnDataChange\n");
691 if(This->Connections[index].advf & ADVF_ONLYONCE) {
692 TRACE("Removing connection\n");
693 DataAdviseHolder_Unadvise(iface, index+1);
700 /***********************************************************************
704 /***********************************************************************
705 * CreateOleAdviseHolder [OLE32.59]
707 HRESULT WINAPI CreateOleAdviseHolder(
708 LPOLEADVISEHOLDER *ppOAHolder)
710 TRACE("(%p)\n", ppOAHolder);
715 if (ppOAHolder==NULL)
718 *ppOAHolder = OleAdviseHolderImpl_Constructor ();
720 if (*ppOAHolder != NULL)
723 return E_OUTOFMEMORY;
726 /******************************************************************************
727 * CreateDataAdviseHolder [OLE32.53]
729 HRESULT WINAPI CreateDataAdviseHolder(
730 LPDATAADVISEHOLDER* ppDAHolder)
732 TRACE("(%p)\n", ppDAHolder);
737 if (ppDAHolder==NULL)
740 *ppDAHolder = DataAdviseHolder_Constructor();
742 if (*ppDAHolder != NULL)
745 return E_OUTOFMEMORY;