- Pass infoPtr around in month calendar control.
[wine/gsoc_dplay.git] / dlls / ole32 / oleobj.c
blobbfda94b90cc3d08d21dd03e218d89fd06747dc09
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();
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 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
185 return ++(This->ref);
188 /******************************************************************************
189 * OleAdviseHolderImpl_Release
191 static ULONG WINAPI OleAdviseHolderImpl_Release(
192 LPOLEADVISEHOLDER iface)
194 OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
195 ULONG ref;
196 TRACE("(%p)->(ref=%ld)\n", This, This->ref);
197 ref = InterlockedDecrement(&This->ref);
199 if (ref == 0) OleAdviseHolderImpl_Destructor(This);
201 return ref;
204 /******************************************************************************
205 * OleAdviseHolderImpl_Advise
207 static HRESULT WINAPI OleAdviseHolderImpl_Advise(
208 LPOLEADVISEHOLDER iface,
209 IAdviseSink* pAdvise,
210 DWORD* pdwConnection)
212 DWORD index;
214 OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
216 TRACE("(%p)->(%p, %p)\n", This, pAdvise, pdwConnection);
219 * Sanity check
221 if (pdwConnection==NULL)
222 return E_POINTER;
224 *pdwConnection = 0;
227 * Find a free spot in the array.
229 for (index = 0; index < This->maxSinks; index++)
231 if (This->arrayOfSinks[index]==NULL)
232 break;
236 * If the array is full, we need to grow it.
238 if (index == This->maxSinks)
240 DWORD i;
242 This->maxSinks+=INITIAL_SINKS;
244 This->arrayOfSinks = HeapReAlloc(GetProcessHeap(),
246 This->arrayOfSinks,
247 This->maxSinks*sizeof(IAdviseSink*));
249 for (i=index;i < This->maxSinks; i++)
250 This->arrayOfSinks[i]=0;
254 * Store the new sink
256 This->arrayOfSinks[index] = pAdvise;
258 if (This->arrayOfSinks[index]!=NULL)
259 IAdviseSink_AddRef(This->arrayOfSinks[index]);
262 * Return the index as the cookie.
263 * Since 0 is not a valid cookie, we will increment by
264 * 1 the index in the table.
266 *pdwConnection = index+1;
268 return S_OK;
271 /******************************************************************************
272 * OleAdviseHolderImpl_Unadvise
274 static HRESULT WINAPI OleAdviseHolderImpl_Unadvise(
275 LPOLEADVISEHOLDER iface,
276 DWORD dwConnection)
278 OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
280 TRACE("(%p)->(%lu)\n", This, dwConnection);
283 * So we don't return 0 as a cookie, the index was
284 * incremented by 1 in OleAdviseHolderImpl_Advise
285 * we have to compensate.
287 dwConnection--;
290 * Check for invalid cookies.
292 if (dwConnection >= This->maxSinks)
293 return OLE_E_NOCONNECTION;
295 if (This->arrayOfSinks[dwConnection] == NULL)
296 return OLE_E_NOCONNECTION;
299 * Release the sink and mark the spot in the list as free.
301 IAdviseSink_Release(This->arrayOfSinks[dwConnection]);
302 This->arrayOfSinks[dwConnection] = NULL;
304 return S_OK;
307 /******************************************************************************
308 * OleAdviseHolderImpl_EnumAdvise
310 static HRESULT WINAPI
311 OleAdviseHolderImpl_EnumAdvise (LPOLEADVISEHOLDER iface, IEnumSTATDATA **ppenumAdvise)
313 OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
314 FIXME("(%p)->(%p)\n", This, ppenumAdvise);
316 *ppenumAdvise = NULL;
318 return S_OK;
321 /******************************************************************************
322 * OleAdviseHolderImpl_SendOnRename
324 static HRESULT WINAPI
325 OleAdviseHolderImpl_SendOnRename (LPOLEADVISEHOLDER iface, IMoniker *pmk)
327 OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
328 FIXME("(%p)->(%p)\n", This, pmk);
331 return S_OK;
334 /******************************************************************************
335 * OleAdviseHolderImpl_SendOnSave
337 static HRESULT WINAPI
338 OleAdviseHolderImpl_SendOnSave (LPOLEADVISEHOLDER iface)
340 OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
341 FIXME("(%p)\n", This);
343 return S_OK;
346 /******************************************************************************
347 * OleAdviseHolderImpl_SendOnClose
349 static HRESULT WINAPI
350 OleAdviseHolderImpl_SendOnClose (LPOLEADVISEHOLDER iface)
352 OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
353 FIXME("(%p)\n", This);
356 return S_OK;
359 /**************************************************************************
360 * DataAdviseHolder Implementation
362 typedef struct DataAdviseConnection {
363 IAdviseSink *sink;
364 FORMATETC fmat;
365 DWORD advf;
366 } DataAdviseConnection;
368 typedef struct DataAdviseHolder
370 IDataAdviseHolderVtbl *lpVtbl;
372 DWORD ref;
373 DWORD maxCons;
374 DataAdviseConnection* Connections;
375 } DataAdviseHolder;
377 /**************************************************************************
378 * DataAdviseHolder method prototypes
380 static IDataAdviseHolder* DataAdviseHolder_Constructor();
381 static void DataAdviseHolder_Destructor(DataAdviseHolder* ptrToDestroy);
382 static HRESULT WINAPI DataAdviseHolder_QueryInterface(
383 IDataAdviseHolder* iface,
384 REFIID riid,
385 void** ppvObject);
386 static ULONG WINAPI DataAdviseHolder_AddRef(
387 IDataAdviseHolder* iface);
388 static ULONG WINAPI DataAdviseHolder_Release(
389 IDataAdviseHolder* iface);
390 static HRESULT WINAPI DataAdviseHolder_Advise(
391 IDataAdviseHolder* iface,
392 IDataObject* pDataObject,
393 FORMATETC* pFetc,
394 DWORD advf,
395 IAdviseSink* pAdvise,
396 DWORD* pdwConnection);
397 static HRESULT WINAPI DataAdviseHolder_Unadvise(
398 IDataAdviseHolder* iface,
399 DWORD dwConnection);
400 static HRESULT WINAPI DataAdviseHolder_EnumAdvise(
401 IDataAdviseHolder* iface,
402 IEnumSTATDATA** ppenumAdvise);
403 static HRESULT WINAPI DataAdviseHolder_SendOnDataChange(
404 IDataAdviseHolder* iface,
405 IDataObject* pDataObject,
406 DWORD dwReserved,
407 DWORD advf);
409 /**************************************************************************
410 * DataAdviseHolderImpl_VTable
412 static struct IDataAdviseHolderVtbl DataAdviseHolderImpl_VTable =
414 DataAdviseHolder_QueryInterface,
415 DataAdviseHolder_AddRef,
416 DataAdviseHolder_Release,
417 DataAdviseHolder_Advise,
418 DataAdviseHolder_Unadvise,
419 DataAdviseHolder_EnumAdvise,
420 DataAdviseHolder_SendOnDataChange
423 /******************************************************************************
424 * DataAdviseHolder_Constructor
426 static IDataAdviseHolder* DataAdviseHolder_Constructor()
428 DataAdviseHolder* newHolder;
430 newHolder = (DataAdviseHolder*)HeapAlloc(GetProcessHeap(),
432 sizeof(DataAdviseHolder));
434 newHolder->lpVtbl = &DataAdviseHolderImpl_VTable;
435 newHolder->ref = 1;
436 newHolder->maxCons = INITIAL_SINKS;
437 newHolder->Connections = HeapAlloc(GetProcessHeap(),
438 HEAP_ZERO_MEMORY,
439 newHolder->maxCons *
440 sizeof(DataAdviseConnection));
442 TRACE("returning %p\n", newHolder);
443 return (IDataAdviseHolder*)newHolder;
446 /******************************************************************************
447 * DataAdviseHolder_Destructor
449 static void DataAdviseHolder_Destructor(DataAdviseHolder* ptrToDestroy)
451 DWORD index;
452 TRACE("%p\n", ptrToDestroy);
454 for (index = 0; index < ptrToDestroy->maxCons; index++)
456 if (ptrToDestroy->Connections[index].sink != NULL)
458 IAdviseSink_Release(ptrToDestroy->Connections[index].sink);
459 ptrToDestroy->Connections[index].sink = NULL;
463 HeapFree(GetProcessHeap(), 0, ptrToDestroy->Connections);
464 HeapFree(GetProcessHeap(), 0, ptrToDestroy);
467 /************************************************************************
468 * DataAdviseHolder_QueryInterface (IUnknown)
470 * See Windows documentation for more details on IUnknown methods.
472 static HRESULT WINAPI DataAdviseHolder_QueryInterface(
473 IDataAdviseHolder* iface,
474 REFIID riid,
475 void** ppvObject)
477 DataAdviseHolder *This = (DataAdviseHolder *)iface;
478 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObject);
480 * Perform a sanity check on the parameters.
482 if ( (This==0) || (ppvObject==0) )
483 return E_INVALIDARG;
486 * Initialize the return parameter.
488 *ppvObject = 0;
491 * Compare the riid with the interface IDs implemented by this object.
493 if ( (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0) ||
494 (memcmp(&IID_IDataAdviseHolder, riid, sizeof(IID_IDataAdviseHolder)) == 0) )
496 *ppvObject = iface;
500 * Check that we obtained an interface.
502 if ((*ppvObject)==0)
504 return E_NOINTERFACE;
508 * Query Interface always increases the reference count by one when it is
509 * successful.
511 IUnknown_AddRef((IUnknown*)*ppvObject);
513 return S_OK;
516 /************************************************************************
517 * DataAdviseHolder_AddRef (IUnknown)
519 * See Windows documentation for more details on IUnknown methods.
521 static ULONG WINAPI DataAdviseHolder_AddRef(
522 IDataAdviseHolder* iface)
524 DataAdviseHolder *This = (DataAdviseHolder *)iface;
525 TRACE("(%p) (ref=%ld)\n", This, This->ref);
526 return InterlockedIncrement(&This->ref);
529 /************************************************************************
530 * DataAdviseHolder_Release (IUnknown)
532 * See Windows documentation for more details on IUnknown methods.
534 static ULONG WINAPI DataAdviseHolder_Release(
535 IDataAdviseHolder* iface)
537 DataAdviseHolder *This = (DataAdviseHolder *)iface;
538 ULONG ref;
539 TRACE("(%p) (ref=%ld)\n", This, This->ref);
542 * Decrease the reference count on this object.
544 ref = InterlockedDecrement(&This->ref);
547 * If the reference count goes down to 0, perform suicide.
549 if (ref==0) DataAdviseHolder_Destructor(This);
551 return ref;
554 /************************************************************************
555 * DataAdviseHolder_Advise
558 static HRESULT WINAPI DataAdviseHolder_Advise(
559 IDataAdviseHolder* iface,
560 IDataObject* pDataObject,
561 FORMATETC* pFetc,
562 DWORD advf,
563 IAdviseSink* pAdvise,
564 DWORD* pdwConnection)
566 DWORD index;
568 DataAdviseHolder *This = (DataAdviseHolder *)iface;
570 TRACE("(%p)->(%p, %p, %08lx, %p, %p)\n", This, pDataObject, pFetc, advf,
571 pAdvise, pdwConnection);
573 * Sanity check
575 if (pdwConnection==NULL)
576 return E_POINTER;
578 *pdwConnection = 0;
581 * Find a free spot in the array.
583 for (index = 0; index < This->maxCons; index++)
585 if (This->Connections[index].sink == NULL)
586 break;
590 * If the array is full, we need to grow it.
592 if (index == This->maxCons)
594 This->maxCons+=INITIAL_SINKS;
595 This->Connections = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
596 This->Connections,
597 This->maxCons*sizeof(DataAdviseConnection));
600 * Store the new sink
602 This->Connections[index].sink = pAdvise;
603 memcpy(&(This->Connections[index].fmat), pFetc, sizeof(FORMATETC));
604 This->Connections[index].advf = advf;
606 if (This->Connections[index].sink != NULL) {
607 IAdviseSink_AddRef(This->Connections[index].sink);
608 if(advf & ADVF_PRIMEFIRST) {
609 DataAdviseHolder_SendOnDataChange(iface, pDataObject, 0, advf);
613 * Return the index as the cookie.
614 * Since 0 is not a valid cookie, we will increment by
615 * 1 the index in the table.
617 *pdwConnection = index+1;
619 return S_OK;
622 /******************************************************************************
623 * DataAdviseHolder_Unadvise
625 static HRESULT WINAPI DataAdviseHolder_Unadvise(
626 IDataAdviseHolder* iface,
627 DWORD dwConnection)
629 DataAdviseHolder *This = (DataAdviseHolder *)iface;
631 TRACE("(%p)->(%lu)\n", This, dwConnection);
634 * So we don't return 0 as a cookie, the index was
635 * incremented by 1 in OleAdviseHolderImpl_Advise
636 * we have to compensate.
638 dwConnection--;
641 * Check for invalid cookies.
643 if (dwConnection >= This->maxCons)
644 return OLE_E_NOCONNECTION;
646 if (This->Connections[dwConnection].sink == NULL)
647 return OLE_E_NOCONNECTION;
650 * Release the sink and mark the spot in the list as free.
652 IAdviseSink_Release(This->Connections[dwConnection].sink);
653 memset(&(This->Connections[dwConnection]), 0, sizeof(DataAdviseConnection));
654 return S_OK;
657 static HRESULT WINAPI DataAdviseHolder_EnumAdvise(
658 IDataAdviseHolder* iface,
659 IEnumSTATDATA** ppenumAdvise)
661 DataAdviseHolder *This = (DataAdviseHolder *)iface;
663 FIXME("(%p)->(%p)\n", This, ppenumAdvise);
664 return E_NOTIMPL;
667 /******************************************************************************
668 * DataAdviseHolder_SendOnDataChange
670 static HRESULT WINAPI DataAdviseHolder_SendOnDataChange(
671 IDataAdviseHolder* iface,
672 IDataObject* pDataObject,
673 DWORD dwReserved,
674 DWORD advf)
676 DataAdviseHolder *This = (DataAdviseHolder *)iface;
677 DWORD index;
678 STGMEDIUM stg;
679 HRESULT res;
681 TRACE("(%p)->(%p,%08lx,%08lx)\n", This, pDataObject, dwReserved, advf);
683 for(index = 0; index < This->maxCons; index++) {
684 if(This->Connections[index].sink != NULL) {
685 if(!(This->Connections[index].advf & ADVF_NODATA)) {
686 TRACE("Calling IDataObject_GetData\n");
687 res = IDataObject_GetData(pDataObject,
688 &(This->Connections[index].fmat),
689 &stg);
690 TRACE("returns %08lx\n", res);
692 TRACE("Calling IAdviseSink_OnDataChange\n");
693 IAdviseSink_OnDataChange(This->Connections[index].sink,
694 &(This->Connections[index].fmat),
695 &stg);
696 TRACE("Done IAdviseSink_OnDataChange\n");
697 if(This->Connections[index].advf & ADVF_ONLYONCE) {
698 TRACE("Removing connection\n");
699 DataAdviseHolder_Unadvise(iface, index+1);
703 return S_OK;
706 /***********************************************************************
707 * API functions
710 /***********************************************************************
711 * CreateOleAdviseHolder [OLE32.@]
713 HRESULT WINAPI CreateOleAdviseHolder(
714 LPOLEADVISEHOLDER *ppOAHolder)
716 TRACE("(%p)\n", ppOAHolder);
719 * Sanity check,
721 if (ppOAHolder==NULL)
722 return E_POINTER;
724 *ppOAHolder = OleAdviseHolderImpl_Constructor ();
726 if (*ppOAHolder != NULL)
727 return S_OK;
729 return E_OUTOFMEMORY;
732 /******************************************************************************
733 * CreateDataAdviseHolder [OLE32.@]
735 HRESULT WINAPI CreateDataAdviseHolder(
736 LPDATAADVISEHOLDER* ppDAHolder)
738 TRACE("(%p)\n", ppDAHolder);
741 * Sanity check,
743 if (ppDAHolder==NULL)
744 return E_POINTER;
746 *ppDAHolder = DataAdviseHolder_Constructor();
748 if (*ppDAHolder != NULL)
749 return S_OK;
751 return E_OUTOFMEMORY;