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
= (OleAdviseHolderImpl
*)HeapAlloc(GetProcessHeap(),
93 sizeof(OleAdviseHolderImpl
));
95 lpoah
->lpVtbl
= &oahvt
;
97 lpoah
->maxSinks
= INITIAL_SINKS
;
98 lpoah
->arrayOfSinks
= HeapAlloc(GetProcessHeap(),
100 lpoah
->maxSinks
* sizeof(IAdviseSink
*));
102 for (index
= 0; index
< lpoah
->maxSinks
; index
++)
103 lpoah
->arrayOfSinks
[index
]=0;
105 TRACE("returning %p\n", lpoah
);
106 return (LPOLEADVISEHOLDER
)lpoah
;
109 /**************************************************************************
110 * OleAdviseHolderImpl_Destructor
112 static void OleAdviseHolderImpl_Destructor(
113 OleAdviseHolderImpl
* ptrToDestroy
)
116 TRACE("%p\n", ptrToDestroy
);
118 for (index
= 0; index
< ptrToDestroy
->maxSinks
; index
++)
120 if (ptrToDestroy
->arrayOfSinks
[index
]!=0)
122 IAdviseSink_Release(ptrToDestroy
->arrayOfSinks
[index
]);
123 ptrToDestroy
->arrayOfSinks
[index
] = NULL
;
127 HeapFree(GetProcessHeap(),
129 ptrToDestroy
->arrayOfSinks
);
132 HeapFree(GetProcessHeap(),
137 /**************************************************************************
138 * OleAdviseHolderImpl_QueryInterface
140 static HRESULT WINAPI
OleAdviseHolderImpl_QueryInterface(
141 LPOLEADVISEHOLDER iface
,
145 OleAdviseHolderImpl
*This
= (OleAdviseHolderImpl
*)iface
;
146 TRACE("(%p)->(%s,%p)\n",This
,debugstr_guid(riid
),ppvObj
);
155 if (IsEqualIID(riid
, &IID_IUnknown
))
160 else if(IsEqualIID(riid
, &IID_IOleAdviseHolder
))
162 /* IOleAdviseHolder */
163 *ppvObj
= (IOleAdviseHolder
*) This
;
167 return E_NOINTERFACE
;
170 * A successful QI always increments the reference count.
172 IUnknown_AddRef((IUnknown
*)*ppvObj
);
177 /******************************************************************************
178 * OleAdviseHolderImpl_AddRef
180 static ULONG WINAPI
OleAdviseHolderImpl_AddRef(
181 LPOLEADVISEHOLDER iface
)
183 OleAdviseHolderImpl
*This
= (OleAdviseHolderImpl
*)iface
;
184 ULONG ref
= InterlockedIncrement(&This
->ref
);
186 TRACE("(%p)->(ref=%ld)\n", This
, ref
- 1);
191 /******************************************************************************
192 * OleAdviseHolderImpl_Release
194 static ULONG WINAPI
OleAdviseHolderImpl_Release(
195 LPOLEADVISEHOLDER iface
)
197 OleAdviseHolderImpl
*This
= (OleAdviseHolderImpl
*)iface
;
199 TRACE("(%p)->(ref=%ld)\n", This
, This
->ref
);
200 ref
= InterlockedDecrement(&This
->ref
);
202 if (ref
== 0) OleAdviseHolderImpl_Destructor(This
);
207 /******************************************************************************
208 * OleAdviseHolderImpl_Advise
210 static HRESULT WINAPI
OleAdviseHolderImpl_Advise(
211 LPOLEADVISEHOLDER iface
,
212 IAdviseSink
* pAdvise
,
213 DWORD
* pdwConnection
)
217 OleAdviseHolderImpl
*This
= (OleAdviseHolderImpl
*)iface
;
219 TRACE("(%p)->(%p, %p)\n", This
, pAdvise
, pdwConnection
);
224 if (pdwConnection
==NULL
)
230 * Find a free spot in the array.
232 for (index
= 0; index
< This
->maxSinks
; index
++)
234 if (This
->arrayOfSinks
[index
]==NULL
)
239 * If the array is full, we need to grow it.
241 if (index
== This
->maxSinks
)
245 This
->maxSinks
+=INITIAL_SINKS
;
247 This
->arrayOfSinks
= HeapReAlloc(GetProcessHeap(),
250 This
->maxSinks
*sizeof(IAdviseSink
*));
252 for (i
=index
;i
< This
->maxSinks
; i
++)
253 This
->arrayOfSinks
[i
]=0;
259 This
->arrayOfSinks
[index
] = pAdvise
;
261 if (This
->arrayOfSinks
[index
]!=NULL
)
262 IAdviseSink_AddRef(This
->arrayOfSinks
[index
]);
265 * Return the index as the cookie.
266 * Since 0 is not a valid cookie, we will increment by
267 * 1 the index in the table.
269 *pdwConnection
= index
+1;
274 /******************************************************************************
275 * OleAdviseHolderImpl_Unadvise
277 static HRESULT WINAPI
OleAdviseHolderImpl_Unadvise(
278 LPOLEADVISEHOLDER iface
,
281 OleAdviseHolderImpl
*This
= (OleAdviseHolderImpl
*)iface
;
283 TRACE("(%p)->(%lu)\n", This
, dwConnection
);
286 * So we don't return 0 as a cookie, the index was
287 * incremented by 1 in OleAdviseHolderImpl_Advise
288 * we have to compensate.
293 * Check for invalid cookies.
295 if (dwConnection
>= This
->maxSinks
)
296 return OLE_E_NOCONNECTION
;
298 if (This
->arrayOfSinks
[dwConnection
] == NULL
)
299 return OLE_E_NOCONNECTION
;
302 * Release the sink and mark the spot in the list as free.
304 IAdviseSink_Release(This
->arrayOfSinks
[dwConnection
]);
305 This
->arrayOfSinks
[dwConnection
] = NULL
;
310 /******************************************************************************
311 * OleAdviseHolderImpl_EnumAdvise
313 static HRESULT WINAPI
314 OleAdviseHolderImpl_EnumAdvise (LPOLEADVISEHOLDER iface
, IEnumSTATDATA
**ppenumAdvise
)
316 OleAdviseHolderImpl
*This
= (OleAdviseHolderImpl
*)iface
;
317 FIXME("(%p)->(%p)\n", This
, ppenumAdvise
);
319 *ppenumAdvise
= NULL
;
324 /******************************************************************************
325 * OleAdviseHolderImpl_SendOnRename
327 static HRESULT WINAPI
328 OleAdviseHolderImpl_SendOnRename (LPOLEADVISEHOLDER iface
, IMoniker
*pmk
)
330 OleAdviseHolderImpl
*This
= (OleAdviseHolderImpl
*)iface
;
331 FIXME("(%p)->(%p)\n", This
, pmk
);
337 /******************************************************************************
338 * OleAdviseHolderImpl_SendOnSave
340 static HRESULT WINAPI
341 OleAdviseHolderImpl_SendOnSave (LPOLEADVISEHOLDER iface
)
343 OleAdviseHolderImpl
*This
= (OleAdviseHolderImpl
*)iface
;
344 FIXME("(%p)\n", This
);
349 /******************************************************************************
350 * OleAdviseHolderImpl_SendOnClose
352 static HRESULT WINAPI
353 OleAdviseHolderImpl_SendOnClose (LPOLEADVISEHOLDER iface
)
355 OleAdviseHolderImpl
*This
= (OleAdviseHolderImpl
*)iface
;
356 FIXME("(%p)\n", This
);
362 /**************************************************************************
363 * DataAdviseHolder Implementation
365 typedef struct DataAdviseConnection
{
369 } DataAdviseConnection
;
371 typedef struct DataAdviseHolder
373 IDataAdviseHolderVtbl
*lpVtbl
;
377 DataAdviseConnection
* Connections
;
380 /**************************************************************************
381 * DataAdviseHolder method prototypes
383 static IDataAdviseHolder
* DataAdviseHolder_Constructor(void);
384 static void DataAdviseHolder_Destructor(DataAdviseHolder
* ptrToDestroy
);
385 static HRESULT WINAPI
DataAdviseHolder_QueryInterface(
386 IDataAdviseHolder
* iface
,
389 static ULONG WINAPI
DataAdviseHolder_AddRef(
390 IDataAdviseHolder
* iface
);
391 static ULONG WINAPI
DataAdviseHolder_Release(
392 IDataAdviseHolder
* iface
);
393 static HRESULT WINAPI
DataAdviseHolder_Advise(
394 IDataAdviseHolder
* iface
,
395 IDataObject
* pDataObject
,
398 IAdviseSink
* pAdvise
,
399 DWORD
* pdwConnection
);
400 static HRESULT WINAPI
DataAdviseHolder_Unadvise(
401 IDataAdviseHolder
* iface
,
403 static HRESULT WINAPI
DataAdviseHolder_EnumAdvise(
404 IDataAdviseHolder
* iface
,
405 IEnumSTATDATA
** ppenumAdvise
);
406 static HRESULT WINAPI
DataAdviseHolder_SendOnDataChange(
407 IDataAdviseHolder
* iface
,
408 IDataObject
* pDataObject
,
412 /**************************************************************************
413 * DataAdviseHolderImpl_VTable
415 static struct IDataAdviseHolderVtbl DataAdviseHolderImpl_VTable
=
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 DataAdviseHolder
*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 DataAdviseHolder
*This
= (DataAdviseHolder
*)iface
;
528 TRACE("(%p) (ref=%ld)\n", This
, This
->ref
);
529 return InterlockedIncrement(&This
->ref
);
532 /************************************************************************
533 * DataAdviseHolder_Release (IUnknown)
535 * See Windows documentation for more details on IUnknown methods.
537 static ULONG WINAPI
DataAdviseHolder_Release(
538 IDataAdviseHolder
* iface
)
540 DataAdviseHolder
*This
= (DataAdviseHolder
*)iface
;
542 TRACE("(%p) (ref=%ld)\n", This
, This
->ref
);
545 * Decrease the reference count on this object.
547 ref
= InterlockedDecrement(&This
->ref
);
550 * If the reference count goes down to 0, perform suicide.
552 if (ref
==0) DataAdviseHolder_Destructor(This
);
557 /************************************************************************
558 * DataAdviseHolder_Advise
561 static HRESULT WINAPI
DataAdviseHolder_Advise(
562 IDataAdviseHolder
* iface
,
563 IDataObject
* pDataObject
,
566 IAdviseSink
* pAdvise
,
567 DWORD
* pdwConnection
)
571 DataAdviseHolder
*This
= (DataAdviseHolder
*)iface
;
573 TRACE("(%p)->(%p, %p, %08lx, %p, %p)\n", This
, pDataObject
, pFetc
, advf
,
574 pAdvise
, pdwConnection
);
578 if (pdwConnection
==NULL
)
584 * Find a free spot in the array.
586 for (index
= 0; index
< This
->maxCons
; index
++)
588 if (This
->Connections
[index
].sink
== NULL
)
593 * If the array is full, we need to grow it.
595 if (index
== This
->maxCons
)
597 This
->maxCons
+=INITIAL_SINKS
;
598 This
->Connections
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
600 This
->maxCons
*sizeof(DataAdviseConnection
));
605 This
->Connections
[index
].sink
= pAdvise
;
606 memcpy(&(This
->Connections
[index
].fmat
), pFetc
, sizeof(FORMATETC
));
607 This
->Connections
[index
].advf
= advf
;
609 if (This
->Connections
[index
].sink
!= NULL
) {
610 IAdviseSink_AddRef(This
->Connections
[index
].sink
);
611 if(advf
& ADVF_PRIMEFIRST
) {
612 DataAdviseHolder_SendOnDataChange(iface
, pDataObject
, 0, advf
);
616 * Return the index as the cookie.
617 * Since 0 is not a valid cookie, we will increment by
618 * 1 the index in the table.
620 *pdwConnection
= index
+1;
625 /******************************************************************************
626 * DataAdviseHolder_Unadvise
628 static HRESULT WINAPI
DataAdviseHolder_Unadvise(
629 IDataAdviseHolder
* iface
,
632 DataAdviseHolder
*This
= (DataAdviseHolder
*)iface
;
634 TRACE("(%p)->(%lu)\n", This
, dwConnection
);
637 * So we don't return 0 as a cookie, the index was
638 * incremented by 1 in OleAdviseHolderImpl_Advise
639 * we have to compensate.
644 * Check for invalid cookies.
646 if (dwConnection
>= This
->maxCons
)
647 return OLE_E_NOCONNECTION
;
649 if (This
->Connections
[dwConnection
].sink
== NULL
)
650 return OLE_E_NOCONNECTION
;
653 * Release the sink and mark the spot in the list as free.
655 IAdviseSink_Release(This
->Connections
[dwConnection
].sink
);
656 memset(&(This
->Connections
[dwConnection
]), 0, sizeof(DataAdviseConnection
));
660 static HRESULT WINAPI
DataAdviseHolder_EnumAdvise(
661 IDataAdviseHolder
* iface
,
662 IEnumSTATDATA
** ppenumAdvise
)
664 DataAdviseHolder
*This
= (DataAdviseHolder
*)iface
;
666 FIXME("(%p)->(%p)\n", This
, ppenumAdvise
);
670 /******************************************************************************
671 * DataAdviseHolder_SendOnDataChange
673 static HRESULT WINAPI
DataAdviseHolder_SendOnDataChange(
674 IDataAdviseHolder
* iface
,
675 IDataObject
* pDataObject
,
679 DataAdviseHolder
*This
= (DataAdviseHolder
*)iface
;
684 TRACE("(%p)->(%p,%08lx,%08lx)\n", This
, pDataObject
, dwReserved
, advf
);
686 for(index
= 0; index
< This
->maxCons
; index
++) {
687 if(This
->Connections
[index
].sink
!= NULL
) {
688 if(!(This
->Connections
[index
].advf
& ADVF_NODATA
)) {
689 TRACE("Calling IDataObject_GetData\n");
690 res
= IDataObject_GetData(pDataObject
,
691 &(This
->Connections
[index
].fmat
),
693 TRACE("returns %08lx\n", res
);
695 TRACE("Calling IAdviseSink_OnDataChange\n");
696 IAdviseSink_OnDataChange(This
->Connections
[index
].sink
,
697 &(This
->Connections
[index
].fmat
),
699 TRACE("Done IAdviseSink_OnDataChange\n");
700 if(This
->Connections
[index
].advf
& ADVF_ONLYONCE
) {
701 TRACE("Removing connection\n");
702 DataAdviseHolder_Unadvise(iface
, index
+1);
709 /***********************************************************************
713 /***********************************************************************
714 * CreateOleAdviseHolder [OLE32.@]
716 HRESULT WINAPI
CreateOleAdviseHolder(
717 LPOLEADVISEHOLDER
*ppOAHolder
)
719 TRACE("(%p)\n", ppOAHolder
);
724 if (ppOAHolder
==NULL
)
727 *ppOAHolder
= OleAdviseHolderImpl_Constructor ();
729 if (*ppOAHolder
!= NULL
)
732 return E_OUTOFMEMORY
;
735 /******************************************************************************
736 * CreateDataAdviseHolder [OLE32.@]
738 HRESULT WINAPI
CreateDataAdviseHolder(
739 LPDATAADVISEHOLDER
* ppDAHolder
)
741 TRACE("(%p)\n", ppDAHolder
);
746 if (ppDAHolder
==NULL
)
749 *ppDAHolder
= DataAdviseHolder_Constructor();
751 if (*ppDAHolder
!= NULL
)
754 return E_OUTOFMEMORY
;