source: trunk/src/ole32/oleobj.c@ 10367

Last change on this file since 10367 was 8620, checked in by sandervl, 23 years ago

Resync with latest Wine

File size: 19.5 KB
Line 
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
29WINE_DEFAULT_DEBUG_CHANNEL(ole);
30
31#define INITIAL_SINKS 10
32
33/**************************************************************************
34 * OleAdviseHolderImpl Implementation
35 */
36typedef struct OleAdviseHolderImpl
37{
38 ICOM_VFIELD(IOleAdviseHolder);
39
40 DWORD ref;
41
42 DWORD maxSinks;
43 IAdviseSink** arrayOfSinks;
44
45} OleAdviseHolderImpl;
46
47static LPOLEADVISEHOLDER OleAdviseHolderImpl_Constructor();
48static void OleAdviseHolderImpl_Destructor(OleAdviseHolderImpl* ptrToDestroy);
49static HRESULT WINAPI OleAdviseHolderImpl_QueryInterface(LPOLEADVISEHOLDER,REFIID,LPVOID*);
50static ULONG WINAPI OleAdviseHolderImpl_AddRef(LPOLEADVISEHOLDER);
51static ULONG WINAPI OleAdviseHolderImpl_Release(LPOLEADVISEHOLDER);
52static HRESULT WINAPI OleAdviseHolderImpl_Advise(LPOLEADVISEHOLDER, IAdviseSink*, DWORD*);
53static HRESULT WINAPI OleAdviseHolderImpl_Unadvise (LPOLEADVISEHOLDER, DWORD);
54static HRESULT WINAPI OleAdviseHolderImpl_EnumAdvise (LPOLEADVISEHOLDER, IEnumSTATDATA **);
55static HRESULT WINAPI OleAdviseHolderImpl_SendOnRename (LPOLEADVISEHOLDER, IMoniker *);
56static HRESULT WINAPI OleAdviseHolderImpl_SendOnSave (LPOLEADVISEHOLDER);
57static HRESULT WINAPI OleAdviseHolderImpl_SendOnClose (LPOLEADVISEHOLDER);
58
59
60/**************************************************************************
61 * OleAdviseHolderImpl_VTable
62 */
63static 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
81static 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 */
107static 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 */
135static 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 */
175static 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 */
186static 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 */
206static 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 */
273static 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 < 0) ||
292 (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 */
310static HRESULT WINAPI
311OleAdviseHolderImpl_EnumAdvise (LPOLEADVISEHOLDER iface, IEnumSTATDATA **ppenumAdvise)
312{
313 ICOM_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 */
324static HRESULT WINAPI
325OleAdviseHolderImpl_SendOnRename (LPOLEADVISEHOLDER iface, IMoniker *pmk)
326{
327 ICOM_THIS(OleAdviseHolderImpl, iface);
328 FIXME("(%p)->(%p)\n", This, pmk);
329
330
331 return S_OK;
332}
333
334/******************************************************************************
335 * OleAdviseHolderImpl_SendOnSave
336 */
337static HRESULT WINAPI
338OleAdviseHolderImpl_SendOnSave (LPOLEADVISEHOLDER iface)
339{
340 ICOM_THIS(OleAdviseHolderImpl, iface);
341 FIXME("(%p)\n", This);
342
343 return S_OK;
344}
345
346/******************************************************************************
347 * OleAdviseHolderImpl_SendOnClose
348 */
349static HRESULT WINAPI
350OleAdviseHolderImpl_SendOnClose (LPOLEADVISEHOLDER iface)
351{
352 ICOM_THIS(OleAdviseHolderImpl, iface);
353 FIXME("(%p)\n", This);
354
355
356 return S_OK;
357}
358
359/**************************************************************************
360 * DataAdviseHolder Implementation
361 */
362typedef struct DataAdviseConnection {
363 IAdviseSink *sink;
364 FORMATETC fmat;
365 DWORD advf;
366} DataAdviseConnection;
367
368typedef struct DataAdviseHolder
369{
370 ICOM_VFIELD(IDataAdviseHolder);
371
372 DWORD ref;
373 DWORD maxCons;
374 DataAdviseConnection* Connections;
375} DataAdviseHolder;
376
377/**************************************************************************
378 * DataAdviseHolder method prototypes
379 */
380static IDataAdviseHolder* DataAdviseHolder_Constructor();
381static void DataAdviseHolder_Destructor(DataAdviseHolder* ptrToDestroy);
382static HRESULT WINAPI DataAdviseHolder_QueryInterface(
383 IDataAdviseHolder* iface,
384 REFIID riid,
385 void** ppvObject);
386static ULONG WINAPI DataAdviseHolder_AddRef(
387 IDataAdviseHolder* iface);
388static ULONG WINAPI DataAdviseHolder_Release(
389 IDataAdviseHolder* iface);
390static HRESULT WINAPI DataAdviseHolder_Advise(
391 IDataAdviseHolder* iface,
392 IDataObject* pDataObject,
393 FORMATETC* pFetc,
394 DWORD advf,
395 IAdviseSink* pAdvise,
396 DWORD* pdwConnection);
397static HRESULT WINAPI DataAdviseHolder_Unadvise(
398 IDataAdviseHolder* iface,
399 DWORD dwConnection);
400static HRESULT WINAPI DataAdviseHolder_EnumAdvise(
401 IDataAdviseHolder* iface,
402 IEnumSTATDATA** ppenumAdvise);
403static HRESULT WINAPI DataAdviseHolder_SendOnDataChange(
404 IDataAdviseHolder* iface,
405 IDataObject* pDataObject,
406 DWORD dwReserved,
407 DWORD advf);
408
409/**************************************************************************
410 * DataAdviseHolderImpl_VTable
411 */
412static struct ICOM_VTABLE(IDataAdviseHolder) DataAdviseHolderImpl_VTable =
413{
414 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
415 DataAdviseHolder_QueryInterface,
416 DataAdviseHolder_AddRef,
417 DataAdviseHolder_Release,
418 DataAdviseHolder_Advise,
419 DataAdviseHolder_Unadvise,
420 DataAdviseHolder_EnumAdvise,
421 DataAdviseHolder_SendOnDataChange
422};
423
424/******************************************************************************
425 * DataAdviseHolder_Constructor
426 */
427static IDataAdviseHolder* DataAdviseHolder_Constructor()
428{
429 DataAdviseHolder* newHolder;
430
431 newHolder = (DataAdviseHolder*)HeapAlloc(GetProcessHeap(),
432 0,
433 sizeof(DataAdviseHolder));
434
435 ICOM_VTBL(newHolder) = &DataAdviseHolderImpl_VTable;
436 newHolder->ref = 1;
437 newHolder->maxCons = INITIAL_SINKS;
438 newHolder->Connections = HeapAlloc(GetProcessHeap(),
439 HEAP_ZERO_MEMORY,
440 newHolder->maxCons *
441 sizeof(DataAdviseConnection));
442
443 TRACE("returning %p\n", newHolder);
444 return (IDataAdviseHolder*)newHolder;
445}
446
447/******************************************************************************
448 * DataAdviseHolder_Destructor
449 */
450static void DataAdviseHolder_Destructor(DataAdviseHolder* ptrToDestroy)
451{
452 DWORD index;
453 TRACE("%p\n", ptrToDestroy);
454
455 for (index = 0; index < ptrToDestroy->maxCons; index++)
456 {
457 if (ptrToDestroy->Connections[index].sink != NULL)
458 {
459 IAdviseSink_Release(ptrToDestroy->Connections[index].sink);
460 ptrToDestroy->Connections[index].sink = NULL;
461 }
462 }
463
464 HeapFree(GetProcessHeap(), 0, ptrToDestroy->Connections);
465 HeapFree(GetProcessHeap(), 0, ptrToDestroy);
466}
467
468/************************************************************************
469 * DataAdviseHolder_QueryInterface (IUnknown)
470 *
471 * See Windows documentation for more details on IUnknown methods.
472 */
473static HRESULT WINAPI DataAdviseHolder_QueryInterface(
474 IDataAdviseHolder* iface,
475 REFIID riid,
476 void** ppvObject)
477{
478 ICOM_THIS(DataAdviseHolder, iface);
479 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObject);
480 /*
481 * Perform a sanity check on the parameters.
482 */
483 if ( (This==0) || (ppvObject==0) )
484 return E_INVALIDARG;
485
486 /*
487 * Initialize the return parameter.
488 */
489 *ppvObject = 0;
490
491 /*
492 * Compare the riid with the interface IDs implemented by this object.
493 */
494 if ( (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0) ||
495 (memcmp(&IID_IDataAdviseHolder, riid, sizeof(IID_IDataAdviseHolder)) == 0) )
496 {
497 *ppvObject = iface;
498 }
499
500 /*
501 * Check that we obtained an interface.
502 */
503 if ((*ppvObject)==0)
504 {
505 return E_NOINTERFACE;
506 }
507
508 /*
509 * Query Interface always increases the reference count by one when it is
510 * successful.
511 */
512 IUnknown_AddRef((IUnknown*)*ppvObject);
513
514 return S_OK;
515}
516
517/************************************************************************
518 * DataAdviseHolder_AddRef (IUnknown)
519 *
520 * See Windows documentation for more details on IUnknown methods.
521 */
522static ULONG WINAPI DataAdviseHolder_AddRef(
523 IDataAdviseHolder* iface)
524{
525 ICOM_THIS(DataAdviseHolder, iface);
526 TRACE("(%p) (ref=%ld)\n", This, This->ref);
527 This->ref++;
528
529 return This->ref;
530}
531
532/************************************************************************
533 * DataAdviseHolder_Release (IUnknown)
534 *
535 * See Windows documentation for more details on IUnknown methods.
536 */
537static ULONG WINAPI DataAdviseHolder_Release(
538 IDataAdviseHolder* iface)
539{
540 ICOM_THIS(DataAdviseHolder, iface);
541 TRACE("(%p) (ref=%ld)\n", This, This->ref);
542
543 /*
544 * Decrease the reference count on this object.
545 */
546 This->ref--;
547
548 /*
549 * If the reference count goes down to 0, perform suicide.
550 */
551 if (This->ref==0)
552 {
553 DataAdviseHolder_Destructor(This);
554
555 return 0;
556 }
557
558 return This->ref;
559}
560
561/************************************************************************
562 * DataAdviseHolder_Advise
563 *
564 */
565static HRESULT WINAPI DataAdviseHolder_Advise(
566 IDataAdviseHolder* iface,
567 IDataObject* pDataObject,
568 FORMATETC* pFetc,
569 DWORD advf,
570 IAdviseSink* pAdvise,
571 DWORD* pdwConnection)
572{
573 DWORD index;
574
575 ICOM_THIS(DataAdviseHolder, iface);
576
577 TRACE("(%p)->(%p, %p, %08lx, %p, %p)\n", This, pDataObject, pFetc, advf,
578 pAdvise, pdwConnection);
579 /*
580 * Sanity check
581 */
582 if (pdwConnection==NULL)
583 return E_POINTER;
584
585 *pdwConnection = 0;
586
587 /*
588 * Find a free spot in the array.
589 */
590 for (index = 0; index < This->maxCons; index++)
591 {
592 if (This->Connections[index].sink == NULL)
593 break;
594 }
595
596 /*
597 * If the array is full, we need to grow it.
598 */
599 if (index == This->maxCons)
600 {
601 This->maxCons+=INITIAL_SINKS;
602 This->Connections = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
603 This->Connections,
604 This->maxCons*sizeof(DataAdviseConnection));
605 }
606 /*
607 * Store the new sink
608 */
609 This->Connections[index].sink = pAdvise;
610 memcpy(&(This->Connections[index].fmat), pFetc, sizeof(FORMATETC));
611 This->Connections[index].advf = advf;
612
613 if (This->Connections[index].sink != NULL) {
614 IAdviseSink_AddRef(This->Connections[index].sink);
615 if(advf & ADVF_PRIMEFIRST) {
616 DataAdviseHolder_SendOnDataChange(iface, pDataObject, 0, advf);
617 }
618 }
619 /*
620 * Return the index as the cookie.
621 * Since 0 is not a valid cookie, we will increment by
622 * 1 the index in the table.
623 */
624 *pdwConnection = index+1;
625
626 return S_OK;
627}
628
629/******************************************************************************
630 * DataAdviseHolder_Unadvise
631 */
632static HRESULT WINAPI DataAdviseHolder_Unadvise(
633 IDataAdviseHolder* iface,
634 DWORD dwConnection)
635{
636 ICOM_THIS(DataAdviseHolder, iface);
637
638 TRACE("(%p)->(%lu)\n", This, dwConnection);
639
640 /*
641 * So we don't return 0 as a cookie, the index was
642 * incremented by 1 in OleAdviseHolderImpl_Advise
643 * we have to compensate.
644 */
645 dwConnection--;
646
647 /*
648 * Check for invalid cookies.
649 */
650 if ( (dwConnection < 0) ||
651 (dwConnection >= This->maxCons) )
652 return OLE_E_NOCONNECTION;
653
654 if (This->Connections[dwConnection].sink == NULL)
655 return OLE_E_NOCONNECTION;
656
657 /*
658 * Release the sink and mark the spot in the list as free.
659 */
660 IAdviseSink_Release(This->Connections[dwConnection].sink);
661 memset(&(This->Connections[dwConnection]), 0, sizeof(DataAdviseConnection));
662 return S_OK;
663}
664
665static HRESULT WINAPI DataAdviseHolder_EnumAdvise(
666 IDataAdviseHolder* iface,
667 IEnumSTATDATA** ppenumAdvise)
668{
669 ICOM_THIS(DataAdviseHolder, iface);
670
671 FIXME("(%p)->(%p)\n", This, ppenumAdvise);
672 return E_NOTIMPL;
673}
674
675/******************************************************************************
676 * DataAdviseHolder_SendOnDataChange
677 */
678static HRESULT WINAPI DataAdviseHolder_SendOnDataChange(
679 IDataAdviseHolder* iface,
680 IDataObject* pDataObject,
681 DWORD dwReserved,
682 DWORD advf)
683{
684 ICOM_THIS(DataAdviseHolder, iface);
685 DWORD index;
686 STGMEDIUM stg;
687 HRESULT res;
688
689 TRACE("(%p)->(%p,%08lx,%08lx)\n", This, pDataObject, dwReserved, advf);
690
691 for(index = 0; index < This->maxCons; index++) {
692 if(This->Connections[index].sink != NULL) {
693 if(!(This->Connections[index].advf & ADVF_NODATA)) {
694 TRACE("Calling IDataObject_GetData\n");
695 res = IDataObject_GetData(pDataObject,
696 &(This->Connections[index].fmat),
697 &stg);
698 TRACE("returns %08lx\n", res);
699 }
700 TRACE("Calling IAdviseSink_OnDataChange\n");
701 IAdviseSink_OnDataChange(This->Connections[index].sink,
702 &(This->Connections[index].fmat),
703 &stg);
704 TRACE("Done IAdviseSink_OnDataChange\n");
705 if(This->Connections[index].advf & ADVF_ONLYONCE) {
706 TRACE("Removing connection\n");
707 DataAdviseHolder_Unadvise(iface, index+1);
708 }
709 }
710 }
711 return S_OK;
712}
713
714/***********************************************************************
715 * API functions
716 */
717
718/***********************************************************************
719 * CreateOleAdviseHolder [OLE32.59]
720 */
721HRESULT WINAPI CreateOleAdviseHolder(
722 LPOLEADVISEHOLDER *ppOAHolder)
723{
724 TRACE("(%p)\n", ppOAHolder);
725
726 /*
727 * Sanity check,
728 */
729 if (ppOAHolder==NULL)
730 return E_POINTER;
731
732 *ppOAHolder = OleAdviseHolderImpl_Constructor ();
733
734 if (*ppOAHolder != NULL)
735 return S_OK;
736
737 return E_OUTOFMEMORY;
738}
739
740/******************************************************************************
741 * CreateDataAdviseHolder [OLE32.53]
742 */
743HRESULT WINAPI CreateDataAdviseHolder(
744 LPDATAADVISEHOLDER* ppDAHolder)
745{
746 TRACE("(%p)\n", ppDAHolder);
747
748 /*
749 * Sanity check,
750 */
751 if (ppDAHolder==NULL)
752 return E_POINTER;
753
754 *ppDAHolder = DataAdviseHolder_Constructor();
755
756 if (*ppDAHolder != NULL)
757 return S_OK;
758
759 return E_OUTOFMEMORY;
760}
761
Note: See TracBrowser for help on using the repository browser.