Implemented NetQueryDisplayInformation, NetUserGetInfo, created
[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 <string.h>
24 #include "winbase.h"
25 #include "winerror.h"
26 #include "wine/debug.h"
27 #include "oleidl.h"
28
29 WINE_DEFAULT_DEBUG_CHANNEL(ole);
30
31 #define INITIAL_SINKS 10
32
33 /**************************************************************************
34  *  OleAdviseHolderImpl Implementation
35  */
36 typedef struct OleAdviseHolderImpl
37 {
38   ICOM_VFIELD(IOleAdviseHolder);
39
40   DWORD ref;
41
42   DWORD         maxSinks;
43   IAdviseSink** arrayOfSinks;
44
45 } OleAdviseHolderImpl;
46
47 static LPOLEADVISEHOLDER OleAdviseHolderImpl_Constructor();
48 static void              OleAdviseHolderImpl_Destructor(OleAdviseHolderImpl* ptrToDestroy);
49 static HRESULT WINAPI    OleAdviseHolderImpl_QueryInterface(LPOLEADVISEHOLDER,REFIID,LPVOID*);
50 static ULONG WINAPI      OleAdviseHolderImpl_AddRef(LPOLEADVISEHOLDER);
51 static ULONG WINAPI      OleAdviseHolderImpl_Release(LPOLEADVISEHOLDER);
52 static HRESULT WINAPI    OleAdviseHolderImpl_Advise(LPOLEADVISEHOLDER, IAdviseSink*, DWORD*);
53 static HRESULT WINAPI    OleAdviseHolderImpl_Unadvise (LPOLEADVISEHOLDER, DWORD);
54 static HRESULT WINAPI    OleAdviseHolderImpl_EnumAdvise (LPOLEADVISEHOLDER, IEnumSTATDATA **);
55 static HRESULT WINAPI    OleAdviseHolderImpl_SendOnRename (LPOLEADVISEHOLDER, IMoniker *);
56 static HRESULT WINAPI    OleAdviseHolderImpl_SendOnSave (LPOLEADVISEHOLDER);
57 static HRESULT WINAPI    OleAdviseHolderImpl_SendOnClose (LPOLEADVISEHOLDER);
58
59
60 /**************************************************************************
61  *  OleAdviseHolderImpl_VTable
62  */
63 static struct ICOM_VTABLE(IOleAdviseHolder) oahvt =
64 {
65     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
66     OleAdviseHolderImpl_QueryInterface,
67     OleAdviseHolderImpl_AddRef,
68     OleAdviseHolderImpl_Release,
69     OleAdviseHolderImpl_Advise,
70     OleAdviseHolderImpl_Unadvise,
71     OleAdviseHolderImpl_EnumAdvise,
72     OleAdviseHolderImpl_SendOnRename,
73     OleAdviseHolderImpl_SendOnSave,
74     OleAdviseHolderImpl_SendOnClose
75 };
76
77 /**************************************************************************
78  *  OleAdviseHolderImpl_Constructor
79  */
80
81 static LPOLEADVISEHOLDER OleAdviseHolderImpl_Constructor()
82 {
83   OleAdviseHolderImpl* lpoah;
84   DWORD                index;
85
86   lpoah= (OleAdviseHolderImpl*)HeapAlloc(GetProcessHeap(),
87                                          0,
88                                          sizeof(OleAdviseHolderImpl));
89
90   ICOM_VTBL(lpoah) = &oahvt;
91   lpoah->ref = 1;
92   lpoah->maxSinks = INITIAL_SINKS;
93   lpoah->arrayOfSinks = HeapAlloc(GetProcessHeap(),
94                                   0,
95                                   lpoah->maxSinks * sizeof(IAdviseSink*));
96
97   for (index = 0; index < lpoah->maxSinks; index++)
98     lpoah->arrayOfSinks[index]=0;
99
100   TRACE("returning %p\n", lpoah);
101   return (LPOLEADVISEHOLDER)lpoah;
102 }
103
104 /**************************************************************************
105  *  OleAdviseHolderImpl_Destructor
106  */
107 static void OleAdviseHolderImpl_Destructor(
108   OleAdviseHolderImpl* ptrToDestroy)
109 {
110   DWORD index;
111   TRACE("%p\n", ptrToDestroy);
112
113   for (index = 0; index < ptrToDestroy->maxSinks; index++)
114   {
115     if (ptrToDestroy->arrayOfSinks[index]!=0)
116     {
117       IAdviseSink_Release(ptrToDestroy->arrayOfSinks[index]);
118       ptrToDestroy->arrayOfSinks[index] = NULL;
119     }
120   }
121
122   HeapFree(GetProcessHeap(),
123            0,
124            ptrToDestroy->arrayOfSinks);
125
126
127   HeapFree(GetProcessHeap(),
128            0,
129            ptrToDestroy);
130 }
131
132 /**************************************************************************
133  *  OleAdviseHolderImpl_QueryInterface
134  */
135 static HRESULT WINAPI OleAdviseHolderImpl_QueryInterface(
136   LPOLEADVISEHOLDER iface,
137   REFIID            riid,
138   LPVOID*           ppvObj)
139 {
140   ICOM_THIS(OleAdviseHolderImpl, iface);
141   TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObj);
142   /*
143    * Sanity check
144    */
145   if (ppvObj==NULL)
146     return E_POINTER;
147
148   *ppvObj = NULL;
149
150   if (IsEqualIID(riid, &IID_IUnknown))
151   {
152     /* IUnknown */
153     *ppvObj = This;
154   }
155   else if(IsEqualIID(riid, &IID_IOleAdviseHolder))
156   {
157     /* IOleAdviseHolder */
158     *ppvObj = (IOleAdviseHolder*) This;
159   }
160
161   if(*ppvObj == NULL)
162     return E_NOINTERFACE;
163
164   /*
165    * A successful QI always increments the reference count.
166    */
167   IUnknown_AddRef((IUnknown*)*ppvObj);
168
169   return S_OK;
170 }
171
172 /******************************************************************************
173  * OleAdviseHolderImpl_AddRef
174  */
175 static ULONG WINAPI OleAdviseHolderImpl_AddRef(
176   LPOLEADVISEHOLDER iface)
177 {
178   ICOM_THIS(OleAdviseHolderImpl, iface);
179   TRACE("(%p)->(ref=%ld)\n", This, This->ref);
180   return ++(This->ref);
181 }
182
183 /******************************************************************************
184  * OleAdviseHolderImpl_Release
185  */
186 static ULONG WINAPI OleAdviseHolderImpl_Release(
187   LPOLEADVISEHOLDER iface)
188 {
189   ICOM_THIS(OleAdviseHolderImpl, iface);
190   TRACE("(%p)->(ref=%ld)\n", This, This->ref);
191   This->ref--;
192
193   if (This->ref == 0)
194   {
195     OleAdviseHolderImpl_Destructor(This);
196
197     return 0;
198   }
199
200   return This->ref;
201 }
202
203 /******************************************************************************
204  * OleAdviseHolderImpl_Advise
205  */
206 static HRESULT WINAPI OleAdviseHolderImpl_Advise(
207   LPOLEADVISEHOLDER iface,
208   IAdviseSink*      pAdvise,
209   DWORD*            pdwConnection)
210 {
211   DWORD index;
212
213   ICOM_THIS(OleAdviseHolderImpl, iface);
214
215   TRACE("(%p)->(%p, %p)\n", This, pAdvise, pdwConnection);
216
217   /*
218    * Sanity check
219    */
220   if (pdwConnection==NULL)
221     return E_POINTER;
222
223   *pdwConnection = 0;
224
225   /*
226    * Find a free spot in the array.
227    */
228   for (index = 0; index < This->maxSinks; index++)
229   {
230     if (This->arrayOfSinks[index]==NULL)
231       break;
232   }
233
234   /*
235    * If the array is full, we need to grow it.
236    */
237   if (index == This->maxSinks)
238   {
239     DWORD i;
240
241     This->maxSinks+=INITIAL_SINKS;
242
243     This->arrayOfSinks = HeapReAlloc(GetProcessHeap(),
244                                      0,
245                                      This->arrayOfSinks,
246                                      This->maxSinks*sizeof(IAdviseSink*));
247
248     for (i=index;i < This->maxSinks; i++)
249       This->arrayOfSinks[i]=0;
250   }
251
252   /*
253    * Store the new sink
254    */
255   This->arrayOfSinks[index] = pAdvise;
256
257   if (This->arrayOfSinks[index]!=NULL)
258     IAdviseSink_AddRef(This->arrayOfSinks[index]);
259
260   /*
261    * Return the index as the cookie.
262    * Since 0 is not a valid cookie, we will increment by
263    * 1 the index in the table.
264    */
265   *pdwConnection = index+1;
266
267   return S_OK;
268 }
269
270 /******************************************************************************
271  * OleAdviseHolderImpl_Unadvise
272  */
273 static HRESULT WINAPI OleAdviseHolderImpl_Unadvise(
274   LPOLEADVISEHOLDER iface,
275   DWORD             dwConnection)
276 {
277   ICOM_THIS(OleAdviseHolderImpl, iface);
278
279   TRACE("(%p)->(%lu)\n", This, dwConnection);
280
281   /*
282    * So we don't return 0 as a cookie, the index was
283    * incremented by 1 in OleAdviseHolderImpl_Advise
284    * we have to compensate.
285    */
286   dwConnection--;
287
288   /*
289    * Check for invalid cookies.
290    */
291   if (dwConnection >= This->maxSinks)
292     return OLE_E_NOCONNECTION;
293
294   if (This->arrayOfSinks[dwConnection] == NULL)
295     return OLE_E_NOCONNECTION;
296
297   /*
298    * Release the sink and mark the spot in the list as free.
299    */
300   IAdviseSink_Release(This->arrayOfSinks[dwConnection]);
301   This->arrayOfSinks[dwConnection] = NULL;
302
303   return S_OK;
304 }
305
306 /******************************************************************************
307  * OleAdviseHolderImpl_EnumAdvise
308  */
309 static HRESULT WINAPI
310 OleAdviseHolderImpl_EnumAdvise (LPOLEADVISEHOLDER iface, IEnumSTATDATA **ppenumAdvise)
311 {
312     ICOM_THIS(OleAdviseHolderImpl, iface);
313     FIXME("(%p)->(%p)\n", This, ppenumAdvise);
314
315     *ppenumAdvise = NULL;
316
317     return S_OK;
318 }
319
320 /******************************************************************************
321  * OleAdviseHolderImpl_SendOnRename
322  */
323 static HRESULT WINAPI
324 OleAdviseHolderImpl_SendOnRename (LPOLEADVISEHOLDER iface, IMoniker *pmk)
325 {
326     ICOM_THIS(OleAdviseHolderImpl, iface);
327     FIXME("(%p)->(%p)\n", This, pmk);
328
329
330     return S_OK;
331 }
332
333 /******************************************************************************
334  * OleAdviseHolderImpl_SendOnSave
335  */
336 static HRESULT WINAPI
337 OleAdviseHolderImpl_SendOnSave (LPOLEADVISEHOLDER iface)
338 {
339     ICOM_THIS(OleAdviseHolderImpl, iface);
340     FIXME("(%p)\n", This);
341
342     return S_OK;
343 }
344
345 /******************************************************************************
346  * OleAdviseHolderImpl_SendOnClose
347  */
348 static HRESULT WINAPI
349 OleAdviseHolderImpl_SendOnClose (LPOLEADVISEHOLDER iface)
350 {
351     ICOM_THIS(OleAdviseHolderImpl, iface);
352     FIXME("(%p)\n", This);
353
354
355     return S_OK;
356 }
357
358 /**************************************************************************
359  *  DataAdviseHolder Implementation
360  */
361 typedef struct DataAdviseConnection {
362   IAdviseSink *sink;
363   FORMATETC fmat;
364   DWORD advf;
365 } DataAdviseConnection;
366
367 typedef struct DataAdviseHolder
368 {
369   ICOM_VFIELD(IDataAdviseHolder);
370
371   DWORD                 ref;
372   DWORD                 maxCons;
373   DataAdviseConnection* Connections;
374 } DataAdviseHolder;
375
376 /**************************************************************************
377  *  DataAdviseHolder method prototypes
378  */
379 static IDataAdviseHolder* DataAdviseHolder_Constructor();
380 static void               DataAdviseHolder_Destructor(DataAdviseHolder* ptrToDestroy);
381 static HRESULT WINAPI     DataAdviseHolder_QueryInterface(
382                             IDataAdviseHolder*      iface,
383                             REFIID                  riid,
384                             void**                  ppvObject);
385 static ULONG WINAPI       DataAdviseHolder_AddRef(
386                             IDataAdviseHolder*      iface);
387 static ULONG WINAPI       DataAdviseHolder_Release(
388                             IDataAdviseHolder*      iface);
389 static HRESULT WINAPI     DataAdviseHolder_Advise(
390                             IDataAdviseHolder*      iface,
391                             IDataObject*            pDataObject,
392                             FORMATETC*              pFetc,
393                             DWORD                   advf,
394                             IAdviseSink*            pAdvise,
395                             DWORD*                  pdwConnection);
396 static HRESULT WINAPI     DataAdviseHolder_Unadvise(
397                             IDataAdviseHolder*      iface,
398                             DWORD                   dwConnection);
399 static HRESULT WINAPI     DataAdviseHolder_EnumAdvise(
400                             IDataAdviseHolder*      iface,
401                             IEnumSTATDATA**         ppenumAdvise);
402 static HRESULT WINAPI     DataAdviseHolder_SendOnDataChange(
403                             IDataAdviseHolder*      iface,
404                             IDataObject*            pDataObject,
405                             DWORD                   dwReserved,
406                             DWORD                   advf);
407
408 /**************************************************************************
409  *  DataAdviseHolderImpl_VTable
410  */
411 static struct ICOM_VTABLE(IDataAdviseHolder) DataAdviseHolderImpl_VTable =
412 {
413   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
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   ICOM_VTBL(newHolder) = &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   ICOM_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   ICOM_THIS(DataAdviseHolder, iface);
525   TRACE("(%p) (ref=%ld)\n", This, This->ref);
526   This->ref++;
527
528   return This->ref;
529 }
530
531 /************************************************************************
532  * DataAdviseHolder_Release (IUnknown)
533  *
534  * See Windows documentation for more details on IUnknown methods.
535  */
536 static ULONG WINAPI DataAdviseHolder_Release(
537   IDataAdviseHolder*      iface)
538 {
539   ICOM_THIS(DataAdviseHolder, iface);
540   TRACE("(%p) (ref=%ld)\n", This, This->ref);
541
542   /*
543    * Decrease the reference count on this object.
544    */
545   This->ref--;
546
547   /*
548    * If the reference count goes down to 0, perform suicide.
549    */
550   if (This->ref==0)
551   {
552     DataAdviseHolder_Destructor(This);
553
554     return 0;
555   }
556
557   return This->ref;
558 }
559
560 /************************************************************************
561  * DataAdviseHolder_Advise
562  *
563  */
564 static HRESULT WINAPI DataAdviseHolder_Advise(
565   IDataAdviseHolder*      iface,
566   IDataObject*            pDataObject,
567   FORMATETC*              pFetc,
568   DWORD                   advf,
569   IAdviseSink*            pAdvise,
570   DWORD*                  pdwConnection)
571 {
572   DWORD index;
573
574   ICOM_THIS(DataAdviseHolder, iface);
575
576   TRACE("(%p)->(%p, %p, %08lx, %p, %p)\n", This, pDataObject, pFetc, advf,
577         pAdvise, pdwConnection);
578   /*
579    * Sanity check
580    */
581   if (pdwConnection==NULL)
582     return E_POINTER;
583
584   *pdwConnection = 0;
585
586   /*
587    * Find a free spot in the array.
588    */
589   for (index = 0; index < This->maxCons; index++)
590   {
591     if (This->Connections[index].sink == NULL)
592       break;
593   }
594
595   /*
596    * If the array is full, we need to grow it.
597    */
598   if (index == This->maxCons)
599   {
600     This->maxCons+=INITIAL_SINKS;
601     This->Connections = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
602                                     This->Connections,
603                                     This->maxCons*sizeof(DataAdviseConnection));
604   }
605   /*
606    * Store the new sink
607    */
608   This->Connections[index].sink = pAdvise;
609   memcpy(&(This->Connections[index].fmat), pFetc, sizeof(FORMATETC));
610   This->Connections[index].advf = advf;
611
612   if (This->Connections[index].sink != NULL) {
613     IAdviseSink_AddRef(This->Connections[index].sink);
614     if(advf & ADVF_PRIMEFIRST) {
615       DataAdviseHolder_SendOnDataChange(iface, pDataObject, 0, advf);
616     }
617   }
618   /*
619    * Return the index as the cookie.
620    * Since 0 is not a valid cookie, we will increment by
621    * 1 the index in the table.
622    */
623   *pdwConnection = index+1;
624
625   return S_OK;
626 }
627
628 /******************************************************************************
629  * DataAdviseHolder_Unadvise
630  */
631 static HRESULT WINAPI     DataAdviseHolder_Unadvise(
632   IDataAdviseHolder*      iface,
633   DWORD                   dwConnection)
634 {
635   ICOM_THIS(DataAdviseHolder, iface);
636
637   TRACE("(%p)->(%lu)\n", This, dwConnection);
638
639   /*
640    * So we don't return 0 as a cookie, the index was
641    * incremented by 1 in OleAdviseHolderImpl_Advise
642    * we have to compensate.
643    */
644   dwConnection--;
645
646   /*
647    * Check for invalid cookies.
648    */
649   if (dwConnection >= This->maxCons)
650     return OLE_E_NOCONNECTION;
651
652   if (This->Connections[dwConnection].sink == NULL)
653     return OLE_E_NOCONNECTION;
654
655   /*
656    * Release the sink and mark the spot in the list as free.
657    */
658   IAdviseSink_Release(This->Connections[dwConnection].sink);
659   memset(&(This->Connections[dwConnection]), 0, sizeof(DataAdviseConnection));
660   return S_OK;
661 }
662
663 static HRESULT WINAPI     DataAdviseHolder_EnumAdvise(
664   IDataAdviseHolder*      iface,
665   IEnumSTATDATA**         ppenumAdvise)
666 {
667   ICOM_THIS(DataAdviseHolder, iface);
668
669   FIXME("(%p)->(%p)\n", This, ppenumAdvise);
670   return E_NOTIMPL;
671 }
672
673 /******************************************************************************
674  * DataAdviseHolder_SendOnDataChange
675  */
676 static HRESULT WINAPI     DataAdviseHolder_SendOnDataChange(
677   IDataAdviseHolder*      iface,
678   IDataObject*            pDataObject,
679   DWORD                   dwReserved,
680   DWORD                   advf)
681 {
682   ICOM_THIS(DataAdviseHolder, iface);
683   DWORD index;
684   STGMEDIUM stg;
685   HRESULT res;
686
687   TRACE("(%p)->(%p,%08lx,%08lx)\n", This, pDataObject, dwReserved, advf);
688
689   for(index = 0; index < This->maxCons; index++) {
690     if(This->Connections[index].sink != NULL) {
691       if(!(This->Connections[index].advf & ADVF_NODATA)) {
692         TRACE("Calling IDataObject_GetData\n");
693         res = IDataObject_GetData(pDataObject,
694                                   &(This->Connections[index].fmat),
695                                   &stg);
696         TRACE("returns %08lx\n", res);
697       }
698       TRACE("Calling IAdviseSink_OnDataChange\n");
699       IAdviseSink_OnDataChange(This->Connections[index].sink,
700                                      &(This->Connections[index].fmat),
701                                      &stg);
702       TRACE("Done IAdviseSink_OnDataChange\n");
703       if(This->Connections[index].advf & ADVF_ONLYONCE) {
704         TRACE("Removing connection\n");
705         DataAdviseHolder_Unadvise(iface, index+1);
706       }
707     }
708   }
709   return S_OK;
710 }
711
712 /***********************************************************************
713  * API functions
714  */
715
716 /***********************************************************************
717  * CreateOleAdviseHolder [OLE32.59]
718  */
719 HRESULT WINAPI CreateOleAdviseHolder(
720   LPOLEADVISEHOLDER *ppOAHolder)
721 {
722   TRACE("(%p)\n", ppOAHolder);
723
724   /*
725    * Sanity check,
726    */
727   if (ppOAHolder==NULL)
728     return E_POINTER;
729
730   *ppOAHolder = OleAdviseHolderImpl_Constructor ();
731
732   if (*ppOAHolder != NULL)
733     return S_OK;
734
735   return E_OUTOFMEMORY;
736 }
737
738 /******************************************************************************
739  *              CreateDataAdviseHolder        [OLE32.53]
740  */
741 HRESULT WINAPI CreateDataAdviseHolder(
742   LPDATAADVISEHOLDER* ppDAHolder)
743 {
744   TRACE("(%p)\n", ppDAHolder);
745
746   /*
747    * Sanity check,
748    */
749   if (ppDAHolder==NULL)
750     return E_POINTER;
751
752   *ppDAHolder = DataAdviseHolder_Constructor();
753
754   if (*ppDAHolder != NULL)
755     return S_OK;
756
757   return E_OUTOFMEMORY;
758 }
759