kernel: DelayLoadFailureHook crash fix.
[wine/multimedia.git] / dlls / ole32 / oleobj.c
blob3943aec6b88a703acb5cbe83a34f408b2a1332e9
1 /*
2 * OLE2 COM objects
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
23 #include <stdarg.h>
24 #include <string.h>
26 #define COBJMACROS
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winuser.h"
31 #include "winerror.h"
32 #include "wine/debug.h"
33 #include "ole2.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(ole);
37 #define INITIAL_SINKS 10
39 /**************************************************************************
40 * OleAdviseHolderImpl Implementation
42 typedef struct OleAdviseHolderImpl
44 const IOleAdviseHolderVtbl *lpVtbl;
46 LONG ref;
48 DWORD maxSinks;
49 IAdviseSink** arrayOfSinks;
51 } OleAdviseHolderImpl;
53 /**************************************************************************
54 * OleAdviseHolderImpl_Destructor
56 static void OleAdviseHolderImpl_Destructor(
57 OleAdviseHolderImpl* ptrToDestroy)
59 DWORD index;
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(),
78 ptrToDestroy);
81 /**************************************************************************
82 * OleAdviseHolderImpl_QueryInterface
84 static HRESULT WINAPI OleAdviseHolderImpl_QueryInterface(
85 LPOLEADVISEHOLDER iface,
86 REFIID riid,
87 LPVOID* ppvObj)
89 OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
90 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObj);
92 * Sanity check
94 if (ppvObj==NULL)
95 return E_POINTER;
97 *ppvObj = NULL;
99 if (IsEqualIID(riid, &IID_IUnknown))
101 /* IUnknown */
102 *ppvObj = This;
104 else if(IsEqualIID(riid, &IID_IOleAdviseHolder))
106 /* IOleAdviseHolder */
107 *ppvObj = (IOleAdviseHolder*) This;
110 if(*ppvObj == NULL)
111 return E_NOINTERFACE;
114 * A successful QI always increments the reference count.
116 IUnknown_AddRef((IUnknown*)*ppvObj);
118 return S_OK;
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);
132 return ref;
135 /******************************************************************************
136 * OleAdviseHolderImpl_Release
138 static ULONG WINAPI OleAdviseHolderImpl_Release(
139 LPOLEADVISEHOLDER iface)
141 OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
142 ULONG ref;
143 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
144 ref = InterlockedDecrement(&This->ref);
146 if (ref == 0) OleAdviseHolderImpl_Destructor(This);
148 return ref;
151 /******************************************************************************
152 * OleAdviseHolderImpl_Advise
154 static HRESULT WINAPI OleAdviseHolderImpl_Advise(
155 LPOLEADVISEHOLDER iface,
156 IAdviseSink* pAdvise,
157 DWORD* pdwConnection)
159 DWORD index;
161 OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
163 TRACE("(%p)->(%p, %p)\n", This, pAdvise, pdwConnection);
166 * Sanity check
168 if (pdwConnection==NULL)
169 return E_POINTER;
171 *pdwConnection = 0;
174 * Find a free spot in the array.
176 for (index = 0; index < This->maxSinks; index++)
178 if (This->arrayOfSinks[index]==NULL)
179 break;
183 * If the array is full, we need to grow it.
185 if (index == This->maxSinks)
187 DWORD i;
189 This->maxSinks+=INITIAL_SINKS;
191 This->arrayOfSinks = HeapReAlloc(GetProcessHeap(),
193 This->arrayOfSinks,
194 This->maxSinks*sizeof(IAdviseSink*));
196 for (i=index;i < This->maxSinks; i++)
197 This->arrayOfSinks[i]=0;
201 * Store the new sink
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;
215 return S_OK;
218 /******************************************************************************
219 * OleAdviseHolderImpl_Unadvise
221 static HRESULT WINAPI OleAdviseHolderImpl_Unadvise(
222 LPOLEADVISEHOLDER iface,
223 DWORD dwConnection)
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.
234 dwConnection--;
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;
251 return S_OK;
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;
265 return S_OK;
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);
278 return S_OK;
281 /******************************************************************************
282 * OleAdviseHolderImpl_SendOnSave
284 static HRESULT WINAPI
285 OleAdviseHolderImpl_SendOnSave (LPOLEADVISEHOLDER iface)
287 OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
288 FIXME("(%p)\n", This);
290 return S_OK;
293 /******************************************************************************
294 * OleAdviseHolderImpl_SendOnClose
296 static HRESULT WINAPI
297 OleAdviseHolderImpl_SendOnClose (LPOLEADVISEHOLDER iface)
299 OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
300 FIXME("(%p)\n", This);
303 return S_OK;
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;
329 DWORD index;
331 lpoah = HeapAlloc(GetProcessHeap(), 0, sizeof(OleAdviseHolderImpl));
333 lpoah->lpVtbl = &oahvt;
334 lpoah->ref = 1;
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 {
351 IAdviseSink *sink;
352 FORMATETC fmat;
353 DWORD advf;
354 DWORD remote_connection;
355 } DataAdviseConnection;
357 typedef struct DataAdviseHolder
359 const IDataAdviseHolderVtbl *lpVtbl;
361 LONG ref;
362 DWORD maxCons;
363 DataAdviseConnection* Connections;
364 } DataAdviseHolder;
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)
374 DWORD index;
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,
397 REFIID riid,
398 void** ppvObject)
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) )
406 return E_INVALIDARG;
409 * Initialize the return parameter.
411 *ppvObject = 0;
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) )
419 *ppvObject = iface;
423 * Check that we obtained an interface.
425 if ((*ppvObject)==0)
427 return E_NOINTERFACE;
431 * Query Interface always increases the reference count by one when it is
432 * successful.
434 IUnknown_AddRef((IUnknown*)*ppvObject);
436 return S_OK;
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;
461 ULONG ref;
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);
474 return ref;
477 /************************************************************************
478 * DataAdviseHolder_Advise
481 static HRESULT WINAPI DataAdviseHolder_Advise(
482 IDataAdviseHolder* iface,
483 IDataObject* pDataObject,
484 FORMATETC* pFetc,
485 DWORD advf,
486 IAdviseSink* pAdvise,
487 DWORD* pdwConnection)
489 DWORD index;
491 DataAdviseHolder *This = (DataAdviseHolder *)iface;
493 TRACE("(%p)->(%p, %p, %08lx, %p, %p)\n", This, pDataObject, pFetc, advf,
494 pAdvise, pdwConnection);
496 * Sanity check
498 if (pdwConnection==NULL)
499 return E_POINTER;
501 *pdwConnection = 0;
504 * Find a free spot in the array.
506 for (index = 0; index < This->maxCons; index++)
508 if (This->Connections[index].sink == NULL)
509 break;
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,
519 This->Connections,
520 This->maxCons*sizeof(DataAdviseConnection));
523 * Store the new sink
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;
542 return S_OK;
545 /******************************************************************************
546 * DataAdviseHolder_Unadvise
548 static HRESULT WINAPI DataAdviseHolder_Unadvise(
549 IDataAdviseHolder* iface,
550 DWORD dwConnection)
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.
561 dwConnection--;
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));
577 return S_OK;
580 static HRESULT WINAPI DataAdviseHolder_EnumAdvise(
581 IDataAdviseHolder* iface,
582 IEnumSTATDATA** ppenumAdvise)
584 DataAdviseHolder *This = (DataAdviseHolder *)iface;
586 FIXME("(%p)->(%p)\n", This, ppenumAdvise);
587 return E_NOTIMPL;
590 /******************************************************************************
591 * DataAdviseHolder_SendOnDataChange
593 static HRESULT WINAPI DataAdviseHolder_SendOnDataChange(
594 IDataAdviseHolder* iface,
595 IDataObject* pDataObject,
596 DWORD dwReserved,
597 DWORD advf)
599 DataAdviseHolder *This = (DataAdviseHolder *)iface;
600 DWORD index;
601 STGMEDIUM stg;
602 HRESULT res;
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),
612 &stg);
613 TRACE("returns %08lx\n", res);
615 TRACE("Calling IAdviseSink_OnDataChange\n");
616 IAdviseSink_OnDataChange(This->Connections[index].sink,
617 &(This->Connections[index].fmat),
618 &stg);
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);
626 return S_OK;
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;
646 DWORD index;
647 HRESULT hr = S_OK;
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 */
662 return hr;
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;
680 newHolder->ref = 1;
681 newHolder->maxCons = INITIAL_SINKS;
682 newHolder->Connections = HeapAlloc(GetProcessHeap(),
683 HEAP_ZERO_MEMORY,
684 newHolder->maxCons *
685 sizeof(DataAdviseConnection));
687 TRACE("returning %p\n", newHolder);
688 return (IDataAdviseHolder*)newHolder;
691 /***********************************************************************
692 * API functions
695 /***********************************************************************
696 * CreateOleAdviseHolder [OLE32.@]
698 HRESULT WINAPI CreateOleAdviseHolder(
699 LPOLEADVISEHOLDER *ppOAHolder)
701 TRACE("(%p)\n", ppOAHolder);
704 * Sanity check,
706 if (ppOAHolder==NULL)
707 return E_POINTER;
709 *ppOAHolder = OleAdviseHolderImpl_Constructor ();
711 if (*ppOAHolder != NULL)
712 return S_OK;
714 return E_OUTOFMEMORY;
717 /******************************************************************************
718 * CreateDataAdviseHolder [OLE32.@]
720 HRESULT WINAPI CreateDataAdviseHolder(
721 LPDATAADVISEHOLDER* ppDAHolder)
723 TRACE("(%p)\n", ppDAHolder);
726 * Sanity check,
728 if (ppDAHolder==NULL)
729 return E_POINTER;
731 *ppDAHolder = DataAdviseHolder_Constructor();
733 if (*ppDAHolder != NULL)
734 return S_OK;
736 return E_OUTOFMEMORY;