The COM virtual tables must use the
[wine] / dlls / ole32 / oleobj.c
1 /*
2  *      OLE2 COM objects
3  *
4  *      Copyright 1998 Eric Kohl
5  *      Copyright 1999 Francis Beaudet
6  */
7
8
9 #include <string.h>
10 #include "winbase.h"
11 #include "winerror.h"
12 #include "oleidl.h"
13 #include "debugtools.h"
14
15 DEFAULT_DEBUG_CHANNEL(ole)
16
17
18 /**************************************************************************
19  *  OleAdviseHolderImpl Implementation
20  */
21 typedef struct OleAdviseHolderImpl
22 {
23   ICOM_VFIELD(IOleAdviseHolder);
24
25   DWORD ref;
26
27   DWORD         maxSinks;
28   IAdviseSink** arrayOfSinks;
29
30 } OleAdviseHolderImpl;
31
32 static LPOLEADVISEHOLDER OleAdviseHolderImpl_Constructor();
33 static void              OleAdviseHolderImpl_Destructor(OleAdviseHolderImpl* ptrToDestroy);
34 static HRESULT WINAPI    OleAdviseHolderImpl_QueryInterface(LPOLEADVISEHOLDER,REFIID,LPVOID*);
35 static ULONG WINAPI      OleAdviseHolderImpl_AddRef(LPOLEADVISEHOLDER);
36 static ULONG WINAPI      OleAdviseHolderImpl_Release(LPOLEADVISEHOLDER);
37 static HRESULT WINAPI    OleAdviseHolderImpl_Advise(LPOLEADVISEHOLDER, IAdviseSink*, DWORD*);
38 static HRESULT WINAPI    OleAdviseHolderImpl_Unadvise (LPOLEADVISEHOLDER, DWORD);
39 static HRESULT WINAPI    OleAdviseHolderImpl_EnumAdvise (LPOLEADVISEHOLDER, IEnumSTATDATA **);
40 static HRESULT WINAPI    OleAdviseHolderImpl_SendOnRename (LPOLEADVISEHOLDER, IMoniker *);
41 static HRESULT WINAPI    OleAdviseHolderImpl_SendOnSave (LPOLEADVISEHOLDER);
42 static HRESULT WINAPI    OleAdviseHolderImpl_SendOnClose (LPOLEADVISEHOLDER);
43
44
45 /**************************************************************************
46  *  OleAdviseHolderImpl_VTable
47  */
48 static struct ICOM_VTABLE(IOleAdviseHolder) oahvt =
49 {
50     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
51     OleAdviseHolderImpl_QueryInterface,
52     OleAdviseHolderImpl_AddRef,
53     OleAdviseHolderImpl_Release,
54     OleAdviseHolderImpl_Advise,
55     OleAdviseHolderImpl_Unadvise,
56     OleAdviseHolderImpl_EnumAdvise,
57     OleAdviseHolderImpl_SendOnRename,
58     OleAdviseHolderImpl_SendOnSave,
59     OleAdviseHolderImpl_SendOnClose
60 };
61
62 /**************************************************************************
63  *  OleAdviseHolderImpl_Constructor
64  */
65
66 static LPOLEADVISEHOLDER OleAdviseHolderImpl_Constructor()
67 {
68   OleAdviseHolderImpl* lpoah;
69   DWORD                index;
70
71   lpoah= (OleAdviseHolderImpl*)HeapAlloc(GetProcessHeap(),
72                                          0,
73                                          sizeof(OleAdviseHolderImpl));
74   
75   ICOM_VTBL(lpoah) = &oahvt;
76   lpoah->ref = 1;
77   lpoah->maxSinks = 10;
78   lpoah->arrayOfSinks = HeapAlloc(GetProcessHeap(),
79                                   0,
80                                   lpoah->maxSinks * sizeof(IAdviseSink*));
81
82   for (index = 0; index < lpoah->maxSinks; index++)
83     lpoah->arrayOfSinks[index]=0;
84
85   return (LPOLEADVISEHOLDER)lpoah;
86 }
87
88 /**************************************************************************
89  *  OleAdviseHolderImpl_Destructor
90  */
91 static void OleAdviseHolderImpl_Destructor(
92   OleAdviseHolderImpl* ptrToDestroy)
93 {
94   DWORD index;
95
96   for (index = 0; index < ptrToDestroy->maxSinks; index++)
97   {
98     if (ptrToDestroy->arrayOfSinks[index]!=0)
99     {
100       IAdviseSink_Release(ptrToDestroy->arrayOfSinks[index]);
101       ptrToDestroy->arrayOfSinks[index] = NULL;
102     }
103   }
104   
105   HeapFree(GetProcessHeap(),
106            0,
107            ptrToDestroy->arrayOfSinks);
108   
109
110   HeapFree(GetProcessHeap(),
111            0,
112            ptrToDestroy);
113 }
114
115 /**************************************************************************
116  *  OleAdviseHolderImpl_QueryInterface
117  */
118 static HRESULT WINAPI OleAdviseHolderImpl_QueryInterface(
119   LPOLEADVISEHOLDER iface,
120   REFIID            riid, 
121   LPVOID*           ppvObj)
122 {
123   ICOM_THIS(OleAdviseHolderImpl, iface); 
124
125   /*
126    * Sanity check
127    */
128   if (ppvObj==NULL)
129     return E_POINTER;
130
131   *ppvObj = NULL;
132
133   if (IsEqualIID(riid, &IID_IUnknown)) 
134   {
135     /* IUnknown */
136     *ppvObj = This; 
137   }
138   else if(IsEqualIID(riid, &IID_IOleAdviseHolder)) 
139   {
140     /* IOleAdviseHolder */
141     *ppvObj = (IOleAdviseHolder*) This;
142   }
143
144   if(*ppvObj == NULL)
145     return E_NOINTERFACE;
146   
147   /*
148    * A successful QI always increments the reference count.
149    */
150   IUnknown_AddRef((IUnknown*)*ppvObj);
151
152   return S_OK;
153 }
154
155 /******************************************************************************
156  * OleAdviseHolderImpl_AddRef
157  */
158 static ULONG WINAPI OleAdviseHolderImpl_AddRef(
159   LPOLEADVISEHOLDER iface)
160 {
161   ICOM_THIS(OleAdviseHolderImpl, iface); 
162   
163   return ++(This->ref);
164 }
165
166 /******************************************************************************
167  * OleAdviseHolderImpl_Release
168  */
169 static ULONG WINAPI OleAdviseHolderImpl_Release(
170   LPOLEADVISEHOLDER iface)
171 {
172   ICOM_THIS(OleAdviseHolderImpl, iface); 
173
174   This->ref--;
175
176   if (This->ref == 0)
177   {
178     OleAdviseHolderImpl_Destructor(This);
179
180     return 0;
181   }
182
183   return This->ref;
184 }
185
186 /******************************************************************************
187  * OleAdviseHolderImpl_Advise
188  */
189 static HRESULT WINAPI OleAdviseHolderImpl_Advise(
190   LPOLEADVISEHOLDER iface,
191   IAdviseSink*      pAdvise,
192   DWORD*            pdwConnection)
193 {
194   DWORD index;
195   
196   ICOM_THIS(OleAdviseHolderImpl, iface); 
197
198   TRACE("(%p, %p, %p)\n", This, pAdvise, pdwConnection);
199
200   /*
201    * Sanity check
202    */
203   if (pdwConnection==NULL)
204     return E_POINTER;
205   
206   *pdwConnection = 0;
207
208   /*
209    * Find a free spot in the array.
210    */
211   for (index = 0; index < This->maxSinks; index++)
212   {
213     if (This->arrayOfSinks[index]==NULL)
214       break;
215   }
216
217   /*
218    * If the array is full, we need to grow it.
219    */
220   if (index == This->maxSinks)
221   {
222     DWORD i;
223
224     This->maxSinks+=10;
225
226     This->arrayOfSinks = HeapReAlloc(GetProcessHeap(), 
227                                      0,
228                                      This->arrayOfSinks,
229                                      This->maxSinks*sizeof(IAdviseSink*));
230
231     for (i=index;i < This->maxSinks; i++)
232       This->arrayOfSinks[i]=0;      
233   }
234
235   /*
236    * Store the new sink
237    */
238   This->arrayOfSinks[index] = pAdvise;
239
240   if (This->arrayOfSinks[index]!=NULL)
241     IAdviseSink_AddRef(This->arrayOfSinks[index]);
242
243   /*
244    * Return the index as the cookie.
245    * Since 0 is not a valid cookie, we will increment by
246    * 1 the index in the table.
247    */
248   *pdwConnection = index+1;
249
250   return S_OK;
251 }
252
253 /******************************************************************************
254  * OleAdviseHolderImpl_Unadvise
255  */
256 static HRESULT WINAPI OleAdviseHolderImpl_Unadvise(
257   LPOLEADVISEHOLDER iface, 
258   DWORD             dwConnection)
259 {
260   ICOM_THIS(OleAdviseHolderImpl, iface); 
261
262   TRACE("(%p, %lu)\n", This, dwConnection);
263
264   /*
265    * So we don't return 0 as a cookie, the index was 
266    * incremented by 1 in OleAdviseHolderImpl_Advise
267    * we have to compensate.
268    */
269   dwConnection--;
270   
271   /*
272    * Check for invalid cookies.
273    */
274   if ( (dwConnection < 0) || 
275        (dwConnection >= This->maxSinks) )
276     return OLE_E_NOCONNECTION;
277
278   if (This->arrayOfSinks[dwConnection] == NULL)
279     return OLE_E_NOCONNECTION;
280
281   /*
282    * Release the sink and mark the spot in the list as free.
283    */
284   IAdviseSink_Release(This->arrayOfSinks[dwConnection]);
285   This->arrayOfSinks[dwConnection] = NULL;
286
287   return S_OK;
288 }
289
290 /******************************************************************************
291  * OleAdviseHolderImpl_EnumAdvise
292  */
293 static HRESULT WINAPI
294 OleAdviseHolderImpl_EnumAdvise (LPOLEADVISEHOLDER iface, IEnumSTATDATA **ppenumAdvise)
295 {
296                 ICOM_THIS(OleAdviseHolderImpl, iface); 
297     FIXME("(%p)->(%p)\n", This, ppenumAdvise);
298
299     *ppenumAdvise = NULL;
300
301     return S_OK;
302 }
303
304 /******************************************************************************
305  * OleAdviseHolderImpl_SendOnRename
306  */
307 static HRESULT WINAPI
308 OleAdviseHolderImpl_SendOnRename (LPOLEADVISEHOLDER iface, IMoniker *pmk)
309 {
310                 ICOM_THIS(OleAdviseHolderImpl, iface); 
311     FIXME("(%p)->(%p)\n", This, pmk);
312
313
314     return S_OK;
315 }
316
317 /******************************************************************************
318  * OleAdviseHolderImpl_SendOnSave
319  */
320 static HRESULT WINAPI
321 OleAdviseHolderImpl_SendOnSave (LPOLEADVISEHOLDER iface)
322 {
323                 ICOM_THIS(OleAdviseHolderImpl, iface); 
324     FIXME("(%p)\n", This);
325
326
327     return S_OK;
328 }
329
330 /******************************************************************************
331  * OleAdviseHolderImpl_SendOnClose
332  */
333 static HRESULT WINAPI
334 OleAdviseHolderImpl_SendOnClose (LPOLEADVISEHOLDER iface)
335 {
336   ICOM_THIS(OleAdviseHolderImpl, iface); 
337     FIXME("(%p)\n", This);
338
339
340     return S_OK;
341 }
342
343 /**************************************************************************
344  *  DataAdviseHolder Implementation
345  */
346 typedef struct DataAdviseHolder
347 {
348   ICOM_VFIELD(IDataAdviseHolder);
349
350   DWORD ref;
351 } DataAdviseHolder;
352
353 /**************************************************************************
354  *  DataAdviseHolder method prototypes
355  */
356 static IDataAdviseHolder* DataAdviseHolder_Constructor();
357 static void               DataAdviseHolder_Destructor(DataAdviseHolder* ptrToDestroy);
358 static HRESULT WINAPI     DataAdviseHolder_QueryInterface(
359                             IDataAdviseHolder*      iface,
360                             REFIID                  riid,
361                             void**                  ppvObject);
362 static ULONG WINAPI       DataAdviseHolder_AddRef( 
363                             IDataAdviseHolder*      iface);
364 static ULONG WINAPI       DataAdviseHolder_Release( 
365                             IDataAdviseHolder*      iface);
366 static HRESULT WINAPI     DataAdviseHolder_Advise( 
367                             IDataAdviseHolder*      iface,
368                             IDataObject*            pDataObject, 
369                             FORMATETC*              pFetc, 
370                             DWORD                   advf, 
371                             IAdviseSink*            pAdvise, 
372                             DWORD*                  pdwConnection);
373 static HRESULT WINAPI     DataAdviseHolder_Unadvise( 
374                             IDataAdviseHolder*      iface,
375                             DWORD                   dwConnection);
376 static HRESULT WINAPI     DataAdviseHolder_EnumAdvise( 
377                             IDataAdviseHolder*      iface,       
378                             IEnumSTATDATA**         ppenumAdvise);
379 static HRESULT WINAPI     DataAdviseHolder_SendOnDataChange( 
380                             IDataAdviseHolder*      iface, 
381                             IDataObject*            pDataObject, 
382                             DWORD                   dwReserved, 
383                             DWORD                   advf);
384
385 /**************************************************************************
386  *  DataAdviseHolderImpl_VTable
387  */
388 static struct ICOM_VTABLE(IDataAdviseHolder) DataAdviseHolderImpl_VTable =
389 {
390   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
391   DataAdviseHolder_QueryInterface,
392   DataAdviseHolder_AddRef,
393   DataAdviseHolder_Release,
394   DataAdviseHolder_Advise,
395   DataAdviseHolder_Unadvise,
396   DataAdviseHolder_EnumAdvise,
397   DataAdviseHolder_SendOnDataChange
398 };
399
400 /******************************************************************************
401  * DataAdviseHolder_Constructor
402  */
403 static IDataAdviseHolder* DataAdviseHolder_Constructor()
404 {
405   DataAdviseHolder* newHolder;
406
407   newHolder = (DataAdviseHolder*)HeapAlloc(GetProcessHeap(),
408                                            0,
409                                            sizeof(DataAdviseHolder));
410   
411   ICOM_VTBL(newHolder) = &DataAdviseHolderImpl_VTable;
412   newHolder->ref = 1;
413
414   return (IDataAdviseHolder*)newHolder;
415 }
416
417 /******************************************************************************
418  * DataAdviseHolder_Destructor
419  */
420 static void DataAdviseHolder_Destructor(
421   DataAdviseHolder* ptrToDestroy)
422 {
423   HeapFree(GetProcessHeap(),
424            0,
425            ptrToDestroy);
426 }
427
428 /************************************************************************
429  * DataAdviseHolder_QueryInterface (IUnknown)
430  *
431  * See Windows documentation for more details on IUnknown methods.
432  */
433 static HRESULT WINAPI DataAdviseHolder_QueryInterface(
434   IDataAdviseHolder*      iface,
435   REFIID                  riid,
436   void**                  ppvObject)
437 {
438   ICOM_THIS(DataAdviseHolder, iface); 
439
440   /*
441    * Perform a sanity check on the parameters.
442    */
443   if ( (This==0) || (ppvObject==0) )
444     return E_INVALIDARG;
445   
446   /*
447    * Initialize the return parameter.
448    */
449   *ppvObject = 0;
450
451   /*
452    * Compare the riid with the interface IDs implemented by this object.
453    */
454   if ( (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0) ||
455        (memcmp(&IID_IDataAdviseHolder, riid, sizeof(IID_IDataAdviseHolder)) == 0)  )
456   {
457     *ppvObject = iface;
458   }
459   
460   /*
461    * Check that we obtained an interface.
462    */
463   if ((*ppvObject)==0)
464   {
465     return E_NOINTERFACE;
466   }
467   
468   /*
469    * Query Interface always increases the reference count by one when it is
470    * successful. 
471    */
472   IUnknown_AddRef((IUnknown*)*ppvObject);
473
474   return S_OK;;  
475 }
476
477 /************************************************************************
478  * DataAdviseHolder_AddRef (IUnknown)
479  *
480  * See Windows documentation for more details on IUnknown methods.
481  */
482 static ULONG WINAPI       DataAdviseHolder_AddRef(                             
483   IDataAdviseHolder*      iface)
484 {
485   ICOM_THIS(DataAdviseHolder, iface); 
486
487   This->ref++;
488
489   return This->ref;
490 }
491
492 /************************************************************************
493  * DataAdviseHolder_Release (IUnknown)
494  *
495  * See Windows documentation for more details on IUnknown methods.
496  */
497 static ULONG WINAPI DataAdviseHolder_Release( 
498   IDataAdviseHolder*      iface)
499 {
500   ICOM_THIS(DataAdviseHolder, iface); 
501
502   /*
503    * Decrease the reference count on this object.
504    */
505   This->ref--;
506
507   /*
508    * If the reference count goes down to 0, perform suicide.
509    */
510   if (This->ref==0)
511   {
512     DataAdviseHolder_Destructor(This);
513
514     return 0;
515   }
516   
517   return This->ref;
518 }
519
520 static HRESULT WINAPI DataAdviseHolder_Advise(
521   IDataAdviseHolder*      iface,
522   IDataObject*            pDataObject, 
523   FORMATETC*              pFetc, 
524   DWORD                   advf, 
525   IAdviseSink*            pAdvise, 
526   DWORD*                  pdwConnection)
527 {
528   FIXME("(): stub\n");
529   return E_NOTIMPL;
530 }
531
532 static HRESULT WINAPI     DataAdviseHolder_Unadvise( 
533   IDataAdviseHolder*      iface,
534   DWORD                   dwConnection)
535 {
536   FIXME("(): stub\n");
537   return E_NOTIMPL;
538 }
539
540 static HRESULT WINAPI     DataAdviseHolder_EnumAdvise( 
541   IDataAdviseHolder*      iface,       
542   IEnumSTATDATA**         ppenumAdvise)
543 {
544   FIXME("(): stub\n");
545   return E_NOTIMPL;
546 }
547
548 static HRESULT WINAPI     DataAdviseHolder_SendOnDataChange( 
549   IDataAdviseHolder*      iface, 
550   IDataObject*            pDataObject, 
551   DWORD                   dwReserved, 
552   DWORD                   advf)
553 {
554   FIXME("(): stub\n");
555   return E_NOTIMPL;
556 }
557
558 /***********************************************************************
559  * API functions
560  */
561
562 /***********************************************************************
563  * CreateOleAdviseHolder [OLE32.59]
564  */
565 HRESULT WINAPI CreateOleAdviseHolder(
566   LPOLEADVISEHOLDER *ppOAHolder)
567 {
568   TRACE("(%p)\n", ppOAHolder);
569
570   /*
571    * Sanity check,
572    */
573   if (ppOAHolder==NULL)
574     return E_POINTER;
575
576   *ppOAHolder = OleAdviseHolderImpl_Constructor ();
577
578   if (*ppOAHolder != NULL)
579     return S_OK;
580
581   return E_OUTOFMEMORY;
582 }
583
584 /******************************************************************************
585  *              CreateDataAdviseHolder        [OLE32.53]
586  */
587 HRESULT WINAPI CreateDataAdviseHolder(
588   LPDATAADVISEHOLDER* ppDAHolder)
589 {
590   TRACE("(%p)\n", ppDAHolder);
591
592   /*
593    * Sanity check,
594    */
595   if (ppDAHolder==NULL)
596     return E_POINTER;
597
598   *ppDAHolder = DataAdviseHolder_Constructor();
599
600   if (*ppDAHolder != NULL)
601     return S_OK;
602
603   return E_OUTOFMEMORY;
604 }
605