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 const IOleAdviseHolderVtbl
*lpVtbl
;
49 IAdviseSink
** arrayOfSinks
;
51 } OleAdviseHolderImpl
;
53 /**************************************************************************
54 * OleAdviseHolderImpl_Destructor
56 static void OleAdviseHolderImpl_Destructor(
57 OleAdviseHolderImpl
* ptrToDestroy
)
60 TRACE("%p\n", ptrToDestroy
);
62 for (index
= 0; index
< ptrToDestroy
->maxSinks
; index
++)
64 if (ptrToDestroy
->arrayOfSinks
[index
]!=0)
66 IAdviseSink_Release(ptrToDestroy
->arrayOfSinks
[index
]);
67 ptrToDestroy
->arrayOfSinks
[index
] = NULL
;
71 HeapFree(GetProcessHeap(),
73 ptrToDestroy
->arrayOfSinks
);
76 HeapFree(GetProcessHeap(),
81 /**************************************************************************
82 * OleAdviseHolderImpl_QueryInterface
84 static HRESULT WINAPI
OleAdviseHolderImpl_QueryInterface(
85 LPOLEADVISEHOLDER iface
,
89 OleAdviseHolderImpl
*This
= (OleAdviseHolderImpl
*)iface
;
90 TRACE("(%p)->(%s,%p)\n",This
,debugstr_guid(riid
),ppvObj
);
99 if (IsEqualIID(riid
, &IID_IUnknown
))
104 else if(IsEqualIID(riid
, &IID_IOleAdviseHolder
))
106 /* IOleAdviseHolder */
107 *ppvObj
= (IOleAdviseHolder
*) This
;
111 return E_NOINTERFACE
;
114 * A successful QI always increments the reference count.
116 IUnknown_AddRef((IUnknown
*)*ppvObj
);
121 /******************************************************************************
122 * OleAdviseHolderImpl_AddRef
124 static ULONG WINAPI
OleAdviseHolderImpl_AddRef(
125 LPOLEADVISEHOLDER iface
)
127 OleAdviseHolderImpl
*This
= (OleAdviseHolderImpl
*)iface
;
128 ULONG ref
= InterlockedIncrement(&This
->ref
);
130 TRACE("(%p)->(ref=%ld)\n", This
, ref
- 1);
135 /******************************************************************************
136 * OleAdviseHolderImpl_Release
138 static ULONG WINAPI
OleAdviseHolderImpl_Release(
139 LPOLEADVISEHOLDER iface
)
141 OleAdviseHolderImpl
*This
= (OleAdviseHolderImpl
*)iface
;
143 TRACE("(%p)->(ref=%ld)\n", This
, This
->ref
);
144 ref
= InterlockedDecrement(&This
->ref
);
146 if (ref
== 0) OleAdviseHolderImpl_Destructor(This
);
151 /******************************************************************************
152 * OleAdviseHolderImpl_Advise
154 static HRESULT WINAPI
OleAdviseHolderImpl_Advise(
155 LPOLEADVISEHOLDER iface
,
156 IAdviseSink
* pAdvise
,
157 DWORD
* pdwConnection
)
161 OleAdviseHolderImpl
*This
= (OleAdviseHolderImpl
*)iface
;
163 TRACE("(%p)->(%p, %p)\n", This
, pAdvise
, pdwConnection
);
168 if (pdwConnection
==NULL
)
174 * Find a free spot in the array.
176 for (index
= 0; index
< This
->maxSinks
; index
++)
178 if (This
->arrayOfSinks
[index
]==NULL
)
183 * If the array is full, we need to grow it.
185 if (index
== This
->maxSinks
)
189 This
->maxSinks
+=INITIAL_SINKS
;
191 This
->arrayOfSinks
= HeapReAlloc(GetProcessHeap(),
194 This
->maxSinks
*sizeof(IAdviseSink
*));
196 for (i
=index
;i
< This
->maxSinks
; i
++)
197 This
->arrayOfSinks
[i
]=0;
203 This
->arrayOfSinks
[index
] = pAdvise
;
205 if (This
->arrayOfSinks
[index
]!=NULL
)
206 IAdviseSink_AddRef(This
->arrayOfSinks
[index
]);
209 * Return the index as the cookie.
210 * Since 0 is not a valid cookie, we will increment by
211 * 1 the index in the table.
213 *pdwConnection
= index
+1;
218 /******************************************************************************
219 * OleAdviseHolderImpl_Unadvise
221 static HRESULT WINAPI
OleAdviseHolderImpl_Unadvise(
222 LPOLEADVISEHOLDER iface
,
225 OleAdviseHolderImpl
*This
= (OleAdviseHolderImpl
*)iface
;
227 TRACE("(%p)->(%lu)\n", This
, dwConnection
);
230 * So we don't return 0 as a cookie, the index was
231 * incremented by 1 in OleAdviseHolderImpl_Advise
232 * we have to compensate.
237 * Check for invalid cookies.
239 if (dwConnection
>= This
->maxSinks
)
240 return OLE_E_NOCONNECTION
;
242 if (This
->arrayOfSinks
[dwConnection
] == NULL
)
243 return OLE_E_NOCONNECTION
;
246 * Release the sink and mark the spot in the list as free.
248 IAdviseSink_Release(This
->arrayOfSinks
[dwConnection
]);
249 This
->arrayOfSinks
[dwConnection
] = NULL
;
254 /******************************************************************************
255 * OleAdviseHolderImpl_EnumAdvise
257 static HRESULT WINAPI
258 OleAdviseHolderImpl_EnumAdvise (LPOLEADVISEHOLDER iface
, IEnumSTATDATA
**ppenumAdvise
)
260 OleAdviseHolderImpl
*This
= (OleAdviseHolderImpl
*)iface
;
261 FIXME("(%p)->(%p)\n", This
, ppenumAdvise
);
263 *ppenumAdvise
= NULL
;
268 /******************************************************************************
269 * OleAdviseHolderImpl_SendOnRename
271 static HRESULT WINAPI
272 OleAdviseHolderImpl_SendOnRename (LPOLEADVISEHOLDER iface
, IMoniker
*pmk
)
274 OleAdviseHolderImpl
*This
= (OleAdviseHolderImpl
*)iface
;
275 FIXME("(%p)->(%p)\n", This
, pmk
);
281 /******************************************************************************
282 * OleAdviseHolderImpl_SendOnSave
284 static HRESULT WINAPI
285 OleAdviseHolderImpl_SendOnSave (LPOLEADVISEHOLDER iface
)
287 OleAdviseHolderImpl
*This
= (OleAdviseHolderImpl
*)iface
;
288 FIXME("(%p)\n", This
);
293 /******************************************************************************
294 * OleAdviseHolderImpl_SendOnClose
296 static HRESULT WINAPI
297 OleAdviseHolderImpl_SendOnClose (LPOLEADVISEHOLDER iface
)
299 OleAdviseHolderImpl
*This
= (OleAdviseHolderImpl
*)iface
;
300 FIXME("(%p)\n", This
);
306 /**************************************************************************
307 * OleAdviseHolderImpl_VTable
309 static const IOleAdviseHolderVtbl oahvt
=
311 OleAdviseHolderImpl_QueryInterface
,
312 OleAdviseHolderImpl_AddRef
,
313 OleAdviseHolderImpl_Release
,
314 OleAdviseHolderImpl_Advise
,
315 OleAdviseHolderImpl_Unadvise
,
316 OleAdviseHolderImpl_EnumAdvise
,
317 OleAdviseHolderImpl_SendOnRename
,
318 OleAdviseHolderImpl_SendOnSave
,
319 OleAdviseHolderImpl_SendOnClose
322 /**************************************************************************
323 * OleAdviseHolderImpl_Constructor
326 static LPOLEADVISEHOLDER
OleAdviseHolderImpl_Constructor(void)
328 OleAdviseHolderImpl
* lpoah
;
331 lpoah
= HeapAlloc(GetProcessHeap(), 0, sizeof(OleAdviseHolderImpl
));
333 lpoah
->lpVtbl
= &oahvt
;
335 lpoah
->maxSinks
= INITIAL_SINKS
;
336 lpoah
->arrayOfSinks
= HeapAlloc(GetProcessHeap(),
338 lpoah
->maxSinks
* sizeof(IAdviseSink
*));
340 for (index
= 0; index
< lpoah
->maxSinks
; index
++)
341 lpoah
->arrayOfSinks
[index
]=0;
343 TRACE("returning %p\n", lpoah
);
344 return (LPOLEADVISEHOLDER
)lpoah
;
347 /**************************************************************************
348 * DataAdviseHolder Implementation
350 typedef struct DataAdviseConnection
{
354 DWORD remote_connection
;
355 } DataAdviseConnection
;
357 typedef struct DataAdviseHolder
359 const IDataAdviseHolderVtbl
*lpVtbl
;
363 DataAdviseConnection
* Connections
;
366 /* this connection has also has been advised to the delegate data object */
367 #define WINE_ADVF_REMOTE 0x80000000
369 /******************************************************************************
370 * DataAdviseHolder_Destructor
372 static void DataAdviseHolder_Destructor(DataAdviseHolder
* ptrToDestroy
)
375 TRACE("%p\n", ptrToDestroy
);
377 for (index
= 0; index
< ptrToDestroy
->maxCons
; index
++)
379 if (ptrToDestroy
->Connections
[index
].sink
!= NULL
)
381 IAdviseSink_Release(ptrToDestroy
->Connections
[index
].sink
);
382 ptrToDestroy
->Connections
[index
].sink
= NULL
;
386 HeapFree(GetProcessHeap(), 0, ptrToDestroy
->Connections
);
387 HeapFree(GetProcessHeap(), 0, ptrToDestroy
);
390 /************************************************************************
391 * DataAdviseHolder_QueryInterface (IUnknown)
393 * See Windows documentation for more details on IUnknown methods.
395 static HRESULT WINAPI
DataAdviseHolder_QueryInterface(
396 IDataAdviseHolder
* iface
,
400 DataAdviseHolder
*This
= (DataAdviseHolder
*)iface
;
401 TRACE("(%p)->(%s,%p)\n",This
,debugstr_guid(riid
),ppvObject
);
403 * Perform a sanity check on the parameters.
405 if ( (This
==0) || (ppvObject
==0) )
409 * Initialize the return parameter.
414 * Compare the riid with the interface IDs implemented by this object.
416 if ( (memcmp(&IID_IUnknown
, riid
, sizeof(IID_IUnknown
)) == 0) ||
417 (memcmp(&IID_IDataAdviseHolder
, riid
, sizeof(IID_IDataAdviseHolder
)) == 0) )
423 * Check that we obtained an interface.
427 return E_NOINTERFACE
;
431 * Query Interface always increases the reference count by one when it is
434 IUnknown_AddRef((IUnknown
*)*ppvObject
);
439 /************************************************************************
440 * DataAdviseHolder_AddRef (IUnknown)
442 * See Windows documentation for more details on IUnknown methods.
444 static ULONG WINAPI
DataAdviseHolder_AddRef(
445 IDataAdviseHolder
* iface
)
447 DataAdviseHolder
*This
= (DataAdviseHolder
*)iface
;
448 TRACE("(%p) (ref=%ld)\n", This
, This
->ref
);
449 return InterlockedIncrement(&This
->ref
);
452 /************************************************************************
453 * DataAdviseHolder_Release (IUnknown)
455 * See Windows documentation for more details on IUnknown methods.
457 static ULONG WINAPI
DataAdviseHolder_Release(
458 IDataAdviseHolder
* iface
)
460 DataAdviseHolder
*This
= (DataAdviseHolder
*)iface
;
462 TRACE("(%p) (ref=%ld)\n", This
, This
->ref
);
465 * Decrease the reference count on this object.
467 ref
= InterlockedDecrement(&This
->ref
);
470 * If the reference count goes down to 0, perform suicide.
472 if (ref
==0) DataAdviseHolder_Destructor(This
);
477 /************************************************************************
478 * DataAdviseHolder_Advise
481 static HRESULT WINAPI
DataAdviseHolder_Advise(
482 IDataAdviseHolder
* iface
,
483 IDataObject
* pDataObject
,
486 IAdviseSink
* pAdvise
,
487 DWORD
* pdwConnection
)
491 DataAdviseHolder
*This
= (DataAdviseHolder
*)iface
;
493 TRACE("(%p)->(%p, %p, %08lx, %p, %p)\n", This
, pDataObject
, pFetc
, advf
,
494 pAdvise
, pdwConnection
);
498 if (pdwConnection
==NULL
)
504 * Find a free spot in the array.
506 for (index
= 0; index
< This
->maxCons
; index
++)
508 if (This
->Connections
[index
].sink
== NULL
)
513 * If the array is full, we need to grow it.
515 if (index
== This
->maxCons
)
517 This
->maxCons
+=INITIAL_SINKS
;
518 This
->Connections
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
520 This
->maxCons
*sizeof(DataAdviseConnection
));
525 This
->Connections
[index
].sink
= pAdvise
;
526 memcpy(&(This
->Connections
[index
].fmat
), pFetc
, sizeof(FORMATETC
));
527 This
->Connections
[index
].advf
= advf
& ~WINE_ADVF_REMOTE
;
529 if (This
->Connections
[index
].sink
!= NULL
) {
530 IAdviseSink_AddRef(This
->Connections
[index
].sink
);
531 if(advf
& ADVF_PRIMEFIRST
) {
532 IDataAdviseHolder_SendOnDataChange(iface
, pDataObject
, 0, advf
);
536 * Return the index as the cookie.
537 * Since 0 is not a valid cookie, we will increment by
538 * 1 the index in the table.
540 *pdwConnection
= index
+1;
545 /******************************************************************************
546 * DataAdviseHolder_Unadvise
548 static HRESULT WINAPI
DataAdviseHolder_Unadvise(
549 IDataAdviseHolder
* iface
,
552 DataAdviseHolder
*This
= (DataAdviseHolder
*)iface
;
554 TRACE("(%p)->(%lu)\n", This
, dwConnection
);
557 * So we don't return 0 as a cookie, the index was
558 * incremented by 1 in OleAdviseHolderImpl_Advise
559 * we have to compensate.
564 * Check for invalid cookies.
566 if (dwConnection
>= This
->maxCons
)
567 return OLE_E_NOCONNECTION
;
569 if (This
->Connections
[dwConnection
].sink
== NULL
)
570 return OLE_E_NOCONNECTION
;
573 * Release the sink and mark the spot in the list as free.
575 IAdviseSink_Release(This
->Connections
[dwConnection
].sink
);
576 memset(&(This
->Connections
[dwConnection
]), 0, sizeof(DataAdviseConnection
));
580 static HRESULT WINAPI
DataAdviseHolder_EnumAdvise(
581 IDataAdviseHolder
* iface
,
582 IEnumSTATDATA
** ppenumAdvise
)
584 DataAdviseHolder
*This
= (DataAdviseHolder
*)iface
;
586 FIXME("(%p)->(%p)\n", This
, ppenumAdvise
);
590 /******************************************************************************
591 * DataAdviseHolder_SendOnDataChange
593 static HRESULT WINAPI
DataAdviseHolder_SendOnDataChange(
594 IDataAdviseHolder
* iface
,
595 IDataObject
* pDataObject
,
599 DataAdviseHolder
*This
= (DataAdviseHolder
*)iface
;
604 TRACE("(%p)->(%p,%08lx,%08lx)\n", This
, pDataObject
, dwReserved
, advf
);
606 for(index
= 0; index
< This
->maxCons
; index
++) {
607 if(This
->Connections
[index
].sink
!= NULL
) {
608 if(!(This
->Connections
[index
].advf
& ADVF_NODATA
)) {
609 TRACE("Calling IDataObject_GetData\n");
610 res
= IDataObject_GetData(pDataObject
,
611 &(This
->Connections
[index
].fmat
),
613 TRACE("returns %08lx\n", res
);
615 TRACE("Calling IAdviseSink_OnDataChange\n");
616 IAdviseSink_OnDataChange(This
->Connections
[index
].sink
,
617 &(This
->Connections
[index
].fmat
),
619 TRACE("Done IAdviseSink_OnDataChange\n");
620 if(This
->Connections
[index
].advf
& ADVF_ONLYONCE
) {
621 TRACE("Removing connection\n");
622 DataAdviseHolder_Unadvise(iface
, index
+1);
629 /**************************************************************************
630 * DataAdviseHolderImpl_VTable
632 static const IDataAdviseHolderVtbl DataAdviseHolderImpl_VTable
=
634 DataAdviseHolder_QueryInterface
,
635 DataAdviseHolder_AddRef
,
636 DataAdviseHolder_Release
,
637 DataAdviseHolder_Advise
,
638 DataAdviseHolder_Unadvise
,
639 DataAdviseHolder_EnumAdvise
,
640 DataAdviseHolder_SendOnDataChange
643 HRESULT
DataAdviseHolder_OnConnect(IDataAdviseHolder
*iface
, IDataObject
*pDelegate
)
645 DataAdviseHolder
*This
= (DataAdviseHolder
*)iface
;
649 for(index
= 0; index
< This
->maxCons
; index
++)
651 if(This
->Connections
[index
].sink
!= NULL
)
653 hr
= IDataObject_DAdvise(pDelegate
, &This
->Connections
[index
].fmat
,
654 This
->Connections
[index
].advf
,
655 This
->Connections
[index
].sink
,
656 &This
->Connections
[index
].remote_connection
);
657 if (FAILED(hr
)) break;
658 This
->Connections
[index
].advf
|= WINE_ADVF_REMOTE
;
661 /* FIXME: store pDelegate somewhere */
665 void DataAdviseHolder_OnDisconnect(IDataAdviseHolder
*iface
)
667 /* FIXME: Unadvise all remote interfaces */
670 /******************************************************************************
671 * DataAdviseHolder_Constructor
673 static IDataAdviseHolder
* DataAdviseHolder_Constructor(void)
675 DataAdviseHolder
* newHolder
;
677 newHolder
= HeapAlloc(GetProcessHeap(), 0, sizeof(DataAdviseHolder
));
679 newHolder
->lpVtbl
= &DataAdviseHolderImpl_VTable
;
681 newHolder
->maxCons
= INITIAL_SINKS
;
682 newHolder
->Connections
= HeapAlloc(GetProcessHeap(),
685 sizeof(DataAdviseConnection
));
687 TRACE("returning %p\n", newHolder
);
688 return (IDataAdviseHolder
*)newHolder
;
691 /***********************************************************************
695 /***********************************************************************
696 * CreateOleAdviseHolder [OLE32.@]
698 HRESULT WINAPI
CreateOleAdviseHolder(
699 LPOLEADVISEHOLDER
*ppOAHolder
)
701 TRACE("(%p)\n", ppOAHolder
);
706 if (ppOAHolder
==NULL
)
709 *ppOAHolder
= OleAdviseHolderImpl_Constructor ();
711 if (*ppOAHolder
!= NULL
)
714 return E_OUTOFMEMORY
;
717 /******************************************************************************
718 * CreateDataAdviseHolder [OLE32.@]
720 HRESULT WINAPI
CreateDataAdviseHolder(
721 LPDATAADVISEHOLDER
* ppDAHolder
)
723 TRACE("(%p)\n", ppDAHolder
);
728 if (ppDAHolder
==NULL
)
731 *ppDAHolder
= DataAdviseHolder_Constructor();
733 if (*ppDAHolder
!= NULL
)
736 return E_OUTOFMEMORY
;