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
32 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
37 #define INITIAL_SINKS 10
39 /**************************************************************************
40 * OleAdviseHolderImpl Implementation
42 typedef struct OleAdviseHolderImpl
44 IOleAdviseHolderVtbl
*lpVtbl
;
49 IAdviseSink
** arrayOfSinks
;
51 } OleAdviseHolderImpl
;
53 static LPOLEADVISEHOLDER
OleAdviseHolderImpl_Constructor(void);
54 static void OleAdviseHolderImpl_Destructor(OleAdviseHolderImpl
* ptrToDestroy
);
55 static HRESULT WINAPI
OleAdviseHolderImpl_QueryInterface(LPOLEADVISEHOLDER
,REFIID
,LPVOID
*);
56 static ULONG WINAPI
OleAdviseHolderImpl_AddRef(LPOLEADVISEHOLDER
);
57 static ULONG WINAPI
OleAdviseHolderImpl_Release(LPOLEADVISEHOLDER
);
58 static HRESULT WINAPI
OleAdviseHolderImpl_Advise(LPOLEADVISEHOLDER
, IAdviseSink
*, DWORD
*);
59 static HRESULT WINAPI
OleAdviseHolderImpl_Unadvise (LPOLEADVISEHOLDER
, DWORD
);
60 static HRESULT WINAPI
OleAdviseHolderImpl_EnumAdvise (LPOLEADVISEHOLDER
, IEnumSTATDATA
**);
61 static HRESULT WINAPI
OleAdviseHolderImpl_SendOnRename (LPOLEADVISEHOLDER
, IMoniker
*);
62 static HRESULT WINAPI
OleAdviseHolderImpl_SendOnSave (LPOLEADVISEHOLDER
);
63 static HRESULT WINAPI
OleAdviseHolderImpl_SendOnClose (LPOLEADVISEHOLDER
);
66 /**************************************************************************
67 * OleAdviseHolderImpl_VTable
69 static struct IOleAdviseHolderVtbl oahvt
=
71 OleAdviseHolderImpl_QueryInterface
,
72 OleAdviseHolderImpl_AddRef
,
73 OleAdviseHolderImpl_Release
,
74 OleAdviseHolderImpl_Advise
,
75 OleAdviseHolderImpl_Unadvise
,
76 OleAdviseHolderImpl_EnumAdvise
,
77 OleAdviseHolderImpl_SendOnRename
,
78 OleAdviseHolderImpl_SendOnSave
,
79 OleAdviseHolderImpl_SendOnClose
82 /**************************************************************************
83 * OleAdviseHolderImpl_Constructor
86 static LPOLEADVISEHOLDER
OleAdviseHolderImpl_Constructor()
88 OleAdviseHolderImpl
* lpoah
;
91 lpoah
= HeapAlloc(GetProcessHeap(), 0, 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 OleAdviseHolderImpl
*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 OleAdviseHolderImpl
*This
= (OleAdviseHolderImpl
*)iface
;
182 ULONG ref
= InterlockedIncrement(&This
->ref
);
184 TRACE("(%p)->(ref=%ld)\n", This
, ref
- 1);
189 /******************************************************************************
190 * OleAdviseHolderImpl_Release
192 static ULONG WINAPI
OleAdviseHolderImpl_Release(
193 LPOLEADVISEHOLDER iface
)
195 OleAdviseHolderImpl
*This
= (OleAdviseHolderImpl
*)iface
;
197 TRACE("(%p)->(ref=%ld)\n", This
, This
->ref
);
198 ref
= InterlockedDecrement(&This
->ref
);
200 if (ref
== 0) OleAdviseHolderImpl_Destructor(This
);
205 /******************************************************************************
206 * OleAdviseHolderImpl_Advise
208 static HRESULT WINAPI
OleAdviseHolderImpl_Advise(
209 LPOLEADVISEHOLDER iface
,
210 IAdviseSink
* pAdvise
,
211 DWORD
* pdwConnection
)
215 OleAdviseHolderImpl
*This
= (OleAdviseHolderImpl
*)iface
;
217 TRACE("(%p)->(%p, %p)\n", This
, pAdvise
, pdwConnection
);
222 if (pdwConnection
==NULL
)
228 * Find a free spot in the array.
230 for (index
= 0; index
< This
->maxSinks
; index
++)
232 if (This
->arrayOfSinks
[index
]==NULL
)
237 * If the array is full, we need to grow it.
239 if (index
== This
->maxSinks
)
243 This
->maxSinks
+=INITIAL_SINKS
;
245 This
->arrayOfSinks
= HeapReAlloc(GetProcessHeap(),
248 This
->maxSinks
*sizeof(IAdviseSink
*));
250 for (i
=index
;i
< This
->maxSinks
; i
++)
251 This
->arrayOfSinks
[i
]=0;
257 This
->arrayOfSinks
[index
] = pAdvise
;
259 if (This
->arrayOfSinks
[index
]!=NULL
)
260 IAdviseSink_AddRef(This
->arrayOfSinks
[index
]);
263 * Return the index as the cookie.
264 * Since 0 is not a valid cookie, we will increment by
265 * 1 the index in the table.
267 *pdwConnection
= index
+1;
272 /******************************************************************************
273 * OleAdviseHolderImpl_Unadvise
275 static HRESULT WINAPI
OleAdviseHolderImpl_Unadvise(
276 LPOLEADVISEHOLDER iface
,
279 OleAdviseHolderImpl
*This
= (OleAdviseHolderImpl
*)iface
;
281 TRACE("(%p)->(%lu)\n", This
, dwConnection
);
284 * So we don't return 0 as a cookie, the index was
285 * incremented by 1 in OleAdviseHolderImpl_Advise
286 * we have to compensate.
291 * Check for invalid cookies.
293 if (dwConnection
>= This
->maxSinks
)
294 return OLE_E_NOCONNECTION
;
296 if (This
->arrayOfSinks
[dwConnection
] == NULL
)
297 return OLE_E_NOCONNECTION
;
300 * Release the sink and mark the spot in the list as free.
302 IAdviseSink_Release(This
->arrayOfSinks
[dwConnection
]);
303 This
->arrayOfSinks
[dwConnection
] = NULL
;
308 /******************************************************************************
309 * OleAdviseHolderImpl_EnumAdvise
311 static HRESULT WINAPI
312 OleAdviseHolderImpl_EnumAdvise (LPOLEADVISEHOLDER iface
, IEnumSTATDATA
**ppenumAdvise
)
314 OleAdviseHolderImpl
*This
= (OleAdviseHolderImpl
*)iface
;
315 FIXME("(%p)->(%p)\n", This
, ppenumAdvise
);
317 *ppenumAdvise
= NULL
;
322 /******************************************************************************
323 * OleAdviseHolderImpl_SendOnRename
325 static HRESULT WINAPI
326 OleAdviseHolderImpl_SendOnRename (LPOLEADVISEHOLDER iface
, IMoniker
*pmk
)
328 OleAdviseHolderImpl
*This
= (OleAdviseHolderImpl
*)iface
;
329 FIXME("(%p)->(%p)\n", This
, pmk
);
335 /******************************************************************************
336 * OleAdviseHolderImpl_SendOnSave
338 static HRESULT WINAPI
339 OleAdviseHolderImpl_SendOnSave (LPOLEADVISEHOLDER iface
)
341 OleAdviseHolderImpl
*This
= (OleAdviseHolderImpl
*)iface
;
342 FIXME("(%p)\n", This
);
347 /******************************************************************************
348 * OleAdviseHolderImpl_SendOnClose
350 static HRESULT WINAPI
351 OleAdviseHolderImpl_SendOnClose (LPOLEADVISEHOLDER iface
)
353 OleAdviseHolderImpl
*This
= (OleAdviseHolderImpl
*)iface
;
354 FIXME("(%p)\n", This
);
360 /**************************************************************************
361 * DataAdviseHolder Implementation
363 typedef struct DataAdviseConnection
{
367 } DataAdviseConnection
;
369 typedef struct DataAdviseHolder
371 IDataAdviseHolderVtbl
*lpVtbl
;
375 DataAdviseConnection
* Connections
;
378 /**************************************************************************
379 * DataAdviseHolder method prototypes
381 static IDataAdviseHolder
* DataAdviseHolder_Constructor(void);
382 static void DataAdviseHolder_Destructor(DataAdviseHolder
* ptrToDestroy
);
383 static HRESULT WINAPI
DataAdviseHolder_QueryInterface(
384 IDataAdviseHolder
* iface
,
387 static ULONG WINAPI
DataAdviseHolder_AddRef(
388 IDataAdviseHolder
* iface
);
389 static ULONG WINAPI
DataAdviseHolder_Release(
390 IDataAdviseHolder
* iface
);
391 static HRESULT WINAPI
DataAdviseHolder_Advise(
392 IDataAdviseHolder
* iface
,
393 IDataObject
* pDataObject
,
396 IAdviseSink
* pAdvise
,
397 DWORD
* pdwConnection
);
398 static HRESULT WINAPI
DataAdviseHolder_Unadvise(
399 IDataAdviseHolder
* iface
,
401 static HRESULT WINAPI
DataAdviseHolder_EnumAdvise(
402 IDataAdviseHolder
* iface
,
403 IEnumSTATDATA
** ppenumAdvise
);
404 static HRESULT WINAPI
DataAdviseHolder_SendOnDataChange(
405 IDataAdviseHolder
* iface
,
406 IDataObject
* pDataObject
,
410 /**************************************************************************
411 * DataAdviseHolderImpl_VTable
413 static struct IDataAdviseHolderVtbl DataAdviseHolderImpl_VTable
=
415 DataAdviseHolder_QueryInterface
,
416 DataAdviseHolder_AddRef
,
417 DataAdviseHolder_Release
,
418 DataAdviseHolder_Advise
,
419 DataAdviseHolder_Unadvise
,
420 DataAdviseHolder_EnumAdvise
,
421 DataAdviseHolder_SendOnDataChange
424 /******************************************************************************
425 * DataAdviseHolder_Constructor
427 static IDataAdviseHolder
* DataAdviseHolder_Constructor()
429 DataAdviseHolder
* newHolder
;
431 newHolder
= HeapAlloc(GetProcessHeap(), 0, sizeof(DataAdviseHolder
));
433 newHolder
->lpVtbl
= &DataAdviseHolderImpl_VTable
;
435 newHolder
->maxCons
= INITIAL_SINKS
;
436 newHolder
->Connections
= HeapAlloc(GetProcessHeap(),
439 sizeof(DataAdviseConnection
));
441 TRACE("returning %p\n", newHolder
);
442 return (IDataAdviseHolder
*)newHolder
;
445 /******************************************************************************
446 * DataAdviseHolder_Destructor
448 static void DataAdviseHolder_Destructor(DataAdviseHolder
* ptrToDestroy
)
451 TRACE("%p\n", ptrToDestroy
);
453 for (index
= 0; index
< ptrToDestroy
->maxCons
; index
++)
455 if (ptrToDestroy
->Connections
[index
].sink
!= NULL
)
457 IAdviseSink_Release(ptrToDestroy
->Connections
[index
].sink
);
458 ptrToDestroy
->Connections
[index
].sink
= NULL
;
462 HeapFree(GetProcessHeap(), 0, ptrToDestroy
->Connections
);
463 HeapFree(GetProcessHeap(), 0, ptrToDestroy
);
466 /************************************************************************
467 * DataAdviseHolder_QueryInterface (IUnknown)
469 * See Windows documentation for more details on IUnknown methods.
471 static HRESULT WINAPI
DataAdviseHolder_QueryInterface(
472 IDataAdviseHolder
* iface
,
476 DataAdviseHolder
*This
= (DataAdviseHolder
*)iface
;
477 TRACE("(%p)->(%s,%p)\n",This
,debugstr_guid(riid
),ppvObject
);
479 * Perform a sanity check on the parameters.
481 if ( (This
==0) || (ppvObject
==0) )
485 * Initialize the return parameter.
490 * Compare the riid with the interface IDs implemented by this object.
492 if ( (memcmp(&IID_IUnknown
, riid
, sizeof(IID_IUnknown
)) == 0) ||
493 (memcmp(&IID_IDataAdviseHolder
, riid
, sizeof(IID_IDataAdviseHolder
)) == 0) )
499 * Check that we obtained an interface.
503 return E_NOINTERFACE
;
507 * Query Interface always increases the reference count by one when it is
510 IUnknown_AddRef((IUnknown
*)*ppvObject
);
515 /************************************************************************
516 * DataAdviseHolder_AddRef (IUnknown)
518 * See Windows documentation for more details on IUnknown methods.
520 static ULONG WINAPI
DataAdviseHolder_AddRef(
521 IDataAdviseHolder
* iface
)
523 DataAdviseHolder
*This
= (DataAdviseHolder
*)iface
;
524 TRACE("(%p) (ref=%ld)\n", This
, This
->ref
);
525 return InterlockedIncrement(&This
->ref
);
528 /************************************************************************
529 * DataAdviseHolder_Release (IUnknown)
531 * See Windows documentation for more details on IUnknown methods.
533 static ULONG WINAPI
DataAdviseHolder_Release(
534 IDataAdviseHolder
* iface
)
536 DataAdviseHolder
*This
= (DataAdviseHolder
*)iface
;
538 TRACE("(%p) (ref=%ld)\n", This
, This
->ref
);
541 * Decrease the reference count on this object.
543 ref
= InterlockedDecrement(&This
->ref
);
546 * If the reference count goes down to 0, perform suicide.
548 if (ref
==0) DataAdviseHolder_Destructor(This
);
553 /************************************************************************
554 * DataAdviseHolder_Advise
557 static HRESULT WINAPI
DataAdviseHolder_Advise(
558 IDataAdviseHolder
* iface
,
559 IDataObject
* pDataObject
,
562 IAdviseSink
* pAdvise
,
563 DWORD
* pdwConnection
)
567 DataAdviseHolder
*This
= (DataAdviseHolder
*)iface
;
569 TRACE("(%p)->(%p, %p, %08lx, %p, %p)\n", This
, pDataObject
, pFetc
, advf
,
570 pAdvise
, pdwConnection
);
574 if (pdwConnection
==NULL
)
580 * Find a free spot in the array.
582 for (index
= 0; index
< This
->maxCons
; index
++)
584 if (This
->Connections
[index
].sink
== NULL
)
589 * If the array is full, we need to grow it.
591 if (index
== This
->maxCons
)
593 This
->maxCons
+=INITIAL_SINKS
;
594 This
->Connections
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
596 This
->maxCons
*sizeof(DataAdviseConnection
));
601 This
->Connections
[index
].sink
= pAdvise
;
602 memcpy(&(This
->Connections
[index
].fmat
), pFetc
, sizeof(FORMATETC
));
603 This
->Connections
[index
].advf
= advf
;
605 if (This
->Connections
[index
].sink
!= NULL
) {
606 IAdviseSink_AddRef(This
->Connections
[index
].sink
);
607 if(advf
& ADVF_PRIMEFIRST
) {
608 DataAdviseHolder_SendOnDataChange(iface
, pDataObject
, 0, advf
);
612 * Return the index as the cookie.
613 * Since 0 is not a valid cookie, we will increment by
614 * 1 the index in the table.
616 *pdwConnection
= index
+1;
621 /******************************************************************************
622 * DataAdviseHolder_Unadvise
624 static HRESULT WINAPI
DataAdviseHolder_Unadvise(
625 IDataAdviseHolder
* iface
,
628 DataAdviseHolder
*This
= (DataAdviseHolder
*)iface
;
630 TRACE("(%p)->(%lu)\n", This
, dwConnection
);
633 * So we don't return 0 as a cookie, the index was
634 * incremented by 1 in OleAdviseHolderImpl_Advise
635 * we have to compensate.
640 * Check for invalid cookies.
642 if (dwConnection
>= This
->maxCons
)
643 return OLE_E_NOCONNECTION
;
645 if (This
->Connections
[dwConnection
].sink
== NULL
)
646 return OLE_E_NOCONNECTION
;
649 * Release the sink and mark the spot in the list as free.
651 IAdviseSink_Release(This
->Connections
[dwConnection
].sink
);
652 memset(&(This
->Connections
[dwConnection
]), 0, sizeof(DataAdviseConnection
));
656 static HRESULT WINAPI
DataAdviseHolder_EnumAdvise(
657 IDataAdviseHolder
* iface
,
658 IEnumSTATDATA
** ppenumAdvise
)
660 DataAdviseHolder
*This
= (DataAdviseHolder
*)iface
;
662 FIXME("(%p)->(%p)\n", This
, ppenumAdvise
);
666 /******************************************************************************
667 * DataAdviseHolder_SendOnDataChange
669 static HRESULT WINAPI
DataAdviseHolder_SendOnDataChange(
670 IDataAdviseHolder
* iface
,
671 IDataObject
* pDataObject
,
675 DataAdviseHolder
*This
= (DataAdviseHolder
*)iface
;
680 TRACE("(%p)->(%p,%08lx,%08lx)\n", This
, pDataObject
, dwReserved
, advf
);
682 for(index
= 0; index
< This
->maxCons
; index
++) {
683 if(This
->Connections
[index
].sink
!= NULL
) {
684 if(!(This
->Connections
[index
].advf
& ADVF_NODATA
)) {
685 TRACE("Calling IDataObject_GetData\n");
686 res
= IDataObject_GetData(pDataObject
,
687 &(This
->Connections
[index
].fmat
),
689 TRACE("returns %08lx\n", res
);
691 TRACE("Calling IAdviseSink_OnDataChange\n");
692 IAdviseSink_OnDataChange(This
->Connections
[index
].sink
,
693 &(This
->Connections
[index
].fmat
),
695 TRACE("Done IAdviseSink_OnDataChange\n");
696 if(This
->Connections
[index
].advf
& ADVF_ONLYONCE
) {
697 TRACE("Removing connection\n");
698 DataAdviseHolder_Unadvise(iface
, index
+1);
705 /***********************************************************************
709 /***********************************************************************
710 * CreateOleAdviseHolder [OLE32.@]
712 HRESULT WINAPI
CreateOleAdviseHolder(
713 LPOLEADVISEHOLDER
*ppOAHolder
)
715 TRACE("(%p)\n", ppOAHolder
);
720 if (ppOAHolder
==NULL
)
723 *ppOAHolder
= OleAdviseHolderImpl_Constructor ();
725 if (*ppOAHolder
!= NULL
)
728 return E_OUTOFMEMORY
;
731 /******************************************************************************
732 * CreateDataAdviseHolder [OLE32.@]
734 HRESULT WINAPI
CreateDataAdviseHolder(
735 LPDATAADVISEHOLDER
* ppDAHolder
)
737 TRACE("(%p)\n", ppDAHolder
);
742 if (ppDAHolder
==NULL
)
745 *ppDAHolder
= DataAdviseHolder_Constructor();
747 if (*ppDAHolder
!= NULL
)
750 return E_OUTOFMEMORY
;