Improve {Uninstall,Install}ColorProfile{A,W}.
[wine] / dlls / ole32 / oleobj.c
1 /*
2  *      OLE2 COM objects
3  *
4  *      Copyright 1998 Eric Kohl
5  *      Copyright 1999 Francis Beaudet
6  *
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.
11  *
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.
16  *
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
20  */
21
22
23 #include <stdarg.h>
24 #include <string.h>
25
26 #define COBJMACROS
27
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"
34
35 WINE_DEFAULT_DEBUG_CHANNEL(ole);
36
37 #define INITIAL_SINKS 10
38
39 /**************************************************************************
40  *  OleAdviseHolderImpl Implementation
41  */
42 typedef struct OleAdviseHolderImpl
43 {
44   IOleAdviseHolderVtbl *lpVtbl;
45
46   DWORD ref;
47
48   DWORD         maxSinks;
49   IAdviseSink** arrayOfSinks;
50
51 } OleAdviseHolderImpl;
52
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);
64
65
66 /**************************************************************************
67  *  OleAdviseHolderImpl_VTable
68  */
69 static struct IOleAdviseHolderVtbl oahvt =
70 {
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
80 };
81
82 /**************************************************************************
83  *  OleAdviseHolderImpl_Constructor
84  */
85
86 static LPOLEADVISEHOLDER OleAdviseHolderImpl_Constructor()
87 {
88   OleAdviseHolderImpl* lpoah;
89   DWORD                index;
90
91   lpoah= (OleAdviseHolderImpl*)HeapAlloc(GetProcessHeap(),
92                                          0,
93                                          sizeof(OleAdviseHolderImpl));
94
95   lpoah->lpVtbl = &oahvt;
96   lpoah->ref = 1;
97   lpoah->maxSinks = INITIAL_SINKS;
98   lpoah->arrayOfSinks = HeapAlloc(GetProcessHeap(),
99                                   0,
100                                   lpoah->maxSinks * sizeof(IAdviseSink*));
101
102   for (index = 0; index < lpoah->maxSinks; index++)
103     lpoah->arrayOfSinks[index]=0;
104
105   TRACE("returning %p\n", lpoah);
106   return (LPOLEADVISEHOLDER)lpoah;
107 }
108
109 /**************************************************************************
110  *  OleAdviseHolderImpl_Destructor
111  */
112 static void OleAdviseHolderImpl_Destructor(
113   OleAdviseHolderImpl* ptrToDestroy)
114 {
115   DWORD index;
116   TRACE("%p\n", ptrToDestroy);
117
118   for (index = 0; index < ptrToDestroy->maxSinks; index++)
119   {
120     if (ptrToDestroy->arrayOfSinks[index]!=0)
121     {
122       IAdviseSink_Release(ptrToDestroy->arrayOfSinks[index]);
123       ptrToDestroy->arrayOfSinks[index] = NULL;
124     }
125   }
126
127   HeapFree(GetProcessHeap(),
128            0,
129            ptrToDestroy->arrayOfSinks);
130
131
132   HeapFree(GetProcessHeap(),
133            0,
134            ptrToDestroy);
135 }
136
137 /**************************************************************************
138  *  OleAdviseHolderImpl_QueryInterface
139  */
140 static HRESULT WINAPI OleAdviseHolderImpl_QueryInterface(
141   LPOLEADVISEHOLDER iface,
142   REFIID            riid,
143   LPVOID*           ppvObj)
144 {
145   OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
146   TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObj);
147   /*
148    * Sanity check
149    */
150   if (ppvObj==NULL)
151     return E_POINTER;
152
153   *ppvObj = NULL;
154
155   if (IsEqualIID(riid, &IID_IUnknown))
156   {
157     /* IUnknown */
158     *ppvObj = This;
159   }
160   else if(IsEqualIID(riid, &IID_IOleAdviseHolder))
161   {
162     /* IOleAdviseHolder */
163     *ppvObj = (IOleAdviseHolder*) This;
164   }
165
166   if(*ppvObj == NULL)
167     return E_NOINTERFACE;
168
169   /*
170    * A successful QI always increments the reference count.
171    */
172   IUnknown_AddRef((IUnknown*)*ppvObj);
173
174   return S_OK;
175 }
176
177 /******************************************************************************
178  * OleAdviseHolderImpl_AddRef
179  */
180 static ULONG WINAPI OleAdviseHolderImpl_AddRef(
181   LPOLEADVISEHOLDER iface)
182 {
183   OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
184   TRACE("(%p)->(ref=%ld)\n", This, This->ref);
185   return ++(This->ref);
186 }
187
188 /******************************************************************************
189  * OleAdviseHolderImpl_Release
190  */
191 static ULONG WINAPI OleAdviseHolderImpl_Release(
192   LPOLEADVISEHOLDER iface)
193 {
194   OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
195   ULONG ref;
196   TRACE("(%p)->(ref=%ld)\n", This, This->ref);
197   ref = InterlockedDecrement(&This->ref);
198
199   if (ref == 0) OleAdviseHolderImpl_Destructor(This);
200
201   return ref;
202 }
203
204 /******************************************************************************
205  * OleAdviseHolderImpl_Advise
206  */
207 static HRESULT WINAPI OleAdviseHolderImpl_Advise(
208   LPOLEADVISEHOLDER iface,
209   IAdviseSink*      pAdvise,
210   DWORD*            pdwConnection)
211 {
212   DWORD index;
213
214   OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
215
216   TRACE("(%p)->(%p, %p)\n", This, pAdvise, pdwConnection);
217
218   /*
219    * Sanity check
220    */
221   if (pdwConnection==NULL)
222     return E_POINTER;
223
224   *pdwConnection = 0;
225
226   /*
227    * Find a free spot in the array.
228    */
229   for (index = 0; index < This->maxSinks; index++)
230   {
231     if (This->arrayOfSinks[index]==NULL)
232       break;
233   }
234
235   /*
236    * If the array is full, we need to grow it.
237    */
238   if (index == This->maxSinks)
239   {
240     DWORD i;
241
242     This->maxSinks+=INITIAL_SINKS;
243
244     This->arrayOfSinks = HeapReAlloc(GetProcessHeap(),
245                                      0,
246                                      This->arrayOfSinks,
247                                      This->maxSinks*sizeof(IAdviseSink*));
248
249     for (i=index;i < This->maxSinks; i++)
250       This->arrayOfSinks[i]=0;
251   }
252
253   /*
254    * Store the new sink
255    */
256   This->arrayOfSinks[index] = pAdvise;
257
258   if (This->arrayOfSinks[index]!=NULL)
259     IAdviseSink_AddRef(This->arrayOfSinks[index]);
260
261   /*
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.
265    */
266   *pdwConnection = index+1;
267
268   return S_OK;
269 }
270
271 /******************************************************************************
272  * OleAdviseHolderImpl_Unadvise
273  */
274 static HRESULT WINAPI OleAdviseHolderImpl_Unadvise(
275   LPOLEADVISEHOLDER iface,
276   DWORD             dwConnection)
277 {
278   OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
279
280   TRACE("(%p)->(%lu)\n", This, dwConnection);
281
282   /*
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.
286    */
287   dwConnection--;
288
289   /*
290    * Check for invalid cookies.
291    */
292   if (dwConnection >= This->maxSinks)
293     return OLE_E_NOCONNECTION;
294
295   if (This->arrayOfSinks[dwConnection] == NULL)
296     return OLE_E_NOCONNECTION;
297
298   /*
299    * Release the sink and mark the spot in the list as free.
300    */
301   IAdviseSink_Release(This->arrayOfSinks[dwConnection]);
302   This->arrayOfSinks[dwConnection] = NULL;
303
304   return S_OK;
305 }
306
307 /******************************************************************************
308  * OleAdviseHolderImpl_EnumAdvise
309  */
310 static HRESULT WINAPI
311 OleAdviseHolderImpl_EnumAdvise (LPOLEADVISEHOLDER iface, IEnumSTATDATA **ppenumAdvise)
312 {
313     OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
314     FIXME("(%p)->(%p)\n", This, ppenumAdvise);
315
316     *ppenumAdvise = NULL;
317
318     return S_OK;
319 }
320
321 /******************************************************************************
322  * OleAdviseHolderImpl_SendOnRename
323  */
324 static HRESULT WINAPI
325 OleAdviseHolderImpl_SendOnRename (LPOLEADVISEHOLDER iface, IMoniker *pmk)
326 {
327     OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
328     FIXME("(%p)->(%p)\n", This, pmk);
329
330
331     return S_OK;
332 }
333
334 /******************************************************************************
335  * OleAdviseHolderImpl_SendOnSave
336  */
337 static HRESULT WINAPI
338 OleAdviseHolderImpl_SendOnSave (LPOLEADVISEHOLDER iface)
339 {
340     OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
341     FIXME("(%p)\n", This);
342
343     return S_OK;
344 }
345
346 /******************************************************************************
347  * OleAdviseHolderImpl_SendOnClose
348  */
349 static HRESULT WINAPI
350 OleAdviseHolderImpl_SendOnClose (LPOLEADVISEHOLDER iface)
351 {
352     OleAdviseHolderImpl *This = (OleAdviseHolderImpl *)iface;
353     FIXME("(%p)\n", This);
354
355
356     return S_OK;
357 }
358
359 /**************************************************************************
360  *  DataAdviseHolder Implementation
361  */
362 typedef struct DataAdviseConnection {
363   IAdviseSink *sink;
364   FORMATETC fmat;
365   DWORD advf;
366 } DataAdviseConnection;
367
368 typedef struct DataAdviseHolder
369 {
370   IDataAdviseHolderVtbl *lpVtbl;
371
372   DWORD                 ref;
373   DWORD                 maxCons;
374   DataAdviseConnection* Connections;
375 } DataAdviseHolder;
376
377 /**************************************************************************
378  *  DataAdviseHolder method prototypes
379  */
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);
408
409 /**************************************************************************
410  *  DataAdviseHolderImpl_VTable
411  */
412 static struct IDataAdviseHolderVtbl DataAdviseHolderImpl_VTable =
413 {
414   DataAdviseHolder_QueryInterface,
415   DataAdviseHolder_AddRef,
416   DataAdviseHolder_Release,
417   DataAdviseHolder_Advise,
418   DataAdviseHolder_Unadvise,
419   DataAdviseHolder_EnumAdvise,
420   DataAdviseHolder_SendOnDataChange
421 };
422
423 /******************************************************************************
424  * DataAdviseHolder_Constructor
425  */
426 static IDataAdviseHolder* DataAdviseHolder_Constructor()
427 {
428   DataAdviseHolder* newHolder;
429
430   newHolder = (DataAdviseHolder*)HeapAlloc(GetProcessHeap(),
431                                            0,
432                                            sizeof(DataAdviseHolder));
433
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));
441
442   TRACE("returning %p\n", newHolder);
443   return (IDataAdviseHolder*)newHolder;
444 }
445
446 /******************************************************************************
447  * DataAdviseHolder_Destructor
448  */
449 static void DataAdviseHolder_Destructor(DataAdviseHolder* ptrToDestroy)
450 {
451   DWORD index;
452   TRACE("%p\n", ptrToDestroy);
453
454   for (index = 0; index < ptrToDestroy->maxCons; index++)
455   {
456     if (ptrToDestroy->Connections[index].sink != NULL)
457     {
458       IAdviseSink_Release(ptrToDestroy->Connections[index].sink);
459       ptrToDestroy->Connections[index].sink = NULL;
460     }
461   }
462
463   HeapFree(GetProcessHeap(), 0, ptrToDestroy->Connections);
464   HeapFree(GetProcessHeap(), 0, ptrToDestroy);
465 }
466
467 /************************************************************************
468  * DataAdviseHolder_QueryInterface (IUnknown)
469  *
470  * See Windows documentation for more details on IUnknown methods.
471  */
472 static HRESULT WINAPI DataAdviseHolder_QueryInterface(
473   IDataAdviseHolder*      iface,
474   REFIID                  riid,
475   void**                  ppvObject)
476 {
477   DataAdviseHolder *This = (DataAdviseHolder *)iface;
478   TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObject);
479   /*
480    * Perform a sanity check on the parameters.
481    */
482   if ( (This==0) || (ppvObject==0) )
483     return E_INVALIDARG;
484
485   /*
486    * Initialize the return parameter.
487    */
488   *ppvObject = 0;
489
490   /*
491    * Compare the riid with the interface IDs implemented by this object.
492    */
493   if ( (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0) ||
494        (memcmp(&IID_IDataAdviseHolder, riid, sizeof(IID_IDataAdviseHolder)) == 0)  )
495   {
496     *ppvObject = iface;
497   }
498
499   /*
500    * Check that we obtained an interface.
501    */
502   if ((*ppvObject)==0)
503   {
504     return E_NOINTERFACE;
505   }
506
507   /*
508    * Query Interface always increases the reference count by one when it is
509    * successful.
510    */
511   IUnknown_AddRef((IUnknown*)*ppvObject);
512
513   return S_OK;
514 }
515
516 /************************************************************************
517  * DataAdviseHolder_AddRef (IUnknown)
518  *
519  * See Windows documentation for more details on IUnknown methods.
520  */
521 static ULONG WINAPI       DataAdviseHolder_AddRef(
522   IDataAdviseHolder*      iface)
523 {
524   DataAdviseHolder *This = (DataAdviseHolder *)iface;
525   TRACE("(%p) (ref=%ld)\n", This, This->ref);
526   return InterlockedIncrement(&This->ref);
527 }
528
529 /************************************************************************
530  * DataAdviseHolder_Release (IUnknown)
531  *
532  * See Windows documentation for more details on IUnknown methods.
533  */
534 static ULONG WINAPI DataAdviseHolder_Release(
535   IDataAdviseHolder*      iface)
536 {
537   DataAdviseHolder *This = (DataAdviseHolder *)iface;
538   ULONG ref;
539   TRACE("(%p) (ref=%ld)\n", This, This->ref);
540
541   /*
542    * Decrease the reference count on this object.
543    */
544   ref = InterlockedDecrement(&This->ref);
545
546   /*
547    * If the reference count goes down to 0, perform suicide.
548    */
549   if (ref==0) DataAdviseHolder_Destructor(This);
550
551   return ref;
552 }
553
554 /************************************************************************
555  * DataAdviseHolder_Advise
556  *
557  */
558 static HRESULT WINAPI DataAdviseHolder_Advise(
559   IDataAdviseHolder*      iface,
560   IDataObject*            pDataObject,
561   FORMATETC*              pFetc,
562   DWORD                   advf,
563   IAdviseSink*            pAdvise,
564   DWORD*                  pdwConnection)
565 {
566   DWORD index;
567
568   DataAdviseHolder *This = (DataAdviseHolder *)iface;
569
570   TRACE("(%p)->(%p, %p, %08lx, %p, %p)\n", This, pDataObject, pFetc, advf,
571         pAdvise, pdwConnection);
572   /*
573    * Sanity check
574    */
575   if (pdwConnection==NULL)
576     return E_POINTER;
577
578   *pdwConnection = 0;
579
580   /*
581    * Find a free spot in the array.
582    */
583   for (index = 0; index < This->maxCons; index++)
584   {
585     if (This->Connections[index].sink == NULL)
586       break;
587   }
588
589   /*
590    * If the array is full, we need to grow it.
591    */
592   if (index == This->maxCons)
593   {
594     This->maxCons+=INITIAL_SINKS;
595     This->Connections = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
596                                     This->Connections,
597                                     This->maxCons*sizeof(DataAdviseConnection));
598   }
599   /*
600    * Store the new sink
601    */
602   This->Connections[index].sink = pAdvise;
603   memcpy(&(This->Connections[index].fmat), pFetc, sizeof(FORMATETC));
604   This->Connections[index].advf = advf;
605
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);
610     }
611   }
612   /*
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.
616    */
617   *pdwConnection = index+1;
618
619   return S_OK;
620 }
621
622 /******************************************************************************
623  * DataAdviseHolder_Unadvise
624  */
625 static HRESULT WINAPI     DataAdviseHolder_Unadvise(
626   IDataAdviseHolder*      iface,
627   DWORD                   dwConnection)
628 {
629   DataAdviseHolder *This = (DataAdviseHolder *)iface;
630
631   TRACE("(%p)->(%lu)\n", This, dwConnection);
632
633   /*
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.
637    */
638   dwConnection--;
639
640   /*
641    * Check for invalid cookies.
642    */
643   if (dwConnection >= This->maxCons)
644     return OLE_E_NOCONNECTION;
645
646   if (This->Connections[dwConnection].sink == NULL)
647     return OLE_E_NOCONNECTION;
648
649   /*
650    * Release the sink and mark the spot in the list as free.
651    */
652   IAdviseSink_Release(This->Connections[dwConnection].sink);
653   memset(&(This->Connections[dwConnection]), 0, sizeof(DataAdviseConnection));
654   return S_OK;
655 }
656
657 static HRESULT WINAPI     DataAdviseHolder_EnumAdvise(
658   IDataAdviseHolder*      iface,
659   IEnumSTATDATA**         ppenumAdvise)
660 {
661   DataAdviseHolder *This = (DataAdviseHolder *)iface;
662
663   FIXME("(%p)->(%p)\n", This, ppenumAdvise);
664   return E_NOTIMPL;
665 }
666
667 /******************************************************************************
668  * DataAdviseHolder_SendOnDataChange
669  */
670 static HRESULT WINAPI     DataAdviseHolder_SendOnDataChange(
671   IDataAdviseHolder*      iface,
672   IDataObject*            pDataObject,
673   DWORD                   dwReserved,
674   DWORD                   advf)
675 {
676   DataAdviseHolder *This = (DataAdviseHolder *)iface;
677   DWORD index;
678   STGMEDIUM stg;
679   HRESULT res;
680
681   TRACE("(%p)->(%p,%08lx,%08lx)\n", This, pDataObject, dwReserved, advf);
682
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);
691       }
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);
700       }
701     }
702   }
703   return S_OK;
704 }
705
706 /***********************************************************************
707  * API functions
708  */
709
710 /***********************************************************************
711  * CreateOleAdviseHolder [OLE32.@]
712  */
713 HRESULT WINAPI CreateOleAdviseHolder(
714   LPOLEADVISEHOLDER *ppOAHolder)
715 {
716   TRACE("(%p)\n", ppOAHolder);
717
718   /*
719    * Sanity check,
720    */
721   if (ppOAHolder==NULL)
722     return E_POINTER;
723
724   *ppOAHolder = OleAdviseHolderImpl_Constructor ();
725
726   if (*ppOAHolder != NULL)
727     return S_OK;
728
729   return E_OUTOFMEMORY;
730 }
731
732 /******************************************************************************
733  *              CreateDataAdviseHolder        [OLE32.@]
734  */
735 HRESULT WINAPI CreateDataAdviseHolder(
736   LPDATAADVISEHOLDER* ppDAHolder)
737 {
738   TRACE("(%p)\n", ppDAHolder);
739
740   /*
741    * Sanity check,
742    */
743   if (ppDAHolder==NULL)
744     return E_POINTER;
745
746   *ppDAHolder = DataAdviseHolder_Constructor();
747
748   if (*ppDAHolder != NULL)
749     return S_OK;
750
751   return E_OUTOFMEMORY;
752 }