Added a missing prototype.
[wine/wine-kai.git] / dlls / ole32 / oleobj.c
blob370020feb977b1769e460b19a5908104689c9b77
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 IOleAdviseHolderVtbl *lpVtbl;
46 DWORD ref;
48 DWORD maxSinks;
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;
89 DWORD index;
91 lpoah= (OleAdviseHolderImpl*)HeapAlloc(GetProcessHeap(),
93 sizeof(OleAdviseHolderImpl));
95 lpoah->lpVtbl = &oahvt;
96 lpoah->ref = 1;
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)
115 DWORD index;
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(),
134 ptrToDestroy);
137 /**************************************************************************
138 * OleAdviseHolderImpl_QueryInterface
140 static HRESULT WINAPI OleAdviseHolderImpl_QueryInterface(
141 LPOLEADVISEHOLDER iface,
142 REFIID riid,
143 LPVOID* ppvObj)
145 OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
146 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObj);
148 * Sanity check
150 if (ppvObj==NULL)
151 return E_POINTER;
153 *ppvObj = NULL;
155 if (IsEqualIID(riid, &IID_IUnknown))
157 /* IUnknown */
158 *ppvObj = This;
160 else if(IsEqualIID(riid, &IID_IOleAdviseHolder))
162 /* IOleAdviseHolder */
163 *ppvObj = (IOleAdviseHolder*) This;
166 if(*ppvObj == NULL)
167 return E_NOINTERFACE;
170 * A successful QI always increments the reference count.
172 IUnknown_AddRef((IUnknown*)*ppvObj);
174 return S_OK;
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);
188 return ref;
191 /******************************************************************************
192 * OleAdviseHolderImpl_Release
194 static ULONG WINAPI OleAdviseHolderImpl_Release(
195 LPOLEADVISEHOLDER iface)
197 OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
198 ULONG ref;
199 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
200 ref = InterlockedDecrement(&This->ref);
202 if (ref == 0) OleAdviseHolderImpl_Destructor(This);
204 return ref;
207 /******************************************************************************
208 * OleAdviseHolderImpl_Advise
210 static HRESULT WINAPI OleAdviseHolderImpl_Advise(
211 LPOLEADVISEHOLDER iface,
212 IAdviseSink* pAdvise,
213 DWORD* pdwConnection)
215 DWORD index;
217 OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
219 TRACE("(%p)->(%p, %p)\n", This, pAdvise, pdwConnection);
222 * Sanity check
224 if (pdwConnection==NULL)
225 return E_POINTER;
227 *pdwConnection = 0;
230 * Find a free spot in the array.
232 for (index = 0; index < This->maxSinks; index++)
234 if (This->arrayOfSinks[index]==NULL)
235 break;
239 * If the array is full, we need to grow it.
241 if (index == This->maxSinks)
243 DWORD i;
245 This->maxSinks+=INITIAL_SINKS;
247 This->arrayOfSinks = HeapReAlloc(GetProcessHeap(),
249 This->arrayOfSinks,
250 This->maxSinks*sizeof(IAdviseSink*));
252 for (i=index;i < This->maxSinks; i++)
253 This->arrayOfSinks[i]=0;
257 * Store the new sink
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;
271 return S_OK;
274 /******************************************************************************
275 * OleAdviseHolderImpl_Unadvise
277 static HRESULT WINAPI OleAdviseHolderImpl_Unadvise(
278 LPOLEADVISEHOLDER iface,
279 DWORD dwConnection)
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.
290 dwConnection--;
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;
307 return S_OK;
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;
321 return S_OK;
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);
334 return S_OK;
337 /******************************************************************************
338 * OleAdviseHolderImpl_SendOnSave
340 static HRESULT WINAPI
341 OleAdviseHolderImpl_SendOnSave (LPOLEADVISEHOLDER iface)
343 OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
344 FIXME("(%p)\n", This);
346 return S_OK;
349 /******************************************************************************
350 * OleAdviseHolderImpl_SendOnClose
352 static HRESULT WINAPI
353 OleAdviseHolderImpl_SendOnClose (LPOLEADVISEHOLDER iface)
355 OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
356 FIXME("(%p)\n", This);
359 return S_OK;
362 /**************************************************************************
363 * DataAdviseHolder Implementation
365 typedef struct DataAdviseConnection {
366 IAdviseSink *sink;
367 FORMATETC fmat;
368 DWORD advf;
369 } DataAdviseConnection;
371 typedef struct DataAdviseHolder
373 IDataAdviseHolderVtbl *lpVtbl;
375 DWORD ref;
376 DWORD maxCons;
377 DataAdviseConnection* Connections;
378 } DataAdviseHolder;
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,
387 REFIID riid,
388 void** ppvObject);
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,
396 FORMATETC* pFetc,
397 DWORD advf,
398 IAdviseSink* pAdvise,
399 DWORD* pdwConnection);
400 static HRESULT WINAPI DataAdviseHolder_Unadvise(
401 IDataAdviseHolder* iface,
402 DWORD dwConnection);
403 static HRESULT WINAPI DataAdviseHolder_EnumAdvise(
404 IDataAdviseHolder* iface,
405 IEnumSTATDATA** ppenumAdvise);
406 static HRESULT WINAPI DataAdviseHolder_SendOnDataChange(
407 IDataAdviseHolder* iface,
408 IDataObject* pDataObject,
409 DWORD dwReserved,
410 DWORD advf);
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;
438 newHolder->ref = 1;
439 newHolder->maxCons = INITIAL_SINKS;
440 newHolder->Connections = HeapAlloc(GetProcessHeap(),
441 HEAP_ZERO_MEMORY,
442 newHolder->maxCons *
443 sizeof(DataAdviseConnection));
445 TRACE("returning %p\n", newHolder);
446 return (IDataAdviseHolder*)newHolder;
449 /******************************************************************************
450 * DataAdviseHolder_Destructor
452 static void DataAdviseHolder_Destructor(DataAdviseHolder* ptrToDestroy)
454 DWORD index;
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,
477 REFIID riid,
478 void** ppvObject)
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) )
486 return E_INVALIDARG;
489 * Initialize the return parameter.
491 *ppvObject = 0;
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) )
499 *ppvObject = iface;
503 * Check that we obtained an interface.
505 if ((*ppvObject)==0)
507 return E_NOINTERFACE;
511 * Query Interface always increases the reference count by one when it is
512 * successful.
514 IUnknown_AddRef((IUnknown*)*ppvObject);
516 return S_OK;
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;
541 ULONG ref;
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);
554 return ref;
557 /************************************************************************
558 * DataAdviseHolder_Advise
561 static HRESULT WINAPI DataAdviseHolder_Advise(
562 IDataAdviseHolder* iface,
563 IDataObject* pDataObject,
564 FORMATETC* pFetc,
565 DWORD advf,
566 IAdviseSink* pAdvise,
567 DWORD* pdwConnection)
569 DWORD index;
571 DataAdviseHolder *This = (DataAdviseHolder *)iface;
573 TRACE("(%p)->(%p, %p, %08lx, %p, %p)\n", This, pDataObject, pFetc, advf,
574 pAdvise, pdwConnection);
576 * Sanity check
578 if (pdwConnection==NULL)
579 return E_POINTER;
581 *pdwConnection = 0;
584 * Find a free spot in the array.
586 for (index = 0; index < This->maxCons; index++)
588 if (This->Connections[index].sink == NULL)
589 break;
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,
599 This->Connections,
600 This->maxCons*sizeof(DataAdviseConnection));
603 * Store the new sink
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;
622 return S_OK;
625 /******************************************************************************
626 * DataAdviseHolder_Unadvise
628 static HRESULT WINAPI DataAdviseHolder_Unadvise(
629 IDataAdviseHolder* iface,
630 DWORD dwConnection)
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.
641 dwConnection--;
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));
657 return S_OK;
660 static HRESULT WINAPI DataAdviseHolder_EnumAdvise(
661 IDataAdviseHolder* iface,
662 IEnumSTATDATA** ppenumAdvise)
664 DataAdviseHolder *This = (DataAdviseHolder *)iface;
666 FIXME("(%p)->(%p)\n", This, ppenumAdvise);
667 return E_NOTIMPL;
670 /******************************************************************************
671 * DataAdviseHolder_SendOnDataChange
673 static HRESULT WINAPI DataAdviseHolder_SendOnDataChange(
674 IDataAdviseHolder* iface,
675 IDataObject* pDataObject,
676 DWORD dwReserved,
677 DWORD advf)
679 DataAdviseHolder *This = (DataAdviseHolder *)iface;
680 DWORD index;
681 STGMEDIUM stg;
682 HRESULT res;
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),
692 &stg);
693 TRACE("returns %08lx\n", res);
695 TRACE("Calling IAdviseSink_OnDataChange\n");
696 IAdviseSink_OnDataChange(This->Connections[index].sink,
697 &(This->Connections[index].fmat),
698 &stg);
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);
706 return S_OK;
709 /***********************************************************************
710 * API functions
713 /***********************************************************************
714 * CreateOleAdviseHolder [OLE32.@]
716 HRESULT WINAPI CreateOleAdviseHolder(
717 LPOLEADVISEHOLDER *ppOAHolder)
719 TRACE("(%p)\n", ppOAHolder);
722 * Sanity check,
724 if (ppOAHolder==NULL)
725 return E_POINTER;
727 *ppOAHolder = OleAdviseHolderImpl_Constructor ();
729 if (*ppOAHolder != NULL)
730 return S_OK;
732 return E_OUTOFMEMORY;
735 /******************************************************************************
736 * CreateDataAdviseHolder [OLE32.@]
738 HRESULT WINAPI CreateDataAdviseHolder(
739 LPDATAADVISEHOLDER* ppDAHolder)
741 TRACE("(%p)\n", ppDAHolder);
744 * Sanity check,
746 if (ppDAHolder==NULL)
747 return E_POINTER;
749 *ppDAHolder = DataAdviseHolder_Constructor();
751 if (*ppDAHolder != NULL)
752 return S_OK;
754 return E_OUTOFMEMORY;