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
29 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
34 #define INITIAL_SINKS 10
36 /**************************************************************************
37 * OleAdviseHolderImpl Implementation
39 typedef struct OleAdviseHolderImpl
41 ICOM_VFIELD(IOleAdviseHolder
);
46 IAdviseSink
** arrayOfSinks
;
48 } OleAdviseHolderImpl
;
50 static LPOLEADVISEHOLDER
OleAdviseHolderImpl_Constructor();
51 static void OleAdviseHolderImpl_Destructor(OleAdviseHolderImpl
* ptrToDestroy
);
52 static HRESULT WINAPI
OleAdviseHolderImpl_QueryInterface(LPOLEADVISEHOLDER
,REFIID
,LPVOID
*);
53 static ULONG WINAPI
OleAdviseHolderImpl_AddRef(LPOLEADVISEHOLDER
);
54 static ULONG WINAPI
OleAdviseHolderImpl_Release(LPOLEADVISEHOLDER
);
55 static HRESULT WINAPI
OleAdviseHolderImpl_Advise(LPOLEADVISEHOLDER
, IAdviseSink
*, DWORD
*);
56 static HRESULT WINAPI
OleAdviseHolderImpl_Unadvise (LPOLEADVISEHOLDER
, DWORD
);
57 static HRESULT WINAPI
OleAdviseHolderImpl_EnumAdvise (LPOLEADVISEHOLDER
, IEnumSTATDATA
**);
58 static HRESULT WINAPI
OleAdviseHolderImpl_SendOnRename (LPOLEADVISEHOLDER
, IMoniker
*);
59 static HRESULT WINAPI
OleAdviseHolderImpl_SendOnSave (LPOLEADVISEHOLDER
);
60 static HRESULT WINAPI
OleAdviseHolderImpl_SendOnClose (LPOLEADVISEHOLDER
);
63 /**************************************************************************
64 * OleAdviseHolderImpl_VTable
66 static struct ICOM_VTABLE(IOleAdviseHolder
) oahvt
=
68 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
69 OleAdviseHolderImpl_QueryInterface
,
70 OleAdviseHolderImpl_AddRef
,
71 OleAdviseHolderImpl_Release
,
72 OleAdviseHolderImpl_Advise
,
73 OleAdviseHolderImpl_Unadvise
,
74 OleAdviseHolderImpl_EnumAdvise
,
75 OleAdviseHolderImpl_SendOnRename
,
76 OleAdviseHolderImpl_SendOnSave
,
77 OleAdviseHolderImpl_SendOnClose
80 /**************************************************************************
81 * OleAdviseHolderImpl_Constructor
84 static LPOLEADVISEHOLDER
OleAdviseHolderImpl_Constructor()
86 OleAdviseHolderImpl
* lpoah
;
89 lpoah
= (OleAdviseHolderImpl
*)HeapAlloc(GetProcessHeap(),
91 sizeof(OleAdviseHolderImpl
));
93 lpoah
->lpVtbl
= &oahvt
;
95 lpoah
->maxSinks
= INITIAL_SINKS
;
96 lpoah
->arrayOfSinks
= HeapAlloc(GetProcessHeap(),
98 lpoah
->maxSinks
* sizeof(IAdviseSink
*));
100 for (index
= 0; index
< lpoah
->maxSinks
; index
++)
101 lpoah
->arrayOfSinks
[index
]=0;
103 TRACE("returning %p\n", lpoah
);
104 return (LPOLEADVISEHOLDER
)lpoah
;
107 /**************************************************************************
108 * OleAdviseHolderImpl_Destructor
110 static void OleAdviseHolderImpl_Destructor(
111 OleAdviseHolderImpl
* ptrToDestroy
)
114 TRACE("%p\n", ptrToDestroy
);
116 for (index
= 0; index
< ptrToDestroy
->maxSinks
; index
++)
118 if (ptrToDestroy
->arrayOfSinks
[index
]!=0)
120 IAdviseSink_Release(ptrToDestroy
->arrayOfSinks
[index
]);
121 ptrToDestroy
->arrayOfSinks
[index
] = NULL
;
125 HeapFree(GetProcessHeap(),
127 ptrToDestroy
->arrayOfSinks
);
130 HeapFree(GetProcessHeap(),
135 /**************************************************************************
136 * OleAdviseHolderImpl_QueryInterface
138 static HRESULT WINAPI
OleAdviseHolderImpl_QueryInterface(
139 LPOLEADVISEHOLDER iface
,
143 ICOM_THIS(OleAdviseHolderImpl
, iface
);
144 TRACE("(%p)->(%s,%p)\n",This
,debugstr_guid(riid
),ppvObj
);
153 if (IsEqualIID(riid
, &IID_IUnknown
))
158 else if(IsEqualIID(riid
, &IID_IOleAdviseHolder
))
160 /* IOleAdviseHolder */
161 *ppvObj
= (IOleAdviseHolder
*) This
;
165 return E_NOINTERFACE
;
168 * A successful QI always increments the reference count.
170 IUnknown_AddRef((IUnknown
*)*ppvObj
);
175 /******************************************************************************
176 * OleAdviseHolderImpl_AddRef
178 static ULONG WINAPI
OleAdviseHolderImpl_AddRef(
179 LPOLEADVISEHOLDER iface
)
181 ICOM_THIS(OleAdviseHolderImpl
, iface
);
182 TRACE("(%p)->(ref=%ld)\n", This
, This
->ref
);
183 return ++(This
->ref
);
186 /******************************************************************************
187 * OleAdviseHolderImpl_Release
189 static ULONG WINAPI
OleAdviseHolderImpl_Release(
190 LPOLEADVISEHOLDER iface
)
192 ICOM_THIS(OleAdviseHolderImpl
, iface
);
193 TRACE("(%p)->(ref=%ld)\n", This
, This
->ref
);
198 OleAdviseHolderImpl_Destructor(This
);
206 /******************************************************************************
207 * OleAdviseHolderImpl_Advise
209 static HRESULT WINAPI
OleAdviseHolderImpl_Advise(
210 LPOLEADVISEHOLDER iface
,
211 IAdviseSink
* pAdvise
,
212 DWORD
* pdwConnection
)
216 ICOM_THIS(OleAdviseHolderImpl
, iface
);
218 TRACE("(%p)->(%p, %p)\n", This
, pAdvise
, pdwConnection
);
223 if (pdwConnection
==NULL
)
229 * Find a free spot in the array.
231 for (index
= 0; index
< This
->maxSinks
; index
++)
233 if (This
->arrayOfSinks
[index
]==NULL
)
238 * If the array is full, we need to grow it.
240 if (index
== This
->maxSinks
)
244 This
->maxSinks
+=INITIAL_SINKS
;
246 This
->arrayOfSinks
= HeapReAlloc(GetProcessHeap(),
249 This
->maxSinks
*sizeof(IAdviseSink
*));
251 for (i
=index
;i
< This
->maxSinks
; i
++)
252 This
->arrayOfSinks
[i
]=0;
258 This
->arrayOfSinks
[index
] = pAdvise
;
260 if (This
->arrayOfSinks
[index
]!=NULL
)
261 IAdviseSink_AddRef(This
->arrayOfSinks
[index
]);
264 * Return the index as the cookie.
265 * Since 0 is not a valid cookie, we will increment by
266 * 1 the index in the table.
268 *pdwConnection
= index
+1;
273 /******************************************************************************
274 * OleAdviseHolderImpl_Unadvise
276 static HRESULT WINAPI
OleAdviseHolderImpl_Unadvise(
277 LPOLEADVISEHOLDER iface
,
280 ICOM_THIS(OleAdviseHolderImpl
, iface
);
282 TRACE("(%p)->(%lu)\n", This
, dwConnection
);
285 * So we don't return 0 as a cookie, the index was
286 * incremented by 1 in OleAdviseHolderImpl_Advise
287 * we have to compensate.
292 * Check for invalid cookies.
294 if (dwConnection
>= This
->maxSinks
)
295 return OLE_E_NOCONNECTION
;
297 if (This
->arrayOfSinks
[dwConnection
] == NULL
)
298 return OLE_E_NOCONNECTION
;
301 * Release the sink and mark the spot in the list as free.
303 IAdviseSink_Release(This
->arrayOfSinks
[dwConnection
]);
304 This
->arrayOfSinks
[dwConnection
] = NULL
;
309 /******************************************************************************
310 * OleAdviseHolderImpl_EnumAdvise
312 static HRESULT WINAPI
313 OleAdviseHolderImpl_EnumAdvise (LPOLEADVISEHOLDER iface
, IEnumSTATDATA
**ppenumAdvise
)
315 ICOM_THIS(OleAdviseHolderImpl
, iface
);
316 FIXME("(%p)->(%p)\n", This
, ppenumAdvise
);
318 *ppenumAdvise
= NULL
;
323 /******************************************************************************
324 * OleAdviseHolderImpl_SendOnRename
326 static HRESULT WINAPI
327 OleAdviseHolderImpl_SendOnRename (LPOLEADVISEHOLDER iface
, IMoniker
*pmk
)
329 ICOM_THIS(OleAdviseHolderImpl
, iface
);
330 FIXME("(%p)->(%p)\n", This
, pmk
);
336 /******************************************************************************
337 * OleAdviseHolderImpl_SendOnSave
339 static HRESULT WINAPI
340 OleAdviseHolderImpl_SendOnSave (LPOLEADVISEHOLDER iface
)
342 ICOM_THIS(OleAdviseHolderImpl
, iface
);
343 FIXME("(%p)\n", This
);
348 /******************************************************************************
349 * OleAdviseHolderImpl_SendOnClose
351 static HRESULT WINAPI
352 OleAdviseHolderImpl_SendOnClose (LPOLEADVISEHOLDER iface
)
354 ICOM_THIS(OleAdviseHolderImpl
, iface
);
355 FIXME("(%p)\n", This
);
361 /**************************************************************************
362 * DataAdviseHolder Implementation
364 typedef struct DataAdviseConnection
{
368 } DataAdviseConnection
;
370 typedef struct DataAdviseHolder
372 ICOM_VFIELD(IDataAdviseHolder
);
376 DataAdviseConnection
* Connections
;
379 /**************************************************************************
380 * DataAdviseHolder method prototypes
382 static IDataAdviseHolder
* DataAdviseHolder_Constructor();
383 static void DataAdviseHolder_Destructor(DataAdviseHolder
* ptrToDestroy
);
384 static HRESULT WINAPI
DataAdviseHolder_QueryInterface(
385 IDataAdviseHolder
* iface
,
388 static ULONG WINAPI
DataAdviseHolder_AddRef(
389 IDataAdviseHolder
* iface
);
390 static ULONG WINAPI
DataAdviseHolder_Release(
391 IDataAdviseHolder
* iface
);
392 static HRESULT WINAPI
DataAdviseHolder_Advise(
393 IDataAdviseHolder
* iface
,
394 IDataObject
* pDataObject
,
397 IAdviseSink
* pAdvise
,
398 DWORD
* pdwConnection
);
399 static HRESULT WINAPI
DataAdviseHolder_Unadvise(
400 IDataAdviseHolder
* iface
,
402 static HRESULT WINAPI
DataAdviseHolder_EnumAdvise(
403 IDataAdviseHolder
* iface
,
404 IEnumSTATDATA
** ppenumAdvise
);
405 static HRESULT WINAPI
DataAdviseHolder_SendOnDataChange(
406 IDataAdviseHolder
* iface
,
407 IDataObject
* pDataObject
,
411 /**************************************************************************
412 * DataAdviseHolderImpl_VTable
414 static struct ICOM_VTABLE(IDataAdviseHolder
) DataAdviseHolderImpl_VTable
=
416 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
417 DataAdviseHolder_QueryInterface
,
418 DataAdviseHolder_AddRef
,
419 DataAdviseHolder_Release
,
420 DataAdviseHolder_Advise
,
421 DataAdviseHolder_Unadvise
,
422 DataAdviseHolder_EnumAdvise
,
423 DataAdviseHolder_SendOnDataChange
426 /******************************************************************************
427 * DataAdviseHolder_Constructor
429 static IDataAdviseHolder
* DataAdviseHolder_Constructor()
431 DataAdviseHolder
* newHolder
;
433 newHolder
= (DataAdviseHolder
*)HeapAlloc(GetProcessHeap(),
435 sizeof(DataAdviseHolder
));
437 newHolder
->lpVtbl
= &DataAdviseHolderImpl_VTable
;
439 newHolder
->maxCons
= INITIAL_SINKS
;
440 newHolder
->Connections
= HeapAlloc(GetProcessHeap(),
443 sizeof(DataAdviseConnection
));
445 TRACE("returning %p\n", newHolder
);
446 return (IDataAdviseHolder
*)newHolder
;
449 /******************************************************************************
450 * DataAdviseHolder_Destructor
452 static void DataAdviseHolder_Destructor(DataAdviseHolder
* ptrToDestroy
)
455 TRACE("%p\n", ptrToDestroy
);
457 for (index
= 0; index
< ptrToDestroy
->maxCons
; index
++)
459 if (ptrToDestroy
->Connections
[index
].sink
!= NULL
)
461 IAdviseSink_Release(ptrToDestroy
->Connections
[index
].sink
);
462 ptrToDestroy
->Connections
[index
].sink
= NULL
;
466 HeapFree(GetProcessHeap(), 0, ptrToDestroy
->Connections
);
467 HeapFree(GetProcessHeap(), 0, ptrToDestroy
);
470 /************************************************************************
471 * DataAdviseHolder_QueryInterface (IUnknown)
473 * See Windows documentation for more details on IUnknown methods.
475 static HRESULT WINAPI
DataAdviseHolder_QueryInterface(
476 IDataAdviseHolder
* iface
,
480 ICOM_THIS(DataAdviseHolder
, iface
);
481 TRACE("(%p)->(%s,%p)\n",This
,debugstr_guid(riid
),ppvObject
);
483 * Perform a sanity check on the parameters.
485 if ( (This
==0) || (ppvObject
==0) )
489 * Initialize the return parameter.
494 * Compare the riid with the interface IDs implemented by this object.
496 if ( (memcmp(&IID_IUnknown
, riid
, sizeof(IID_IUnknown
)) == 0) ||
497 (memcmp(&IID_IDataAdviseHolder
, riid
, sizeof(IID_IDataAdviseHolder
)) == 0) )
503 * Check that we obtained an interface.
507 return E_NOINTERFACE
;
511 * Query Interface always increases the reference count by one when it is
514 IUnknown_AddRef((IUnknown
*)*ppvObject
);
519 /************************************************************************
520 * DataAdviseHolder_AddRef (IUnknown)
522 * See Windows documentation for more details on IUnknown methods.
524 static ULONG WINAPI
DataAdviseHolder_AddRef(
525 IDataAdviseHolder
* iface
)
527 ICOM_THIS(DataAdviseHolder
, iface
);
528 TRACE("(%p) (ref=%ld)\n", This
, This
->ref
);
534 /************************************************************************
535 * DataAdviseHolder_Release (IUnknown)
537 * See Windows documentation for more details on IUnknown methods.
539 static ULONG WINAPI
DataAdviseHolder_Release(
540 IDataAdviseHolder
* iface
)
542 ICOM_THIS(DataAdviseHolder
, iface
);
543 TRACE("(%p) (ref=%ld)\n", This
, This
->ref
);
546 * Decrease the reference count on this object.
551 * If the reference count goes down to 0, perform suicide.
555 DataAdviseHolder_Destructor(This
);
563 /************************************************************************
564 * DataAdviseHolder_Advise
567 static HRESULT WINAPI
DataAdviseHolder_Advise(
568 IDataAdviseHolder
* iface
,
569 IDataObject
* pDataObject
,
572 IAdviseSink
* pAdvise
,
573 DWORD
* pdwConnection
)
577 ICOM_THIS(DataAdviseHolder
, iface
);
579 TRACE("(%p)->(%p, %p, %08lx, %p, %p)\n", This
, pDataObject
, pFetc
, advf
,
580 pAdvise
, pdwConnection
);
584 if (pdwConnection
==NULL
)
590 * Find a free spot in the array.
592 for (index
= 0; index
< This
->maxCons
; index
++)
594 if (This
->Connections
[index
].sink
== NULL
)
599 * If the array is full, we need to grow it.
601 if (index
== This
->maxCons
)
603 This
->maxCons
+=INITIAL_SINKS
;
604 This
->Connections
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
606 This
->maxCons
*sizeof(DataAdviseConnection
));
611 This
->Connections
[index
].sink
= pAdvise
;
612 memcpy(&(This
->Connections
[index
].fmat
), pFetc
, sizeof(FORMATETC
));
613 This
->Connections
[index
].advf
= advf
;
615 if (This
->Connections
[index
].sink
!= NULL
) {
616 IAdviseSink_AddRef(This
->Connections
[index
].sink
);
617 if(advf
& ADVF_PRIMEFIRST
) {
618 DataAdviseHolder_SendOnDataChange(iface
, pDataObject
, 0, advf
);
622 * Return the index as the cookie.
623 * Since 0 is not a valid cookie, we will increment by
624 * 1 the index in the table.
626 *pdwConnection
= index
+1;
631 /******************************************************************************
632 * DataAdviseHolder_Unadvise
634 static HRESULT WINAPI
DataAdviseHolder_Unadvise(
635 IDataAdviseHolder
* iface
,
638 ICOM_THIS(DataAdviseHolder
, iface
);
640 TRACE("(%p)->(%lu)\n", This
, dwConnection
);
643 * So we don't return 0 as a cookie, the index was
644 * incremented by 1 in OleAdviseHolderImpl_Advise
645 * we have to compensate.
650 * Check for invalid cookies.
652 if (dwConnection
>= This
->maxCons
)
653 return OLE_E_NOCONNECTION
;
655 if (This
->Connections
[dwConnection
].sink
== NULL
)
656 return OLE_E_NOCONNECTION
;
659 * Release the sink and mark the spot in the list as free.
661 IAdviseSink_Release(This
->Connections
[dwConnection
].sink
);
662 memset(&(This
->Connections
[dwConnection
]), 0, sizeof(DataAdviseConnection
));
666 static HRESULT WINAPI
DataAdviseHolder_EnumAdvise(
667 IDataAdviseHolder
* iface
,
668 IEnumSTATDATA
** ppenumAdvise
)
670 ICOM_THIS(DataAdviseHolder
, iface
);
672 FIXME("(%p)->(%p)\n", This
, ppenumAdvise
);
676 /******************************************************************************
677 * DataAdviseHolder_SendOnDataChange
679 static HRESULT WINAPI
DataAdviseHolder_SendOnDataChange(
680 IDataAdviseHolder
* iface
,
681 IDataObject
* pDataObject
,
685 ICOM_THIS(DataAdviseHolder
, iface
);
690 TRACE("(%p)->(%p,%08lx,%08lx)\n", This
, pDataObject
, dwReserved
, advf
);
692 for(index
= 0; index
< This
->maxCons
; index
++) {
693 if(This
->Connections
[index
].sink
!= NULL
) {
694 if(!(This
->Connections
[index
].advf
& ADVF_NODATA
)) {
695 TRACE("Calling IDataObject_GetData\n");
696 res
= IDataObject_GetData(pDataObject
,
697 &(This
->Connections
[index
].fmat
),
699 TRACE("returns %08lx\n", res
);
701 TRACE("Calling IAdviseSink_OnDataChange\n");
702 IAdviseSink_OnDataChange(This
->Connections
[index
].sink
,
703 &(This
->Connections
[index
].fmat
),
705 TRACE("Done IAdviseSink_OnDataChange\n");
706 if(This
->Connections
[index
].advf
& ADVF_ONLYONCE
) {
707 TRACE("Removing connection\n");
708 DataAdviseHolder_Unadvise(iface
, index
+1);
715 /***********************************************************************
719 /***********************************************************************
720 * CreateOleAdviseHolder [OLE32.@]
722 HRESULT WINAPI
CreateOleAdviseHolder(
723 LPOLEADVISEHOLDER
*ppOAHolder
)
725 TRACE("(%p)\n", ppOAHolder
);
730 if (ppOAHolder
==NULL
)
733 *ppOAHolder
= OleAdviseHolderImpl_Constructor ();
735 if (*ppOAHolder
!= NULL
)
738 return E_OUTOFMEMORY
;
741 /******************************************************************************
742 * CreateDataAdviseHolder [OLE32.@]
744 HRESULT WINAPI
CreateDataAdviseHolder(
745 LPDATAADVISEHOLDER
* ppDAHolder
)
747 TRACE("(%p)\n", ppDAHolder
);
752 if (ppDAHolder
==NULL
)
755 *ppDAHolder
= DataAdviseHolder_Constructor();
757 if (*ppDAHolder
!= NULL
)
760 return E_OUTOFMEMORY
;