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
>= This
->maxSinks
)
292 return OLE_E_NOCONNECTION
;
294 if (This
->arrayOfSinks
[dwConnection
] == NULL
)
295 return OLE_E_NOCONNECTION
;
298 * Release the sink and mark the spot in the list as free.
300 IAdviseSink_Release(This
->arrayOfSinks
[dwConnection
]);
301 This
->arrayOfSinks
[dwConnection
] = NULL
;
306 /******************************************************************************
307 * OleAdviseHolderImpl_EnumAdvise
309 static HRESULT WINAPI
310 OleAdviseHolderImpl_EnumAdvise (LPOLEADVISEHOLDER iface
, IEnumSTATDATA
**ppenumAdvise
)
312 ICOM_THIS(OleAdviseHolderImpl
, iface
);
313 FIXME("(%p)->(%p)\n", This
, ppenumAdvise
);
315 *ppenumAdvise
= NULL
;
320 /******************************************************************************
321 * OleAdviseHolderImpl_SendOnRename
323 static HRESULT WINAPI
324 OleAdviseHolderImpl_SendOnRename (LPOLEADVISEHOLDER iface
, IMoniker
*pmk
)
326 ICOM_THIS(OleAdviseHolderImpl
, iface
);
327 FIXME("(%p)->(%p)\n", This
, pmk
);
333 /******************************************************************************
334 * OleAdviseHolderImpl_SendOnSave
336 static HRESULT WINAPI
337 OleAdviseHolderImpl_SendOnSave (LPOLEADVISEHOLDER iface
)
339 ICOM_THIS(OleAdviseHolderImpl
, iface
);
340 FIXME("(%p)\n", This
);
345 /******************************************************************************
346 * OleAdviseHolderImpl_SendOnClose
348 static HRESULT WINAPI
349 OleAdviseHolderImpl_SendOnClose (LPOLEADVISEHOLDER iface
)
351 ICOM_THIS(OleAdviseHolderImpl
, iface
);
352 FIXME("(%p)\n", This
);
358 /**************************************************************************
359 * DataAdviseHolder Implementation
361 typedef struct DataAdviseConnection
{
365 } DataAdviseConnection
;
367 typedef struct DataAdviseHolder
369 ICOM_VFIELD(IDataAdviseHolder
);
373 DataAdviseConnection
* Connections
;
376 /**************************************************************************
377 * DataAdviseHolder method prototypes
379 static IDataAdviseHolder
* DataAdviseHolder_Constructor();
380 static void DataAdviseHolder_Destructor(DataAdviseHolder
* ptrToDestroy
);
381 static HRESULT WINAPI
DataAdviseHolder_QueryInterface(
382 IDataAdviseHolder
* iface
,
385 static ULONG WINAPI
DataAdviseHolder_AddRef(
386 IDataAdviseHolder
* iface
);
387 static ULONG WINAPI
DataAdviseHolder_Release(
388 IDataAdviseHolder
* iface
);
389 static HRESULT WINAPI
DataAdviseHolder_Advise(
390 IDataAdviseHolder
* iface
,
391 IDataObject
* pDataObject
,
394 IAdviseSink
* pAdvise
,
395 DWORD
* pdwConnection
);
396 static HRESULT WINAPI
DataAdviseHolder_Unadvise(
397 IDataAdviseHolder
* iface
,
399 static HRESULT WINAPI
DataAdviseHolder_EnumAdvise(
400 IDataAdviseHolder
* iface
,
401 IEnumSTATDATA
** ppenumAdvise
);
402 static HRESULT WINAPI
DataAdviseHolder_SendOnDataChange(
403 IDataAdviseHolder
* iface
,
404 IDataObject
* pDataObject
,
408 /**************************************************************************
409 * DataAdviseHolderImpl_VTable
411 static struct ICOM_VTABLE(IDataAdviseHolder
) DataAdviseHolderImpl_VTable
=
413 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
414 DataAdviseHolder_QueryInterface
,
415 DataAdviseHolder_AddRef
,
416 DataAdviseHolder_Release
,
417 DataAdviseHolder_Advise
,
418 DataAdviseHolder_Unadvise
,
419 DataAdviseHolder_EnumAdvise
,
420 DataAdviseHolder_SendOnDataChange
423 /******************************************************************************
424 * DataAdviseHolder_Constructor
426 static IDataAdviseHolder
* DataAdviseHolder_Constructor()
428 DataAdviseHolder
* newHolder
;
430 newHolder
= (DataAdviseHolder
*)HeapAlloc(GetProcessHeap(),
432 sizeof(DataAdviseHolder
));
434 ICOM_VTBL(newHolder
) = &DataAdviseHolderImpl_VTable
;
436 newHolder
->maxCons
= INITIAL_SINKS
;
437 newHolder
->Connections
= HeapAlloc(GetProcessHeap(),
440 sizeof(DataAdviseConnection
));
442 TRACE("returning %p\n", newHolder
);
443 return (IDataAdviseHolder
*)newHolder
;
446 /******************************************************************************
447 * DataAdviseHolder_Destructor
449 static void DataAdviseHolder_Destructor(DataAdviseHolder
* ptrToDestroy
)
452 TRACE("%p\n", ptrToDestroy
);
454 for (index
= 0; index
< ptrToDestroy
->maxCons
; index
++)
456 if (ptrToDestroy
->Connections
[index
].sink
!= NULL
)
458 IAdviseSink_Release(ptrToDestroy
->Connections
[index
].sink
);
459 ptrToDestroy
->Connections
[index
].sink
= NULL
;
463 HeapFree(GetProcessHeap(), 0, ptrToDestroy
->Connections
);
464 HeapFree(GetProcessHeap(), 0, ptrToDestroy
);
467 /************************************************************************
468 * DataAdviseHolder_QueryInterface (IUnknown)
470 * See Windows documentation for more details on IUnknown methods.
472 static HRESULT WINAPI
DataAdviseHolder_QueryInterface(
473 IDataAdviseHolder
* iface
,
477 ICOM_THIS(DataAdviseHolder
, iface
);
478 TRACE("(%p)->(%s,%p)\n",This
,debugstr_guid(riid
),ppvObject
);
480 * Perform a sanity check on the parameters.
482 if ( (This
==0) || (ppvObject
==0) )
486 * Initialize the return parameter.
491 * Compare the riid with the interface IDs implemented by this object.
493 if ( (memcmp(&IID_IUnknown
, riid
, sizeof(IID_IUnknown
)) == 0) ||
494 (memcmp(&IID_IDataAdviseHolder
, riid
, sizeof(IID_IDataAdviseHolder
)) == 0) )
500 * Check that we obtained an interface.
504 return E_NOINTERFACE
;
508 * Query Interface always increases the reference count by one when it is
511 IUnknown_AddRef((IUnknown
*)*ppvObject
);
516 /************************************************************************
517 * DataAdviseHolder_AddRef (IUnknown)
519 * See Windows documentation for more details on IUnknown methods.
521 static ULONG WINAPI
DataAdviseHolder_AddRef(
522 IDataAdviseHolder
* iface
)
524 ICOM_THIS(DataAdviseHolder
, iface
);
525 TRACE("(%p) (ref=%ld)\n", This
, This
->ref
);
531 /************************************************************************
532 * DataAdviseHolder_Release (IUnknown)
534 * See Windows documentation for more details on IUnknown methods.
536 static ULONG WINAPI
DataAdviseHolder_Release(
537 IDataAdviseHolder
* iface
)
539 ICOM_THIS(DataAdviseHolder
, iface
);
540 TRACE("(%p) (ref=%ld)\n", This
, This
->ref
);
543 * Decrease the reference count on this object.
548 * If the reference count goes down to 0, perform suicide.
552 DataAdviseHolder_Destructor(This
);
560 /************************************************************************
561 * DataAdviseHolder_Advise
564 static HRESULT WINAPI
DataAdviseHolder_Advise(
565 IDataAdviseHolder
* iface
,
566 IDataObject
* pDataObject
,
569 IAdviseSink
* pAdvise
,
570 DWORD
* pdwConnection
)
574 ICOM_THIS(DataAdviseHolder
, iface
);
576 TRACE("(%p)->(%p, %p, %08lx, %p, %p)\n", This
, pDataObject
, pFetc
, advf
,
577 pAdvise
, pdwConnection
);
581 if (pdwConnection
==NULL
)
587 * Find a free spot in the array.
589 for (index
= 0; index
< This
->maxCons
; index
++)
591 if (This
->Connections
[index
].sink
== NULL
)
596 * If the array is full, we need to grow it.
598 if (index
== This
->maxCons
)
600 This
->maxCons
+=INITIAL_SINKS
;
601 This
->Connections
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
603 This
->maxCons
*sizeof(DataAdviseConnection
));
608 This
->Connections
[index
].sink
= pAdvise
;
609 memcpy(&(This
->Connections
[index
].fmat
), pFetc
, sizeof(FORMATETC
));
610 This
->Connections
[index
].advf
= advf
;
612 if (This
->Connections
[index
].sink
!= NULL
) {
613 IAdviseSink_AddRef(This
->Connections
[index
].sink
);
614 if(advf
& ADVF_PRIMEFIRST
) {
615 DataAdviseHolder_SendOnDataChange(iface
, pDataObject
, 0, advf
);
619 * Return the index as the cookie.
620 * Since 0 is not a valid cookie, we will increment by
621 * 1 the index in the table.
623 *pdwConnection
= index
+1;
628 /******************************************************************************
629 * DataAdviseHolder_Unadvise
631 static HRESULT WINAPI
DataAdviseHolder_Unadvise(
632 IDataAdviseHolder
* iface
,
635 ICOM_THIS(DataAdviseHolder
, iface
);
637 TRACE("(%p)->(%lu)\n", This
, dwConnection
);
640 * So we don't return 0 as a cookie, the index was
641 * incremented by 1 in OleAdviseHolderImpl_Advise
642 * we have to compensate.
647 * Check for invalid cookies.
649 if (dwConnection
>= This
->maxCons
)
650 return OLE_E_NOCONNECTION
;
652 if (This
->Connections
[dwConnection
].sink
== NULL
)
653 return OLE_E_NOCONNECTION
;
656 * Release the sink and mark the spot in the list as free.
658 IAdviseSink_Release(This
->Connections
[dwConnection
].sink
);
659 memset(&(This
->Connections
[dwConnection
]), 0, sizeof(DataAdviseConnection
));
663 static HRESULT WINAPI
DataAdviseHolder_EnumAdvise(
664 IDataAdviseHolder
* iface
,
665 IEnumSTATDATA
** ppenumAdvise
)
667 ICOM_THIS(DataAdviseHolder
, iface
);
669 FIXME("(%p)->(%p)\n", This
, ppenumAdvise
);
673 /******************************************************************************
674 * DataAdviseHolder_SendOnDataChange
676 static HRESULT WINAPI
DataAdviseHolder_SendOnDataChange(
677 IDataAdviseHolder
* iface
,
678 IDataObject
* pDataObject
,
682 ICOM_THIS(DataAdviseHolder
, iface
);
687 TRACE("(%p)->(%p,%08lx,%08lx)\n", This
, pDataObject
, dwReserved
, advf
);
689 for(index
= 0; index
< This
->maxCons
; index
++) {
690 if(This
->Connections
[index
].sink
!= NULL
) {
691 if(!(This
->Connections
[index
].advf
& ADVF_NODATA
)) {
692 TRACE("Calling IDataObject_GetData\n");
693 res
= IDataObject_GetData(pDataObject
,
694 &(This
->Connections
[index
].fmat
),
696 TRACE("returns %08lx\n", res
);
698 TRACE("Calling IAdviseSink_OnDataChange\n");
699 IAdviseSink_OnDataChange(This
->Connections
[index
].sink
,
700 &(This
->Connections
[index
].fmat
),
702 TRACE("Done IAdviseSink_OnDataChange\n");
703 if(This
->Connections
[index
].advf
& ADVF_ONLYONCE
) {
704 TRACE("Removing connection\n");
705 DataAdviseHolder_Unadvise(iface
, index
+1);
712 /***********************************************************************
716 /***********************************************************************
717 * CreateOleAdviseHolder [OLE32.59]
719 HRESULT WINAPI
CreateOleAdviseHolder(
720 LPOLEADVISEHOLDER
*ppOAHolder
)
722 TRACE("(%p)\n", ppOAHolder
);
727 if (ppOAHolder
==NULL
)
730 *ppOAHolder
= OleAdviseHolderImpl_Constructor ();
732 if (*ppOAHolder
!= NULL
)
735 return E_OUTOFMEMORY
;
738 /******************************************************************************
739 * CreateDataAdviseHolder [OLE32.53]
741 HRESULT WINAPI
CreateDataAdviseHolder(
742 LPDATAADVISEHOLDER
* ppDAHolder
)
744 TRACE("(%p)\n", ppDAHolder
);
749 if (ppDAHolder
==NULL
)
752 *ppDAHolder
= DataAdviseHolder_Constructor();
754 if (*ppDAHolder
!= NULL
)
757 return E_OUTOFMEMORY
;