4 * Copyright 1998 Eric Kohl
5 * Copyright 1999 Francis Beaudet
12 #include "debugtools.h"
17 DEFAULT_DEBUG_CHANNEL(ole);
19 #define INITIAL_SINKS 10
21 /**************************************************************************
22 * OleAdviseHolderImpl Implementation
24 typedef struct OleAdviseHolderImpl
26 ICOM_VFIELD(IOleAdviseHolder);
31 IAdviseSink** arrayOfSinks;
33 } OleAdviseHolderImpl;
35 static LPOLEADVISEHOLDER OleAdviseHolderImpl_Constructor();
36 static void OleAdviseHolderImpl_Destructor(OleAdviseHolderImpl* ptrToDestroy);
37 static HRESULT WINAPI OleAdviseHolderImpl_QueryInterface(LPOLEADVISEHOLDER,REFIID,LPVOID*);
38 static ULONG WINAPI OleAdviseHolderImpl_AddRef(LPOLEADVISEHOLDER);
39 static ULONG WINAPI OleAdviseHolderImpl_Release(LPOLEADVISEHOLDER);
40 static HRESULT WINAPI OleAdviseHolderImpl_Advise(LPOLEADVISEHOLDER, IAdviseSink*, DWORD*);
41 static HRESULT WINAPI OleAdviseHolderImpl_Unadvise (LPOLEADVISEHOLDER, DWORD);
42 static HRESULT WINAPI OleAdviseHolderImpl_EnumAdvise (LPOLEADVISEHOLDER, IEnumSTATDATA **);
43 static HRESULT WINAPI OleAdviseHolderImpl_SendOnRename (LPOLEADVISEHOLDER, IMoniker *);
44 static HRESULT WINAPI OleAdviseHolderImpl_SendOnSave (LPOLEADVISEHOLDER);
45 static HRESULT WINAPI OleAdviseHolderImpl_SendOnClose (LPOLEADVISEHOLDER);
48 /**************************************************************************
49 * OleAdviseHolderImpl_VTable
51 static struct ICOM_VTABLE(IOleAdviseHolder) oahvt =
53 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
54 OleAdviseHolderImpl_QueryInterface,
55 OleAdviseHolderImpl_AddRef,
56 OleAdviseHolderImpl_Release,
57 OleAdviseHolderImpl_Advise,
58 OleAdviseHolderImpl_Unadvise,
59 OleAdviseHolderImpl_EnumAdvise,
60 OleAdviseHolderImpl_SendOnRename,
61 OleAdviseHolderImpl_SendOnSave,
62 OleAdviseHolderImpl_SendOnClose
65 /**************************************************************************
66 * OleAdviseHolderImpl_Constructor
69 static LPOLEADVISEHOLDER OleAdviseHolderImpl_Constructor()
71 OleAdviseHolderImpl* lpoah;
74 lpoah= (OleAdviseHolderImpl*)HeapAlloc(GetProcessHeap(),
76 sizeof(OleAdviseHolderImpl));
78 ICOM_VTBL(lpoah) = &oahvt;
80 lpoah->maxSinks = INITIAL_SINKS;
81 lpoah->arrayOfSinks = HeapAlloc(GetProcessHeap(),
83 lpoah->maxSinks * sizeof(IAdviseSink*));
85 for (index = 0; index < lpoah->maxSinks; index++)
86 lpoah->arrayOfSinks[index]=0;
88 TRACE("returning %p\n", lpoah);
89 return (LPOLEADVISEHOLDER)lpoah;
92 /**************************************************************************
93 * OleAdviseHolderImpl_Destructor
95 static void OleAdviseHolderImpl_Destructor(
96 OleAdviseHolderImpl* ptrToDestroy)
99 TRACE("%p\n", ptrToDestroy);
101 for (index = 0; index < ptrToDestroy->maxSinks; index++)
103 if (ptrToDestroy->arrayOfSinks[index]!=0)
105 IAdviseSink_Release(ptrToDestroy->arrayOfSinks[index]);
106 ptrToDestroy->arrayOfSinks[index] = NULL;
110 HeapFree(GetProcessHeap(),
112 ptrToDestroy->arrayOfSinks);
115 HeapFree(GetProcessHeap(),
120 /**************************************************************************
121 * OleAdviseHolderImpl_QueryInterface
123 static HRESULT WINAPI OleAdviseHolderImpl_QueryInterface(
124 LPOLEADVISEHOLDER iface,
128 ICOM_THIS(OleAdviseHolderImpl, iface);
129 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObj);
138 if (IsEqualIID(riid, &IID_IUnknown))
143 else if(IsEqualIID(riid, &IID_IOleAdviseHolder))
145 /* IOleAdviseHolder */
146 *ppvObj = (IOleAdviseHolder*) This;
150 return E_NOINTERFACE;
153 * A successful QI always increments the reference count.
155 IUnknown_AddRef((IUnknown*)*ppvObj);
160 /******************************************************************************
161 * OleAdviseHolderImpl_AddRef
163 static ULONG WINAPI OleAdviseHolderImpl_AddRef(
164 LPOLEADVISEHOLDER iface)
166 ICOM_THIS(OleAdviseHolderImpl, iface);
167 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
168 return ++(This->ref);
171 /******************************************************************************
172 * OleAdviseHolderImpl_Release
174 static ULONG WINAPI OleAdviseHolderImpl_Release(
175 LPOLEADVISEHOLDER iface)
177 ICOM_THIS(OleAdviseHolderImpl, iface);
178 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
183 OleAdviseHolderImpl_Destructor(This);
191 /******************************************************************************
192 * OleAdviseHolderImpl_Advise
194 static HRESULT WINAPI OleAdviseHolderImpl_Advise(
195 LPOLEADVISEHOLDER iface,
196 IAdviseSink* pAdvise,
197 DWORD* pdwConnection)
201 ICOM_THIS(OleAdviseHolderImpl, iface);
203 TRACE("(%p)->(%p, %p)\n", This, pAdvise, pdwConnection);
208 if (pdwConnection==NULL)
214 * Find a free spot in the array.
216 for (index = 0; index < This->maxSinks; index++)
218 if (This->arrayOfSinks[index]==NULL)
223 * If the array is full, we need to grow it.
225 if (index == This->maxSinks)
229 This->maxSinks+=INITIAL_SINKS;
231 This->arrayOfSinks = HeapReAlloc(GetProcessHeap(),
234 This->maxSinks*sizeof(IAdviseSink*));
236 for (i=index;i < This->maxSinks; i++)
237 This->arrayOfSinks[i]=0;
243 This->arrayOfSinks[index] = pAdvise;
245 if (This->arrayOfSinks[index]!=NULL)
246 IAdviseSink_AddRef(This->arrayOfSinks[index]);
249 * Return the index as the cookie.
250 * Since 0 is not a valid cookie, we will increment by
251 * 1 the index in the table.
253 *pdwConnection = index+1;
258 /******************************************************************************
259 * OleAdviseHolderImpl_Unadvise
261 static HRESULT WINAPI OleAdviseHolderImpl_Unadvise(
262 LPOLEADVISEHOLDER iface,
265 ICOM_THIS(OleAdviseHolderImpl, iface);
267 TRACE("(%p)->(%lu)\n", This, dwConnection);
270 * So we don't return 0 as a cookie, the index was
271 * incremented by 1 in OleAdviseHolderImpl_Advise
272 * we have to compensate.
277 * Check for invalid cookies.
279 if ( (dwConnection < 0) ||
280 (dwConnection >= This->maxSinks) )
281 return OLE_E_NOCONNECTION;
283 if (This->arrayOfSinks[dwConnection] == NULL)
284 return OLE_E_NOCONNECTION;
287 * Release the sink and mark the spot in the list as free.
289 IAdviseSink_Release(This->arrayOfSinks[dwConnection]);
290 This->arrayOfSinks[dwConnection] = NULL;
295 /******************************************************************************
296 * OleAdviseHolderImpl_EnumAdvise
298 static HRESULT WINAPI
299 OleAdviseHolderImpl_EnumAdvise (LPOLEADVISEHOLDER iface, IEnumSTATDATA **ppenumAdvise)
301 ICOM_THIS(OleAdviseHolderImpl, iface);
302 FIXME("(%p)->(%p)\n", This, ppenumAdvise);
304 *ppenumAdvise = NULL;
309 /******************************************************************************
310 * OleAdviseHolderImpl_SendOnRename
312 static HRESULT WINAPI
313 OleAdviseHolderImpl_SendOnRename (LPOLEADVISEHOLDER iface, IMoniker *pmk)
315 ICOM_THIS(OleAdviseHolderImpl, iface);
316 FIXME("(%p)->(%p)\n", This, pmk);
322 /******************************************************************************
323 * OleAdviseHolderImpl_SendOnSave
325 static HRESULT WINAPI
326 OleAdviseHolderImpl_SendOnSave (LPOLEADVISEHOLDER iface)
328 ICOM_THIS(OleAdviseHolderImpl, iface);
329 FIXME("(%p)\n", This);
334 /******************************************************************************
335 * OleAdviseHolderImpl_SendOnClose
337 static HRESULT WINAPI
338 OleAdviseHolderImpl_SendOnClose (LPOLEADVISEHOLDER iface)
340 ICOM_THIS(OleAdviseHolderImpl, iface);
341 FIXME("(%p)\n", This);
347 /**************************************************************************
348 * DataAdviseHolder Implementation
350 typedef struct DataAdviseConnection {
354 } DataAdviseConnection;
356 typedef struct DataAdviseHolder
358 ICOM_VFIELD(IDataAdviseHolder);
362 DataAdviseConnection* Connections;
365 /**************************************************************************
366 * DataAdviseHolder method prototypes
368 static IDataAdviseHolder* DataAdviseHolder_Constructor();
369 static void DataAdviseHolder_Destructor(DataAdviseHolder* ptrToDestroy);
370 static HRESULT WINAPI DataAdviseHolder_QueryInterface(
371 IDataAdviseHolder* iface,
374 static ULONG WINAPI DataAdviseHolder_AddRef(
375 IDataAdviseHolder* iface);
376 static ULONG WINAPI DataAdviseHolder_Release(
377 IDataAdviseHolder* iface);
378 static HRESULT WINAPI DataAdviseHolder_Advise(
379 IDataAdviseHolder* iface,
380 IDataObject* pDataObject,
383 IAdviseSink* pAdvise,
384 DWORD* pdwConnection);
385 static HRESULT WINAPI DataAdviseHolder_Unadvise(
386 IDataAdviseHolder* iface,
388 static HRESULT WINAPI DataAdviseHolder_EnumAdvise(
389 IDataAdviseHolder* iface,
390 IEnumSTATDATA** ppenumAdvise);
391 static HRESULT WINAPI DataAdviseHolder_SendOnDataChange(
392 IDataAdviseHolder* iface,
393 IDataObject* pDataObject,
397 /**************************************************************************
398 * DataAdviseHolderImpl_VTable
400 static struct ICOM_VTABLE(IDataAdviseHolder) DataAdviseHolderImpl_VTable =
402 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
403 DataAdviseHolder_QueryInterface,
404 DataAdviseHolder_AddRef,
405 DataAdviseHolder_Release,
406 DataAdviseHolder_Advise,
407 DataAdviseHolder_Unadvise,
408 DataAdviseHolder_EnumAdvise,
409 DataAdviseHolder_SendOnDataChange
412 /******************************************************************************
413 * DataAdviseHolder_Constructor
415 static IDataAdviseHolder* DataAdviseHolder_Constructor()
417 DataAdviseHolder* newHolder;
419 newHolder = (DataAdviseHolder*)HeapAlloc(GetProcessHeap(),
421 sizeof(DataAdviseHolder));
423 ICOM_VTBL(newHolder) = &DataAdviseHolderImpl_VTable;
425 newHolder->maxCons = INITIAL_SINKS;
426 newHolder->Connections = HeapAlloc(GetProcessHeap(),
429 sizeof(DataAdviseConnection));
431 TRACE("returning %p\n", newHolder);
432 return (IDataAdviseHolder*)newHolder;
435 /******************************************************************************
436 * DataAdviseHolder_Destructor
438 static void DataAdviseHolder_Destructor(DataAdviseHolder* ptrToDestroy)
441 TRACE("%p\n", ptrToDestroy);
443 for (index = 0; index < ptrToDestroy->maxCons; index++)
445 if (ptrToDestroy->Connections[index].sink != NULL)
447 IAdviseSink_Release(ptrToDestroy->Connections[index].sink);
448 ptrToDestroy->Connections[index].sink = NULL;
452 HeapFree(GetProcessHeap(), 0, ptrToDestroy->Connections);
453 HeapFree(GetProcessHeap(), 0, ptrToDestroy);
456 /************************************************************************
457 * DataAdviseHolder_QueryInterface (IUnknown)
459 * See Windows documentation for more details on IUnknown methods.
461 static HRESULT WINAPI DataAdviseHolder_QueryInterface(
462 IDataAdviseHolder* iface,
466 ICOM_THIS(DataAdviseHolder, iface);
467 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObject);
469 * Perform a sanity check on the parameters.
471 if ( (This==0) || (ppvObject==0) )
475 * Initialize the return parameter.
480 * Compare the riid with the interface IDs implemented by this object.
482 if ( (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0) ||
483 (memcmp(&IID_IDataAdviseHolder, riid, sizeof(IID_IDataAdviseHolder)) == 0) )
489 * Check that we obtained an interface.
493 return E_NOINTERFACE;
497 * Query Interface always increases the reference count by one when it is
500 IUnknown_AddRef((IUnknown*)*ppvObject);
505 /************************************************************************
506 * DataAdviseHolder_AddRef (IUnknown)
508 * See Windows documentation for more details on IUnknown methods.
510 static ULONG WINAPI DataAdviseHolder_AddRef(
511 IDataAdviseHolder* iface)
513 ICOM_THIS(DataAdviseHolder, iface);
514 TRACE("(%p) (ref=%ld)\n", This, This->ref);
520 /************************************************************************
521 * DataAdviseHolder_Release (IUnknown)
523 * See Windows documentation for more details on IUnknown methods.
525 static ULONG WINAPI DataAdviseHolder_Release(
526 IDataAdviseHolder* iface)
528 ICOM_THIS(DataAdviseHolder, iface);
529 TRACE("(%p) (ref=%ld)\n", This, This->ref);
532 * Decrease the reference count on this object.
537 * If the reference count goes down to 0, perform suicide.
541 DataAdviseHolder_Destructor(This);
549 /************************************************************************
550 * DataAdviseHolder_Advise
553 static HRESULT WINAPI DataAdviseHolder_Advise(
554 IDataAdviseHolder* iface,
555 IDataObject* pDataObject,
558 IAdviseSink* pAdvise,
559 DWORD* pdwConnection)
563 ICOM_THIS(DataAdviseHolder, iface);
565 TRACE("(%p)->(%p, %p, %08lx, %p, %p)\n", This, pDataObject, pFetc, advf,
566 pAdvise, pdwConnection);
570 if (pdwConnection==NULL)
576 * Find a free spot in the array.
578 for (index = 0; index < This->maxCons; index++)
580 if (This->Connections[index].sink == NULL)
585 * If the array is full, we need to grow it.
587 if (index == This->maxCons)
589 This->maxCons+=INITIAL_SINKS;
590 This->Connections = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
592 This->maxCons*sizeof(DataAdviseConnection));
597 This->Connections[index].sink = pAdvise;
598 memcpy(&(This->Connections[index].fmat), pFetc, sizeof(FORMATETC));
599 This->Connections[index].advf = advf;
601 if (This->Connections[index].sink != NULL) {
602 IAdviseSink_AddRef(This->Connections[index].sink);
603 if(advf & ADVF_PRIMEFIRST) {
604 DataAdviseHolder_SendOnDataChange(iface, pDataObject, 0, advf);
608 * Return the index as the cookie.
609 * Since 0 is not a valid cookie, we will increment by
610 * 1 the index in the table.
612 *pdwConnection = index+1;
617 /******************************************************************************
618 * DataAdviseHolder_Unadvise
620 static HRESULT WINAPI DataAdviseHolder_Unadvise(
621 IDataAdviseHolder* iface,
624 ICOM_THIS(DataAdviseHolder, iface);
626 TRACE("(%p)->(%lu)\n", This, dwConnection);
629 * So we don't return 0 as a cookie, the index was
630 * incremented by 1 in OleAdviseHolderImpl_Advise
631 * we have to compensate.
636 * Check for invalid cookies.
638 if ( (dwConnection < 0) ||
639 (dwConnection >= This->maxCons) )
640 return OLE_E_NOCONNECTION;
642 if (This->Connections[dwConnection].sink == NULL)
643 return OLE_E_NOCONNECTION;
646 * Release the sink and mark the spot in the list as free.
648 IAdviseSink_Release(This->Connections[dwConnection].sink);
649 memset(&(This->Connections[dwConnection]), 0, sizeof(DataAdviseConnection));
653 static HRESULT WINAPI DataAdviseHolder_EnumAdvise(
654 IDataAdviseHolder* iface,
655 IEnumSTATDATA** ppenumAdvise)
657 ICOM_THIS(DataAdviseHolder, iface);
659 FIXME("(%p)->(%p)\n", This, ppenumAdvise);
663 /******************************************************************************
664 * DataAdviseHolder_SendOnDataChange
666 static HRESULT WINAPI DataAdviseHolder_SendOnDataChange(
667 IDataAdviseHolder* iface,
668 IDataObject* pDataObject,
672 ICOM_THIS(DataAdviseHolder, iface);
677 TRACE("(%p)->(%p,%08lx,%08lx)\n", This, pDataObject, dwReserved, advf);
679 for(index = 0; index < This->maxCons; index++) {
680 if(This->Connections[index].sink != NULL) {
681 if(!(This->Connections[index].advf & ADVF_NODATA)) {
682 TRACE("Calling IDataObject_GetData\n");
683 res = IDataObject_GetData(pDataObject,
684 &(This->Connections[index].fmat),
686 TRACE("returns %08lx\n", res);
688 TRACE("Calling IAdviseSink_OnDataChange\n");
689 IAdviseSink_OnDataChange(This->Connections[index].sink,
690 &(This->Connections[index].fmat),
692 TRACE("Done IAdviseSink_OnDataChange\n");
693 if(This->Connections[index].advf & ADVF_ONLYONCE) {
694 TRACE("Removing connection\n");
695 DataAdviseHolder_Unadvise(iface, index+1);
702 /***********************************************************************
706 /***********************************************************************
707 * CreateOleAdviseHolder [OLE32.59]
709 HRESULT WINAPI CreateOleAdviseHolder(
710 LPOLEADVISEHOLDER *ppOAHolder)
712 TRACE("(%p)\n", ppOAHolder);
717 if (ppOAHolder==NULL)
720 *ppOAHolder = OleAdviseHolderImpl_Constructor ();
722 if (*ppOAHolder != NULL)
725 return E_OUTOFMEMORY;
728 /******************************************************************************
729 * CreateDataAdviseHolder [OLE32.53]
731 HRESULT WINAPI CreateDataAdviseHolder(
732 LPDATAADVISEHOLDER* ppDAHolder)
734 TRACE("(%p)\n", ppDAHolder);
739 if (ppDAHolder==NULL)
742 *ppDAHolder = DataAdviseHolder_Constructor();
744 if (*ppDAHolder != NULL)
747 return E_OUTOFMEMORY;