- implementation of RtlReg* (read access), RtlEvent*, RtlSemaphore*,
[wine] / dlls / shell32 / dataobject.c
1 /*
2  *      IEnumFORMATETC, IDataObject
3  *
4  * selecting and droping objects within the shell and/or common dialogs
5  *
6  *      Copyright 1998, 1999    <juergen.schmied@metronet.de>
7  */
8 #include <string.h>
9
10 #include "oleidl.h"
11 #include "pidl.h"
12 #include "winerror.h"
13 #include "shell32_main.h"
14 #include "debugtools.h"
15 #include "wine/undocshell.h"
16 #include "wine/obj_dataobject.h"
17
18 DEFAULT_DEBUG_CHANNEL(shell)
19
20 /***********************************************************************
21 *   IEnumFORMATETC implementation
22 */
23
24 typedef struct 
25 {
26     /* IUnknown fields */
27     ICOM_VFIELD(IEnumFORMATETC);
28     DWORD                        ref;
29     /* IEnumFORMATETC fields */
30     UINT        posFmt;
31     UINT        countFmt;
32     LPFORMATETC pFmt;
33 } IEnumFORMATETCImpl;
34
35 static HRESULT WINAPI IEnumFORMATETC_fnQueryInterface(LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj);
36 static ULONG WINAPI IEnumFORMATETC_fnAddRef(LPENUMFORMATETC iface);
37 static ULONG WINAPI IEnumFORMATETC_fnRelease(LPENUMFORMATETC iface);
38 static HRESULT WINAPI IEnumFORMATETC_fnNext(LPENUMFORMATETC iface, ULONG celt, FORMATETC* rgelt, ULONG* pceltFethed);
39 static HRESULT WINAPI IEnumFORMATETC_fnSkip(LPENUMFORMATETC iface, ULONG celt);
40 static HRESULT WINAPI IEnumFORMATETC_fnReset(LPENUMFORMATETC iface);
41 static HRESULT WINAPI IEnumFORMATETC_fnClone(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum);
42
43 static struct ICOM_VTABLE(IEnumFORMATETC) efvt = 
44 {
45     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
46         IEnumFORMATETC_fnQueryInterface,
47         IEnumFORMATETC_fnAddRef,
48     IEnumFORMATETC_fnRelease,
49     IEnumFORMATETC_fnNext,
50     IEnumFORMATETC_fnSkip,
51     IEnumFORMATETC_fnReset,
52     IEnumFORMATETC_fnClone
53 };
54
55 LPENUMFORMATETC IEnumFORMATETC_Constructor(UINT cfmt, const FORMATETC afmt[])
56 {
57         IEnumFORMATETCImpl* ef;
58         DWORD size=cfmt * sizeof(FORMATETC);
59         
60         ef=(IEnumFORMATETCImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IEnumFORMATETCImpl));
61
62         if(ef)
63         {
64           ef->ref=1;
65           ICOM_VTBL(ef)=&efvt;
66
67           ef->countFmt = cfmt;
68           ef->pFmt = SHAlloc (size);
69
70           if (ef->pFmt)
71           {
72             memcpy(ef->pFmt, afmt, size);
73           }
74
75           shell32_ObjCount++;
76         }
77
78         TRACE("(%p)->()\n",ef);
79         return (LPENUMFORMATETC)ef;
80 }
81 static HRESULT WINAPI IEnumFORMATETC_fnQueryInterface(LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj)
82 {
83         ICOM_THIS(IEnumFORMATETCImpl,iface);
84         TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
85
86                         *ppvObj = NULL;
87
88         if(IsEqualIID(riid, &IID_IUnknown))
89         { *ppvObj = This; 
90         }
91         else if(IsEqualIID(riid, &IID_IEnumFORMATETC))
92         { *ppvObj = (IDataObject*)This;
93         }   
94
95         if(*ppvObj)
96         { IEnumFORMATETC_AddRef((IEnumFORMATETC*)*ppvObj);
97           TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
98           return S_OK;
99         }
100         TRACE("-- Interface: E_NOINTERFACE\n");
101         return E_NOINTERFACE;
102
103 }
104 static ULONG WINAPI IEnumFORMATETC_fnAddRef(LPENUMFORMATETC iface)
105 {
106         ICOM_THIS(IEnumFORMATETCImpl,iface);
107         TRACE("(%p)->(count=%lu)\n",This, This->ref);
108         shell32_ObjCount++;
109         return ++(This->ref);
110 }
111 static ULONG WINAPI IEnumFORMATETC_fnRelease(LPENUMFORMATETC iface)
112 {
113         ICOM_THIS(IEnumFORMATETCImpl,iface);
114         TRACE("(%p)->()\n",This);
115
116         shell32_ObjCount--;
117
118         if (!--(This->ref)) 
119         { TRACE(" destroying IEnumFORMATETC(%p)\n",This);
120           if (This->pFmt)
121           { SHFree (This->pFmt);
122           }
123           HeapFree(GetProcessHeap(),0,This);
124           return 0;
125         }
126         return This->ref;
127 }
128 static HRESULT WINAPI IEnumFORMATETC_fnNext(LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
129 {
130         ICOM_THIS(IEnumFORMATETCImpl,iface);
131         UINT cfetch;
132         HRESULT hres = S_FALSE;
133
134         TRACE("(%p)->()\n", This);
135
136         if (This->posFmt < This->countFmt)
137         {
138           cfetch = This->countFmt - This->posFmt;
139           if (cfetch >= celt)
140           {
141             cfetch = celt;
142             hres = S_OK;
143           }
144           memcpy(rgelt, &This->pFmt[This->posFmt], cfetch * sizeof(FORMATETC));
145           This->posFmt += cfetch;
146         }
147         else
148         {
149           cfetch = 0;
150         }
151
152         if (pceltFethed)
153         {
154           *pceltFethed = cfetch;
155         }
156
157         return hres;
158 }
159 static HRESULT WINAPI IEnumFORMATETC_fnSkip(LPENUMFORMATETC iface, ULONG celt)
160 {
161         ICOM_THIS(IEnumFORMATETCImpl,iface);
162         FIXME("(%p)->(num=%lu)\n", This, celt);
163
164         This->posFmt += celt;
165         if (This->posFmt > This->countFmt)
166         {
167           This->posFmt = This->countFmt;
168           return S_FALSE;
169         }
170         return S_OK;
171 }
172 static HRESULT WINAPI IEnumFORMATETC_fnReset(LPENUMFORMATETC iface)
173 {
174         ICOM_THIS(IEnumFORMATETCImpl,iface);
175         FIXME("(%p)->()\n", This);
176
177         This->posFmt = 0;
178         return S_OK;
179 }
180 static HRESULT WINAPI IEnumFORMATETC_fnClone(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum)
181 {
182         ICOM_THIS(IEnumFORMATETCImpl,iface);
183         FIXME("(%p)->(ppenum=%p)\n", This, ppenum);
184         return E_NOTIMPL;
185 }
186
187 /**************************************************************************
188  *  IDLList "Item ID List List"
189  *
190  *  NOTES
191  *   interal data holder for IDataObject
192  */
193 #define STDMETHOD(xfn) HRESULT (CALLBACK *fn##xfn)
194 #define STDMETHOD_(type,xfn) type (CALLBACK *fn##xfn)
195 #define THIS_ THIS,
196
197 typedef struct tagLPIDLLIST *LPIDLLIST, IDLList;
198
199 #define THIS LPIDLLIST me
200 typedef enum
201 { State_UnInit=1,
202   State_Init=2,
203   State_OutOfMem=3
204 } IDLListState;
205
206 typedef struct IDLList_VTable
207 { STDMETHOD_(UINT, GetState)(THIS);
208   STDMETHOD_(LPITEMIDLIST, GetElement)(THIS_ UINT nIndex);
209   STDMETHOD_(UINT, GetCount)(THIS);
210   STDMETHOD_(BOOL, StoreItem)(THIS_ LPITEMIDLIST pidl);
211   STDMETHOD_(BOOL, AddItems)(THIS_ LPITEMIDLIST *apidl, UINT cidl);
212   STDMETHOD_(BOOL, InitList)(THIS);
213   STDMETHOD_(void, CleanList)(THIS);
214 } IDLList_VTable,*LPIDLLIST_VTABLE;
215
216 struct tagLPIDLLIST
217 { LPIDLLIST_VTABLE  lpvtbl;
218   HDPA  dpa;
219   UINT  uStep;
220 };
221
222 extern LPIDLLIST IDLList_Constructor (UINT uStep);
223 extern void IDLList_Destructor(LPIDLLIST me);
224 #undef THIS
225
226
227
228 /**************************************************************************
229  *  IDLList "Item ID List List"
230  * 
231  */
232 static UINT WINAPI IDLList_GetState(LPIDLLIST this);
233 static LPITEMIDLIST WINAPI IDLList_GetElement(LPIDLLIST this, UINT nIndex);
234 static UINT WINAPI IDLList_GetCount(LPIDLLIST this);
235 static BOOL WINAPI IDLList_StoreItem(LPIDLLIST this, LPITEMIDLIST pidl);
236 static BOOL WINAPI IDLList_AddItems(LPIDLLIST this, LPITEMIDLIST *apidl, UINT cidl);
237 static BOOL WINAPI IDLList_InitList(LPIDLLIST this);
238 static void WINAPI IDLList_CleanList(LPIDLLIST this);
239
240 static IDLList_VTable idllvt = 
241 {       IDLList_GetState,
242         IDLList_GetElement,
243         IDLList_GetCount,
244         IDLList_StoreItem,
245         IDLList_AddItems,
246         IDLList_InitList,
247         IDLList_CleanList
248 };
249
250 LPIDLLIST IDLList_Constructor (UINT uStep)
251 {
252         LPIDLLIST lpidll;
253         lpidll = (LPIDLLIST)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDLList));
254
255         if (lpidll)
256         {
257           lpidll->lpvtbl=&idllvt;
258           lpidll->uStep=uStep;
259         }
260
261         TRACE("(%p)\n",lpidll);
262         return lpidll;
263 }
264 void IDLList_Destructor(LPIDLLIST this)
265 {       TRACE("(%p)\n",this);
266         IDLList_CleanList(this);
267 }
268  
269 static UINT WINAPI IDLList_GetState(LPIDLLIST this)
270 {       TRACE("(%p)->(uStep=%u dpa=%p)\n",this, this->uStep, this->dpa);
271
272         if (this->uStep == 0)
273         {
274           if (this->dpa)
275             return(State_Init);
276
277           return(State_OutOfMem);
278         }
279         return(State_UnInit);
280 }
281 static LPITEMIDLIST WINAPI IDLList_GetElement(LPIDLLIST this, UINT nIndex)
282 {       TRACE("(%p)->(index=%u)\n",this, nIndex);
283         return((LPITEMIDLIST)pDPA_GetPtr(this->dpa, nIndex));
284 }
285 static UINT WINAPI IDLList_GetCount(LPIDLLIST this)
286 {       TRACE("(%p)\n",this);
287         return(IDLList_GetState(this)==State_Init ? DPA_GetPtrCount(this->dpa) : 0);
288 }
289 static BOOL WINAPI IDLList_StoreItem(LPIDLLIST this, LPITEMIDLIST pidl)
290 {       TRACE("(%p)->(pidl=%p)\n",this, pidl);
291         if (pidl)
292         { if (IDLList_InitList(this) && pDPA_InsertPtr(this->dpa, 0x7fff, (LPSTR)pidl)>=0)
293             return(TRUE);
294           ILFree(pidl);
295         }
296         IDLList_CleanList(this);
297         return(FALSE);
298 }
299 static BOOL WINAPI IDLList_AddItems(LPIDLLIST this, LPITEMIDLIST *apidl, UINT cidl)
300 {       INT i;
301         TRACE("(%p)->(apidl=%p cidl=%u)\n",this, apidl, cidl);
302
303         for (i=0; i<cidl; ++i)
304         { if (!IDLList_StoreItem(this, ILClone((LPCITEMIDLIST)apidl[i])))
305             return(FALSE);
306         }
307         return(TRUE);
308 }
309 static BOOL WINAPI IDLList_InitList(LPIDLLIST this)
310 {       TRACE("(%p)\n",this);
311         switch (IDLList_GetState(this))
312         { case State_Init:
313             return(TRUE);
314
315           case State_OutOfMem:
316             return(FALSE);
317
318           case State_UnInit:
319           default:
320             this->dpa = pDPA_Create(this->uStep);
321             this->uStep = 0;
322             return(IDLList_InitList(this));
323         }
324 }
325 static void WINAPI IDLList_CleanList(LPIDLLIST this)
326 {       INT i;
327         TRACE("(%p)\n",this);
328
329         if (this->uStep != 0)
330         { this->dpa = NULL;
331           this->uStep = 0;
332           return;
333         }
334
335         if (!this->dpa)
336         { return;
337         }
338
339         for (i=DPA_GetPtrCount(this->dpa)-1; i>=0; --i)
340         { ILFree(IDLList_GetElement(this,i));
341         }
342
343         pDPA_Destroy(this->dpa);
344         this->dpa=NULL;
345 }        
346
347
348 /***********************************************************************
349 *   IDataObject implementation
350 */
351 /* number of supported formats */
352 #define MAX_FORMATS 1
353
354 typedef struct
355 {
356         /* IUnknown fields */
357         ICOM_VFIELD(IDataObject);
358         DWORD           ref;
359
360         /* IDataObject fields */
361         LPIDLLIST       lpill;       /* the data of the dataobject */
362         LPITEMIDLIST    pidl;
363
364         FORMATETC       pFormatEtc[MAX_FORMATS];
365         UINT            cfShellIDList;
366         UINT            cfFileGroupDesc;
367         UINT            cfFileContents;
368
369 } IDataObjectImpl;
370
371 static struct ICOM_VTABLE(IDataObject) dtovt;
372
373 /**************************************************************************
374 *  IDataObject_Constructor
375 */
376 LPDATAOBJECT IDataObject_Constructor(HWND hwndOwner, LPITEMIDLIST pMyPidl, LPITEMIDLIST * apidl, UINT cidl)
377 {
378         IDataObjectImpl* dto;
379
380         dto = (IDataObjectImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDataObjectImpl));
381
382         if (dto)
383         {
384           dto->ref=1;
385           ICOM_VTBL(dto)=&dtovt;
386           dto->pidl=ILClone(pMyPidl);
387
388           /* fill the ItemID List List */
389           dto->lpill = IDLList_Constructor (8);
390           if (! dto->lpill )
391             return NULL;
392           
393           dto->lpill->lpvtbl->fnAddItems(dto->lpill, apidl, cidl); 
394
395           /* */
396           dto->cfShellIDList = RegisterClipboardFormatA(CFSTR_SHELLIDLIST);
397 /*        dto->cfFileGroupDesc = RegisterClipboardFormatA(CFSTR_FILEDESCRIPTORA);
398           dto->cfFileContents = RegisterClipboardFormatA(CFSTR_FILECONTENTS);
399 */
400           InitFormatEtc(dto->pFormatEtc[0], dto->cfShellIDList, TYMED_HGLOBAL);
401
402           shell32_ObjCount++;
403         }
404         
405         TRACE("(%p)->(apidl=%p cidl=%u)\n",dto, apidl, cidl);
406         return (LPDATAOBJECT)dto;
407 }
408 /***************************************************************************
409 *  IDataObject_QueryInterface
410 */
411 static HRESULT WINAPI IDataObject_fnQueryInterface(LPDATAOBJECT iface, REFIID riid, LPVOID * ppvObj)
412 {
413         ICOM_THIS(IDataObjectImpl,iface);
414         TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
415
416         *ppvObj = NULL;
417
418         if(IsEqualIID(riid, &IID_IUnknown))          /*IUnknown*/
419         { *ppvObj = This; 
420         }
421         else if(IsEqualIID(riid, &IID_IDataObject))  /*IDataObject*/
422         { *ppvObj = (IDataObject*)This;
423         }   
424
425         if(*ppvObj)
426         { IDataObject_AddRef((IDataObject*)*ppvObj);      
427           TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
428           return S_OK;
429         }
430         TRACE("-- Interface: E_NOINTERFACE\n");
431         return E_NOINTERFACE;
432 }
433 /**************************************************************************
434 *  IDataObject_AddRef
435 */
436 static ULONG WINAPI IDataObject_fnAddRef(LPDATAOBJECT iface)
437 {
438         ICOM_THIS(IDataObjectImpl,iface);
439
440         TRACE("(%p)->(count=%lu)\n",This, This->ref);
441
442         shell32_ObjCount++;
443         return ++(This->ref);
444 }
445 /**************************************************************************
446 *  IDataObject_Release
447 */
448 static ULONG WINAPI IDataObject_fnRelease(LPDATAOBJECT iface)
449 {
450         ICOM_THIS(IDataObjectImpl,iface);
451         TRACE("(%p)->()\n",This);
452
453         shell32_ObjCount--;
454
455         if (!--(This->ref)) 
456         { TRACE(" destroying IDataObject(%p)\n",This);
457           IDLList_Destructor(This->lpill);
458           HeapFree(GetProcessHeap(),0,This);
459           return 0;
460         }
461         return This->ref;
462 }
463
464 /**************************************************************************
465 * IDataObject_fnGetData
466 */
467 static HRESULT WINAPI IDataObject_fnGetData(LPDATAOBJECT iface, LPFORMATETC pformatetcIn, STGMEDIUM *pmedium)
468 {
469         ICOM_THIS(IDataObjectImpl,iface);
470
471         char    szTemp[256];
472         UINT    cItems;
473         DWORD   sizeCIDA, sizePidl, nOffset, nSize;
474         LPCIDA  pcida;
475         HGLOBAL hmem;
476         int     i;
477         LPITEMIDLIST    pidl;
478         
479         GetClipboardFormatNameA (pformatetcIn->cfFormat, szTemp, 256);
480         TRACE("(%p)->(%p %p format=%s)\n", This, pformatetcIn, pmedium, szTemp);
481
482         /* test expected format */
483         if (!(pformatetcIn->cfFormat == This->cfShellIDList))
484         {
485           FIXME("-- clipformat not implemented\n");
486           return (E_INVALIDARG);
487         }
488
489         if (pformatetcIn->ptd==NULL 
490                 && (pformatetcIn->dwAspect & DVASPECT_CONTENT) 
491                 && pformatetcIn->lindex==-1 
492                 && (pformatetcIn->tymed&TYMED_HGLOBAL))
493         {
494           cItems = This->lpill->lpvtbl->fnGetCount(This->lpill);
495           if (cItems < 1) return(E_UNEXPECTED);
496         
497           sizeCIDA = sizeof(CIDA) + sizeof (UINT)*(cItems);     /* without any pidl */
498           sizePidl = ILGetSize (This->pidl);                    /* add root pidl */
499
500           nSize = sizeCIDA + sizePidl;
501           hmem = GlobalAlloc(GHND|GMEM_SHARE, nSize);           
502           if (!hmem) return(E_OUTOFMEMORY);
503           pcida = GlobalLock (hmem);
504
505           nOffset = sizeCIDA;                           /* start after the CIDA */
506           pcida->cidl = cItems;
507
508           pcida->aoffset[0] = nOffset;                  /* first element */
509           memcpy(((LPBYTE)pcida)+nOffset, This->pidl, sizePidl);
510           nOffset += sizePidl;
511           pdump(This->pidl);
512
513           for (i=0; i< cItems; i++)
514           {
515             pidl = This->lpill->lpvtbl->fnGetElement(This->lpill, i);
516             sizePidl = ILGetSize (pidl);
517             nSize += sizePidl;                          /* size of the structure */
518             pdump(pidl);
519
520             GlobalUnlock(hmem);                         /* grow memory */
521             hmem = GlobalReAlloc(hmem, nSize, GHND|GMEM_SHARE);
522             if (!hmem) return(E_OUTOFMEMORY);
523             pcida = GlobalLock (hmem);
524
525             pcida->aoffset[i+1] = nOffset;              /* copy element */
526             memcpy(((LPBYTE)pcida)+nOffset, pidl, sizePidl);
527             nOffset += sizePidl;
528           }
529
530           GlobalUnlock(hmem);
531
532           pmedium->tymed = TYMED_HGLOBAL;
533           pmedium->u.hGlobal = hmem;
534           pmedium->pUnkForRelease = NULL;
535
536           TRACE("(%p)->(cida at %p)\n", This, pcida);
537           return hmem;
538         }
539
540         FIXME("-- can't serve format\n");
541         return (E_INVALIDARG);
542 }
543 static HRESULT WINAPI IDataObject_fnGetDataHere(LPDATAOBJECT iface, LPFORMATETC pformatetc, STGMEDIUM *pmedium)
544 {
545         ICOM_THIS(IDataObjectImpl,iface);
546         FIXME("(%p)->()\n", This);
547         return E_NOTIMPL;
548 }
549 static HRESULT WINAPI IDataObject_fnQueryGetData(LPDATAOBJECT iface, LPFORMATETC pformatetc)
550 {
551         ICOM_THIS(IDataObjectImpl,iface);
552         UINT i;
553         
554         TRACE("(%p)->(fmt=0x%08x tym=0x%08lx)\n", This, pformatetc->cfFormat, pformatetc->tymed);
555         
556         if(!(DVASPECT_CONTENT & pformatetc->dwAspect))
557           return DV_E_DVASPECT;
558
559         /* check our formats table what we have */
560         for (i=0; i<MAX_FORMATS; i++)
561         {
562           if ((This->pFormatEtc[i].cfFormat == pformatetc->cfFormat)
563            && (This->pFormatEtc[i].tymed == pformatetc->tymed))
564           {
565             return S_OK;
566           }
567         }
568
569         return DV_E_TYMED;
570 }
571 static HRESULT WINAPI IDataObject_fnGetCanonicalFormatEtc(LPDATAOBJECT iface, LPFORMATETC pformatectIn, LPFORMATETC pformatetcOut)
572 {
573         ICOM_THIS(IDataObjectImpl,iface);
574         FIXME("(%p)->()\n", This);
575         return E_NOTIMPL;
576 }
577 static HRESULT WINAPI IDataObject_fnSetData(LPDATAOBJECT iface, LPFORMATETC pformatetc, STGMEDIUM *pmedium, BOOL fRelease)
578 {
579         ICOM_THIS(IDataObjectImpl,iface);
580         FIXME("(%p)->()\n", This);
581         return E_NOTIMPL;
582 }
583 static HRESULT WINAPI IDataObject_fnEnumFormatEtc(LPDATAOBJECT iface, DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc)
584 {
585         ICOM_THIS(IDataObjectImpl,iface);
586
587         TRACE("(%p)->()\n", This);
588         *ppenumFormatEtc=NULL;
589
590         /* only get data */
591         if (DATADIR_GET == dwDirection)
592         {
593           *ppenumFormatEtc = IEnumFORMATETC_Constructor(MAX_FORMATS, This->pFormatEtc);
594           return (*ppenumFormatEtc) ? S_OK : E_FAIL;
595         }
596         
597         return E_NOTIMPL;
598 }
599 static HRESULT WINAPI IDataObject_fnDAdvise(LPDATAOBJECT iface, FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection)
600 {
601         ICOM_THIS(IDataObjectImpl,iface);
602         FIXME("(%p)->()\n", This);
603         return E_NOTIMPL;
604 }
605 static HRESULT WINAPI IDataObject_fnDUnadvise(LPDATAOBJECT iface, DWORD dwConnection)
606 {
607         ICOM_THIS(IDataObjectImpl,iface);
608         FIXME("(%p)->()\n", This);
609         return E_NOTIMPL;
610 }
611 static HRESULT WINAPI IDataObject_fnEnumDAdvise(LPDATAOBJECT iface, IEnumSTATDATA **ppenumAdvise)
612 {
613         ICOM_THIS(IDataObjectImpl,iface);
614         FIXME("(%p)->()\n", This);
615         return E_NOTIMPL;
616 }
617
618 static struct ICOM_VTABLE(IDataObject) dtovt = 
619 {
620         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
621         IDataObject_fnQueryInterface,
622         IDataObject_fnAddRef,
623         IDataObject_fnRelease,
624         IDataObject_fnGetData,
625         IDataObject_fnGetDataHere,
626         IDataObject_fnQueryGetData,
627         IDataObject_fnGetCanonicalFormatEtc,
628         IDataObject_fnSetData,
629         IDataObject_fnEnumFormatEtc,
630         IDataObject_fnDAdvise,
631         IDataObject_fnDUnadvise,
632         IDataObject_fnEnumDAdvise
633 };
634