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
;