ole32: Fix excessive file sizes for Storage files.
[wine] / dlls / ole32 / datacache.c
1 /*
2  *      OLE 2 Data cache
3  *
4  *      Copyright 1999  Francis Beaudet
5  *      Copyright 2000  Abey George
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  * NOTES:
22  *    The OLE2 data cache supports a whole whack of
23  *    interfaces including:
24  *       IDataObject, IPersistStorage, IViewObject2,
25  *       IOleCache2 and IOleCacheControl.
26  *
27  *    Most of the implementation details are taken from: Inside OLE
28  *    second edition by Kraig Brockschmidt,
29  *
30  * NOTES
31  *  -  This implementation of the datacache will let your application
32  *     load documents that have embedded OLE objects in them and it will
33  *     also retrieve the metafile representation of those objects.
34  *  -  This implementation of the datacache will also allow your
35  *     application to save new documents with OLE objects in them.
36  *  -  The main thing that it doesn't do is allow you to activate
37  *     or modify the OLE objects in any way.
38  *  -  I haven't found any good documentation on the real usage of
39  *     the streams created by the data cache. In particular, How to
40  *     determine what the XXX stands for in the stream name
41  *     "\002OlePresXXX". It appears to just be a counter.
42  *  -  Also, I don't know the real content of the presentation stream
43  *     header. I was able to figure-out where the extent of the object
44  *     was stored and the aspect, but that's about it.
45  */
46 #include <assert.h>
47 #include <stdarg.h>
48 #include <string.h>
49
50 #define COBJMACROS
51 #define NONAMELESSUNION
52 #define NONAMELESSSTRUCT
53
54 #include "windef.h"
55 #include "winbase.h"
56 #include "wingdi.h"
57 #include "winuser.h"
58 #include "winerror.h"
59 #include "wine/unicode.h"
60 #include "ole2.h"
61 #include "wine/debug.h"
62
63 WINE_DEFAULT_DEBUG_CHANNEL(ole);
64
65 /****************************************************************************
66  * PresentationDataHeader
67  *
68  * This structure represents the header of the \002OlePresXXX stream in
69  * the OLE object strorage.
70  *
71  * Most fields are still unknown.
72  */
73 typedef struct PresentationDataHeader
74 {
75   DWORD unknown1;       /* -1 */
76   DWORD unknown2;       /* 3, possibly CF_METAFILEPICT */
77   DWORD unknown3;       /* 4, possibly TYMED_ISTREAM */
78   DVASPECT dvAspect;
79   DWORD unknown5;       /* -1 */
80
81   DWORD unknown6;
82   DWORD unknown7;       /* 0 */
83   DWORD dwObjectExtentX;
84   DWORD dwObjectExtentY;
85   DWORD dwSize;
86 } PresentationDataHeader;
87
88 /****************************************************************************
89  * DataCache
90  */
91 struct DataCache
92 {
93   /*
94    * List all interface VTables here
95    */
96   const IDataObjectVtbl*      lpVtbl;
97   const IUnknownVtbl*         lpvtblNDIUnknown;
98   const IPersistStorageVtbl*  lpvtblIPersistStorage;
99   const IViewObject2Vtbl*     lpvtblIViewObject;
100   const IOleCache2Vtbl*       lpvtblIOleCache2;
101   const IOleCacheControlVtbl* lpvtblIOleCacheControl;
102
103   /*
104    * Reference count of this object
105    */
106   LONG ref;
107
108   /*
109    * IUnknown implementation of the outer object.
110    */
111   IUnknown* outerUnknown;
112
113   /*
114    * This storage pointer is set through a call to
115    * IPersistStorage_Load. This is where the visual
116    * representation of the object is stored.
117    */
118   IStorage* presentationStorage;
119
120   /*
121    * The user of this object can setup ONE advise sink
122    * connection with the object. These parameters describe
123    * that connection.
124    */
125   DWORD        sinkAspects;
126   DWORD        sinkAdviseFlag;
127   IAdviseSink* sinkInterface;
128
129 };
130
131 typedef struct DataCache DataCache;
132
133 /*
134  * Here, I define utility macros to help with the casting of the
135  * "this" parameter.
136  * There is a version to accommodate all of the VTables implemented
137  * by this object.
138  */
139
140 static inline DataCache *impl_from_IDataObject( IDataObject *iface )
141 {
142     return (DataCache *)((char*)iface - FIELD_OFFSET(DataCache, lpVtbl));
143 }
144
145 static inline DataCache *impl_from_NDIUnknown( IUnknown *iface )
146 {
147     return (DataCache *)((char*)iface - FIELD_OFFSET(DataCache, lpvtblNDIUnknown));
148 }
149
150 static inline DataCache *impl_from_IPersistStorage( IPersistStorage *iface )
151 {
152     return (DataCache *)((char*)iface - FIELD_OFFSET(DataCache, lpvtblIPersistStorage));
153 }
154
155 static inline DataCache *impl_from_IViewObject2( IViewObject2 *iface )
156 {
157     return (DataCache *)((char*)iface - FIELD_OFFSET(DataCache, lpvtblIViewObject));
158 }
159
160 static inline DataCache *impl_from_IOleCache2( IOleCache2 *iface )
161 {
162     return (DataCache *)((char*)iface - FIELD_OFFSET(DataCache, lpvtblIOleCache2));
163 }
164
165 static inline DataCache *impl_from_IOleCacheControl( IOleCacheControl *iface )
166 {
167     return (DataCache *)((char*)iface - FIELD_OFFSET(DataCache, lpvtblIOleCacheControl));
168 }
169
170
171 /*
172  * Prototypes for the methods of the DataCache class.
173  */
174 static DataCache* DataCache_Construct(REFCLSID  clsid,
175                                       LPUNKNOWN pUnkOuter);
176 static HRESULT    DataCache_OpenPresStream(DataCache *this,
177                                            DWORD      drawAspect,
178                                            IStream  **pStm);
179
180 static void DataCache_Destroy(
181   DataCache* ptrToDestroy)
182 {
183   TRACE("()\n");
184
185   if (ptrToDestroy->sinkInterface != NULL)
186   {
187     IAdviseSink_Release(ptrToDestroy->sinkInterface);
188     ptrToDestroy->sinkInterface = NULL;
189   }
190
191   if (ptrToDestroy->presentationStorage != NULL)
192   {
193     IStorage_Release(ptrToDestroy->presentationStorage);
194     ptrToDestroy->presentationStorage = NULL;
195   }
196
197   /*
198    * Free the datacache pointer.
199    */
200   HeapFree(GetProcessHeap(), 0, ptrToDestroy);
201 }
202
203 /************************************************************************
204  * DataCache_ReadPresentationData
205  *
206  * This method will read information for the requested presentation
207  * into the given structure.
208  *
209  * Param:
210  *   this       - Pointer to the DataCache object
211  *   drawAspect - The aspect of the object that we wish to draw.
212  *   header     - The structure containing information about this
213  *                aspect of the object.
214  */
215 static HRESULT DataCache_ReadPresentationData(
216   DataCache*              this,
217   DWORD                   drawAspect,
218   PresentationDataHeader* header)
219 {
220   IStream* presStream = NULL;
221   HRESULT  hres;
222
223   /*
224    * Open the presentation stream.
225    */
226   hres = DataCache_OpenPresStream(
227            this,
228            drawAspect,
229            &presStream);
230
231   if (FAILED(hres))
232     return hres;
233
234   /*
235    * Read the header.
236    */
237
238   hres = IStream_Read(
239            presStream,
240            header,
241            sizeof(PresentationDataHeader),
242            NULL);
243
244   /*
245    * Cleanup.
246    */
247   IStream_Release(presStream);
248
249   /*
250    * We don't want to propagate any other error
251    * code than a failure.
252    */
253   if (hres!=S_OK)
254     hres = E_FAIL;
255
256   return hres;
257 }
258
259 /************************************************************************
260  * DataCache_FireOnViewChange
261  *
262  * This method will fire an OnViewChange notification to the advise
263  * sink registered with the datacache.
264  *
265  * See IAdviseSink::OnViewChange for more details.
266  */
267 static void DataCache_FireOnViewChange(
268   DataCache* this,
269   DWORD      aspect,
270   LONG       lindex)
271 {
272   TRACE("(%p, %lx, %ld)\n", this, aspect, lindex);
273
274   /*
275    * The sink supplies a filter when it registers
276    * we make sure we only send the notifications when that
277    * filter matches.
278    */
279   if ((this->sinkAspects & aspect) != 0)
280   {
281     if (this->sinkInterface != NULL)
282     {
283       IAdviseSink_OnViewChange(this->sinkInterface,
284                                aspect,
285                                lindex);
286
287       /*
288        * Some sinks want to be unregistered automatically when
289        * the first notification goes out.
290        */
291       if ( (this->sinkAdviseFlag & ADVF_ONLYONCE) != 0)
292       {
293         IAdviseSink_Release(this->sinkInterface);
294
295         this->sinkInterface  = NULL;
296         this->sinkAspects    = 0;
297         this->sinkAdviseFlag = 0;
298       }
299     }
300   }
301 }
302
303 /* Helper for DataCache_OpenPresStream */
304 static BOOL DataCache_IsPresentationStream(const STATSTG *elem)
305 {
306     /* The presentation streams have names of the form "\002OlePresXXX",
307      * where XXX goes from 000 to 999. */
308     static const WCHAR OlePres[] = { 2,'O','l','e','P','r','e','s' };
309
310     LPCWSTR name = elem->pwcsName;
311
312     return (elem->type == STGTY_STREAM)
313         && (elem->cbSize.u.LowPart >= sizeof(PresentationDataHeader))
314         && (strlenW(name) == 11)
315         && (strncmpW(name, OlePres, 8) == 0)
316         && (name[8] >= '0') && (name[8] <= '9')
317         && (name[9] >= '0') && (name[9] <= '9')
318         && (name[10] >= '0') && (name[10] <= '9');
319 }
320
321 /************************************************************************
322  * DataCache_OpenPresStream
323  *
324  * This method will find the stream for the given presentation. It makes
325  * no attempt at fallback.
326  *
327  * Param:
328  *   this       - Pointer to the DataCache object
329  *   drawAspect - The aspect of the object that we wish to draw.
330  *   pStm       - A returned stream. It points to the beginning of the
331  *              - presentation data, including the header.
332  *
333  * Errors:
334  *   S_OK               The requested stream has been opened.
335  *   OLE_E_BLANK        The requested stream could not be found.
336  *   Quite a few others I'm too lazy to map correctly.
337  *
338  * Notes:
339  *   Algorithm: Scan the elements of the presentation storage, looking
340  *              for presentation streams. For each presentation stream,
341  *              load the header and check to see if the aspect matches.
342  *
343  *   If a fallback is desired, just opening the first presentation stream
344  *   is a possibility.
345  */
346 static HRESULT DataCache_OpenPresStream(
347   DataCache *this,
348   DWORD      drawAspect,
349   IStream  **ppStm)
350 {
351     STATSTG elem;
352     IEnumSTATSTG *pEnum;
353     HRESULT hr;
354
355     if (!ppStm) return E_POINTER;
356
357     hr = IStorage_EnumElements(this->presentationStorage, 0, NULL, 0, &pEnum);
358     if (FAILED(hr)) return hr;
359
360     while ((hr = IEnumSTATSTG_Next(pEnum, 1, &elem, NULL)) == S_OK)
361     {
362         if (DataCache_IsPresentationStream(&elem))
363         {
364             IStream *pStm;
365
366             hr = IStorage_OpenStream(this->presentationStorage, elem.pwcsName,
367                                      NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0,
368                                      &pStm);
369             if (SUCCEEDED(hr))
370             {
371                 PresentationDataHeader header;
372                 ULONG actual_read;
373
374                 hr = IStream_Read(pStm, &header, sizeof(header), &actual_read);
375
376                 /* can't use SUCCEEDED(hr): S_FALSE counts as an error */
377                 if (hr == S_OK && actual_read == sizeof(header)
378                     && header.dvAspect == drawAspect)
379                 {
380                     /* Rewind the stream before returning it. */
381                     LARGE_INTEGER offset;
382                     offset.u.LowPart = 0;
383                     offset.u.HighPart = 0;
384                     IStream_Seek(pStm, offset, STREAM_SEEK_SET, NULL);
385
386                     *ppStm = pStm;
387
388                     CoTaskMemFree(elem.pwcsName);
389                     IEnumSTATSTG_Release(pEnum);
390
391                     return S_OK;
392                 }
393
394                 IStream_Release(pStm);
395             }
396         }
397
398         CoTaskMemFree(elem.pwcsName);
399     }
400
401     IEnumSTATSTG_Release(pEnum);
402
403     return (hr == S_FALSE ? OLE_E_BLANK : hr);
404 }
405
406 /************************************************************************
407  * DataCache_ReadPresentationData
408  *
409  * This method will read information for the requested presentation
410  * into the given structure.
411  *
412  * Param:
413  *   this       - Pointer to the DataCache object
414  *   drawAspect - The aspect of the object that we wish to draw.
415  *
416  * Returns:
417  *   This method returns a metafile handle if it is successful.
418  *   it will return 0 if not.
419  */
420 static HMETAFILE DataCache_ReadPresMetafile(
421   DataCache* this,
422   DWORD      drawAspect)
423 {
424   LARGE_INTEGER offset;
425   IStream*      presStream = NULL;
426   HRESULT       hres;
427   void*         metafileBits;
428   STATSTG       streamInfo;
429   HMETAFILE     newMetafile = 0;
430
431   /*
432    * Open the presentation stream.
433    */
434   hres = DataCache_OpenPresStream(
435            this,
436            drawAspect,
437            &presStream);
438
439   if (FAILED(hres))
440     return (HMETAFILE)hres;
441
442   /*
443    * Get the size of the stream.
444    */
445   hres = IStream_Stat(presStream,
446                       &streamInfo,
447                       STATFLAG_NONAME);
448
449   /*
450    * Skip the header
451    */
452   offset.u.HighPart = 0;
453   offset.u.LowPart  = sizeof(PresentationDataHeader);
454
455   hres = IStream_Seek(
456            presStream,
457            offset,
458            STREAM_SEEK_SET,
459            NULL);
460
461   streamInfo.cbSize.u.LowPart -= offset.u.LowPart;
462
463   /*
464    * Allocate a buffer for the metafile bits.
465    */
466   metafileBits = HeapAlloc(GetProcessHeap(),
467                            0,
468                            streamInfo.cbSize.u.LowPart);
469
470   /*
471    * Read the metafile bits.
472    */
473   hres = IStream_Read(
474            presStream,
475            metafileBits,
476            streamInfo.cbSize.u.LowPart,
477            NULL);
478
479   /*
480    * Create a metafile with those bits.
481    */
482   if (SUCCEEDED(hres))
483   {
484     newMetafile = SetMetaFileBitsEx(streamInfo.cbSize.u.LowPart, metafileBits);
485   }
486
487   /*
488    * Cleanup.
489    */
490   HeapFree(GetProcessHeap(), 0, metafileBits);
491   IStream_Release(presStream);
492
493   if (newMetafile==0)
494     hres = E_FAIL;
495
496   return newMetafile;
497 }
498
499 /*********************************************************
500  * Method implementation for the  non delegating IUnknown
501  * part of the DataCache class.
502  */
503
504 /************************************************************************
505  * DataCache_NDIUnknown_QueryInterface (IUnknown)
506  *
507  * See Windows documentation for more details on IUnknown methods.
508  *
509  * This version of QueryInterface will not delegate it's implementation
510  * to the outer unknown.
511  */
512 static HRESULT WINAPI DataCache_NDIUnknown_QueryInterface(
513             IUnknown*      iface,
514             REFIID         riid,
515             void**         ppvObject)
516 {
517   DataCache *this = impl_from_NDIUnknown(iface);
518
519   /*
520    * Perform a sanity check on the parameters.
521    */
522   if ( (this==0) || (ppvObject==0) )
523     return E_INVALIDARG;
524
525   /*
526    * Initialize the return parameter.
527    */
528   *ppvObject = 0;
529
530   /*
531    * Compare the riid with the interface IDs implemented by this object.
532    */
533   if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
534   {
535     *ppvObject = iface;
536   }
537   else if (memcmp(&IID_IDataObject, riid, sizeof(IID_IDataObject)) == 0)
538   {
539     *ppvObject = (IDataObject*)&(this->lpVtbl);
540   }
541   else if ( (memcmp(&IID_IPersistStorage, riid, sizeof(IID_IPersistStorage)) == 0)  ||
542             (memcmp(&IID_IPersist, riid, sizeof(IID_IPersist)) == 0) )
543   {
544     *ppvObject = (IPersistStorage*)&(this->lpvtblIPersistStorage);
545   }
546   else if ( (memcmp(&IID_IViewObject, riid, sizeof(IID_IViewObject)) == 0) ||
547             (memcmp(&IID_IViewObject2, riid, sizeof(IID_IViewObject2)) == 0) )
548   {
549     *ppvObject = (IViewObject2*)&(this->lpvtblIViewObject);
550   }
551   else if ( (memcmp(&IID_IOleCache, riid, sizeof(IID_IOleCache)) == 0) ||
552             (memcmp(&IID_IOleCache2, riid, sizeof(IID_IOleCache2)) == 0) )
553   {
554     *ppvObject = (IOleCache2*)&(this->lpvtblIOleCache2);
555   }
556   else if (memcmp(&IID_IOleCacheControl, riid, sizeof(IID_IOleCacheControl)) == 0)
557   {
558     *ppvObject = (IOleCacheControl*)&(this->lpvtblIOleCacheControl);
559   }
560
561   /*
562    * Check that we obtained an interface.
563    */
564   if ((*ppvObject)==0)
565   {
566     WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid));
567     return E_NOINTERFACE;
568   }
569
570   /*
571    * Query Interface always increases the reference count by one when it is
572    * successful.
573    */
574   IUnknown_AddRef((IUnknown*)*ppvObject);
575
576   return S_OK;
577 }
578
579 /************************************************************************
580  * DataCache_NDIUnknown_AddRef (IUnknown)
581  *
582  * See Windows documentation for more details on IUnknown methods.
583  *
584  * This version of QueryInterface will not delegate it's implementation
585  * to the outer unknown.
586  */
587 static ULONG WINAPI DataCache_NDIUnknown_AddRef(
588             IUnknown*      iface)
589 {
590   DataCache *this = impl_from_NDIUnknown(iface);
591   return InterlockedIncrement(&this->ref);
592 }
593
594 /************************************************************************
595  * DataCache_NDIUnknown_Release (IUnknown)
596  *
597  * See Windows documentation for more details on IUnknown methods.
598  *
599  * This version of QueryInterface will not delegate it's implementation
600  * to the outer unknown.
601  */
602 static ULONG WINAPI DataCache_NDIUnknown_Release(
603             IUnknown*      iface)
604 {
605   DataCache *this = impl_from_NDIUnknown(iface);
606   ULONG ref;
607
608   /*
609    * Decrease the reference count on this object.
610    */
611   ref = InterlockedDecrement(&this->ref);
612
613   /*
614    * If the reference count goes down to 0, perform suicide.
615    */
616   if (ref == 0) DataCache_Destroy(this);
617
618   return ref;
619 }
620
621 /*********************************************************
622  * Method implementation for the IDataObject
623  * part of the DataCache class.
624  */
625
626 /************************************************************************
627  * DataCache_IDataObject_QueryInterface (IUnknown)
628  *
629  * See Windows documentation for more details on IUnknown methods.
630  */
631 static HRESULT WINAPI DataCache_IDataObject_QueryInterface(
632             IDataObject*     iface,
633             REFIID           riid,
634             void**           ppvObject)
635 {
636   DataCache *this = impl_from_IDataObject(iface);
637
638   return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
639 }
640
641 /************************************************************************
642  * DataCache_IDataObject_AddRef (IUnknown)
643  *
644  * See Windows documentation for more details on IUnknown methods.
645  */
646 static ULONG WINAPI DataCache_IDataObject_AddRef(
647             IDataObject*     iface)
648 {
649   DataCache *this = impl_from_IDataObject(iface);
650
651   return IUnknown_AddRef(this->outerUnknown);
652 }
653
654 /************************************************************************
655  * DataCache_IDataObject_Release (IUnknown)
656  *
657  * See Windows documentation for more details on IUnknown methods.
658  */
659 static ULONG WINAPI DataCache_IDataObject_Release(
660             IDataObject*     iface)
661 {
662   DataCache *this = impl_from_IDataObject(iface);
663
664   return IUnknown_Release(this->outerUnknown);
665 }
666
667 /************************************************************************
668  * DataCache_GetData
669  *
670  * Get Data from a source dataobject using format pformatetcIn->cfFormat
671  * See Windows documentation for more details on GetData.
672  * TODO: Currently only CF_METAFILEPICT is implemented
673  */
674 static HRESULT WINAPI DataCache_GetData(
675             IDataObject*     iface,
676             LPFORMATETC      pformatetcIn,
677             STGMEDIUM*       pmedium)
678 {
679   HRESULT hr = 0;
680   HRESULT hrRet = E_UNEXPECTED;
681   IPersistStorage *pPersistStorage = 0;
682   IStorage *pStorage = 0;
683   IStream *pStream = 0;
684   OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
685   HGLOBAL hGlobalMF = 0;
686   void *mfBits = 0;
687   PresentationDataHeader pdh;
688   METAFILEPICT *mfPict;
689   HMETAFILE hMetaFile = 0;
690
691   if (pformatetcIn->cfFormat == CF_METAFILEPICT)
692   {
693     /* Get the Persist Storage */
694
695     hr = IDataObject_QueryInterface(iface, &IID_IPersistStorage, (void**)&pPersistStorage);
696
697     if (hr != S_OK)
698       goto cleanup;
699
700     /* Create a doc file to copy the doc to a storage */
701
702     hr = StgCreateDocfile(NULL, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &pStorage);
703
704     if (hr != S_OK)
705       goto cleanup;
706
707     /* Save it to storage */
708
709     hr = OleSave(pPersistStorage, pStorage, FALSE);
710
711     if (hr != S_OK)
712       goto cleanup;
713
714     /* Open the Presentation data srteam */
715
716     hr = IStorage_OpenStream(pStorage, name, 0, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &pStream);
717
718     if (hr != S_OK)
719       goto cleanup;
720
721     /* Read the presentation header */
722
723     hr = IStream_Read(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
724
725     if (hr != S_OK)
726       goto cleanup;
727
728     mfBits = HeapAlloc(GetProcessHeap(), 0, pdh.dwSize);
729
730     /* Read the Metafile bits */
731
732     hr = IStream_Read(pStream, mfBits, pdh.dwSize, NULL);
733
734     if (hr != S_OK)
735       goto cleanup;
736
737     /* Create the metafile and place it in the STGMEDIUM structure */
738
739     hMetaFile = SetMetaFileBitsEx(pdh.dwSize, mfBits);
740
741     hGlobalMF = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, sizeof(METAFILEPICT));
742     mfPict = (METAFILEPICT *)GlobalLock(hGlobalMF);
743     mfPict->hMF = hMetaFile;
744
745     GlobalUnlock(hGlobalMF);
746
747     pmedium->u.hGlobal = hGlobalMF;
748     pmedium->tymed = TYMED_MFPICT;
749     hrRet = S_OK;
750
751 cleanup:
752
753     HeapFree(GetProcessHeap(), 0, mfBits);
754
755     if (pStream)
756       IStream_Release(pStream);
757
758     if (pStorage)
759       IStorage_Release(pStorage);
760
761     if (pPersistStorage)
762       IPersistStorage_Release(pPersistStorage);
763
764     return hrRet;
765   }
766
767   /* TODO: Other formats are not implemented */
768
769   return E_NOTIMPL;
770 }
771
772 static HRESULT WINAPI DataCache_GetDataHere(
773             IDataObject*     iface,
774             LPFORMATETC      pformatetc,
775             STGMEDIUM*       pmedium)
776 {
777   FIXME("stub\n");
778   return E_NOTIMPL;
779 }
780
781 static HRESULT WINAPI DataCache_QueryGetData(
782             IDataObject*     iface,
783             LPFORMATETC      pformatetc)
784 {
785   FIXME("stub\n");
786   return E_NOTIMPL;
787 }
788
789 /************************************************************************
790  * DataCache_EnumFormatEtc (IDataObject)
791  *
792  * The data cache doesn't implement this method.
793  *
794  * See Windows documentation for more details on IDataObject methods.
795  */
796 static HRESULT WINAPI DataCache_GetCanonicalFormatEtc(
797             IDataObject*     iface,
798             LPFORMATETC      pformatectIn,
799             LPFORMATETC      pformatetcOut)
800 {
801   TRACE("()\n");
802   return E_NOTIMPL;
803 }
804
805 /************************************************************************
806  * DataCache_IDataObject_SetData (IDataObject)
807  *
808  * This method is delegated to the IOleCache2 implementation.
809  *
810  * See Windows documentation for more details on IDataObject methods.
811  */
812 static HRESULT WINAPI DataCache_IDataObject_SetData(
813             IDataObject*     iface,
814             LPFORMATETC      pformatetc,
815             STGMEDIUM*       pmedium,
816             BOOL             fRelease)
817 {
818   IOleCache2* oleCache = NULL;
819   HRESULT     hres;
820
821   TRACE("(%p, %p, %p, %d)\n", iface, pformatetc, pmedium, fRelease);
822
823   hres = IDataObject_QueryInterface(iface, &IID_IOleCache2, (void**)&oleCache);
824
825   if (FAILED(hres))
826     return E_UNEXPECTED;
827
828   hres = IOleCache2_SetData(oleCache, pformatetc, pmedium, fRelease);
829
830   IOleCache2_Release(oleCache);
831
832   return hres;
833 }
834
835 /************************************************************************
836  * DataCache_EnumFormatEtc (IDataObject)
837  *
838  * The data cache doesn't implement this method.
839  *
840  * See Windows documentation for more details on IDataObject methods.
841  */
842 static HRESULT WINAPI DataCache_EnumFormatEtc(
843             IDataObject*     iface,
844             DWORD            dwDirection,
845             IEnumFORMATETC** ppenumFormatEtc)
846 {
847   TRACE("()\n");
848   return E_NOTIMPL;
849 }
850
851 /************************************************************************
852  * DataCache_DAdvise (IDataObject)
853  *
854  * The data cache doesn't support connections.
855  *
856  * See Windows documentation for more details on IDataObject methods.
857  */
858 static HRESULT WINAPI DataCache_DAdvise(
859             IDataObject*     iface,
860             FORMATETC*       pformatetc,
861             DWORD            advf,
862             IAdviseSink*     pAdvSink,
863             DWORD*           pdwConnection)
864 {
865   TRACE("()\n");
866   return OLE_E_ADVISENOTSUPPORTED;
867 }
868
869 /************************************************************************
870  * DataCache_DUnadvise (IDataObject)
871  *
872  * The data cache doesn't support connections.
873  *
874  * See Windows documentation for more details on IDataObject methods.
875  */
876 static HRESULT WINAPI DataCache_DUnadvise(
877             IDataObject*     iface,
878             DWORD            dwConnection)
879 {
880   TRACE("()\n");
881   return OLE_E_NOCONNECTION;
882 }
883
884 /************************************************************************
885  * DataCache_EnumDAdvise (IDataObject)
886  *
887  * The data cache doesn't support connections.
888  *
889  * See Windows documentation for more details on IDataObject methods.
890  */
891 static HRESULT WINAPI DataCache_EnumDAdvise(
892             IDataObject*     iface,
893             IEnumSTATDATA**  ppenumAdvise)
894 {
895   TRACE("()\n");
896   return OLE_E_ADVISENOTSUPPORTED;
897 }
898
899 /*********************************************************
900  * Method implementation for the IDataObject
901  * part of the DataCache class.
902  */
903
904 /************************************************************************
905  * DataCache_IPersistStorage_QueryInterface (IUnknown)
906  *
907  * See Windows documentation for more details on IUnknown methods.
908  */
909 static HRESULT WINAPI DataCache_IPersistStorage_QueryInterface(
910             IPersistStorage* iface,
911             REFIID           riid,
912             void**           ppvObject)
913 {
914   DataCache *this = impl_from_IPersistStorage(iface);
915
916   return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
917 }
918
919 /************************************************************************
920  * DataCache_IPersistStorage_AddRef (IUnknown)
921  *
922  * See Windows documentation for more details on IUnknown methods.
923  */
924 static ULONG WINAPI DataCache_IPersistStorage_AddRef(
925             IPersistStorage* iface)
926 {
927   DataCache *this = impl_from_IPersistStorage(iface);
928
929   return IUnknown_AddRef(this->outerUnknown);
930 }
931
932 /************************************************************************
933  * DataCache_IPersistStorage_Release (IUnknown)
934  *
935  * See Windows documentation for more details on IUnknown methods.
936  */
937 static ULONG WINAPI DataCache_IPersistStorage_Release(
938             IPersistStorage* iface)
939 {
940   DataCache *this = impl_from_IPersistStorage(iface);
941
942   return IUnknown_Release(this->outerUnknown);
943 }
944
945 /************************************************************************
946  * DataCache_GetClassID (IPersistStorage)
947  *
948  * The data cache doesn't implement this method.
949  *
950  * See Windows documentation for more details on IPersistStorage methods.
951  */
952 static HRESULT WINAPI DataCache_GetClassID(
953             IPersistStorage* iface,
954             CLSID*           pClassID)
955 {
956   TRACE("(%p, %p)\n", iface, pClassID);
957   return E_NOTIMPL;
958 }
959
960 /************************************************************************
961  * DataCache_IsDirty (IPersistStorage)
962  *
963  * Until we actually connect to a running object and retrieve new
964  * information to it, we never get dirty.
965  *
966  * See Windows documentation for more details on IPersistStorage methods.
967  */
968 static HRESULT WINAPI DataCache_IsDirty(
969             IPersistStorage* iface)
970 {
971   TRACE("(%p)\n", iface);
972
973   return S_FALSE;
974 }
975
976 /************************************************************************
977  * DataCache_InitNew (IPersistStorage)
978  *
979  * The data cache implementation of IPersistStorage_InitNew simply stores
980  * the storage pointer.
981  *
982  * See Windows documentation for more details on IPersistStorage methods.
983  */
984 static HRESULT WINAPI DataCache_InitNew(
985             IPersistStorage* iface,
986             IStorage*        pStg)
987 {
988   TRACE("(%p, %p)\n", iface, pStg);
989
990   return IPersistStorage_Load(iface, pStg);
991 }
992
993 /************************************************************************
994  * DataCache_Load (IPersistStorage)
995  *
996  * The data cache implementation of IPersistStorage_Load doesn't
997  * actually load anything. Instead, it holds on to the storage pointer
998  * and it will load the presentation information when the
999  * IDataObject_GetData or IViewObject2_Draw methods are called.
1000  *
1001  * See Windows documentation for more details on IPersistStorage methods.
1002  */
1003 static HRESULT WINAPI DataCache_Load(
1004             IPersistStorage* iface,
1005             IStorage*        pStg)
1006 {
1007   DataCache *this = impl_from_IPersistStorage(iface);
1008
1009   TRACE("(%p, %p)\n", iface, pStg);
1010
1011   if (this->presentationStorage != NULL)
1012   {
1013     IStorage_Release(this->presentationStorage);
1014   }
1015
1016   this->presentationStorage = pStg;
1017
1018   if (this->presentationStorage != NULL)
1019   {
1020     IStorage_AddRef(this->presentationStorage);
1021   }
1022   return S_OK;
1023 }
1024
1025 /************************************************************************
1026  * DataCache_Save (IPersistStorage)
1027  *
1028  * Until we actually connect to a running object and retrieve new
1029  * information to it, we never have to save anything. However, it is
1030  * our responsibility to copy the information when saving to a new
1031  * storage.
1032  *
1033  * See Windows documentation for more details on IPersistStorage methods.
1034  */
1035 static HRESULT WINAPI DataCache_Save(
1036             IPersistStorage* iface,
1037             IStorage*        pStg,
1038             BOOL             fSameAsLoad)
1039 {
1040   DataCache *this = impl_from_IPersistStorage(iface);
1041
1042   TRACE("(%p, %p, %d)\n", iface, pStg, fSameAsLoad);
1043
1044   if ( (!fSameAsLoad) &&
1045        (this->presentationStorage!=NULL) )
1046   {
1047     return IStorage_CopyTo(this->presentationStorage,
1048                            0,
1049                            NULL,
1050                            NULL,
1051                            pStg);
1052   }
1053
1054   return S_OK;
1055 }
1056
1057 /************************************************************************
1058  * DataCache_SaveCompleted (IPersistStorage)
1059  *
1060  * This method is called to tell the cache to release the storage
1061  * pointer it's currently holding.
1062  *
1063  * See Windows documentation for more details on IPersistStorage methods.
1064  */
1065 static HRESULT WINAPI DataCache_SaveCompleted(
1066             IPersistStorage* iface,
1067             IStorage*        pStgNew)
1068 {
1069   TRACE("(%p, %p)\n", iface, pStgNew);
1070
1071   if (pStgNew)
1072   {
1073   /*
1074    * First, make sure we get our hands off any storage we have.
1075    */
1076
1077   IPersistStorage_HandsOffStorage(iface);
1078
1079   /*
1080    * Then, attach to the new storage.
1081    */
1082
1083   DataCache_Load(iface, pStgNew);
1084   }
1085
1086   return S_OK;
1087 }
1088
1089 /************************************************************************
1090  * DataCache_HandsOffStorage (IPersistStorage)
1091  *
1092  * This method is called to tell the cache to release the storage
1093  * pointer it's currently holding.
1094  *
1095  * See Windows documentation for more details on IPersistStorage methods.
1096  */
1097 static HRESULT WINAPI DataCache_HandsOffStorage(
1098             IPersistStorage* iface)
1099 {
1100   DataCache *this = impl_from_IPersistStorage(iface);
1101
1102   TRACE("(%p)\n", iface);
1103
1104   if (this->presentationStorage != NULL)
1105   {
1106     IStorage_Release(this->presentationStorage);
1107     this->presentationStorage = NULL;
1108   }
1109
1110   return S_OK;
1111 }
1112
1113 /*********************************************************
1114  * Method implementation for the IViewObject2
1115  * part of the DataCache class.
1116  */
1117
1118 /************************************************************************
1119  * DataCache_IViewObject2_QueryInterface (IUnknown)
1120  *
1121  * See Windows documentation for more details on IUnknown methods.
1122  */
1123 static HRESULT WINAPI DataCache_IViewObject2_QueryInterface(
1124             IViewObject2* iface,
1125             REFIID           riid,
1126             void**           ppvObject)
1127 {
1128   DataCache *this = impl_from_IViewObject2(iface);
1129
1130   return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1131 }
1132
1133 /************************************************************************
1134  * DataCache_IViewObject2_AddRef (IUnknown)
1135  *
1136  * See Windows documentation for more details on IUnknown methods.
1137  */
1138 static ULONG WINAPI DataCache_IViewObject2_AddRef(
1139             IViewObject2* iface)
1140 {
1141   DataCache *this = impl_from_IViewObject2(iface);
1142
1143   return IUnknown_AddRef(this->outerUnknown);
1144 }
1145
1146 /************************************************************************
1147  * DataCache_IViewObject2_Release (IUnknown)
1148  *
1149  * See Windows documentation for more details on IUnknown methods.
1150  */
1151 static ULONG WINAPI DataCache_IViewObject2_Release(
1152             IViewObject2* iface)
1153 {
1154   DataCache *this = impl_from_IViewObject2(iface);
1155
1156   return IUnknown_Release(this->outerUnknown);
1157 }
1158
1159 /************************************************************************
1160  * DataCache_Draw (IViewObject2)
1161  *
1162  * This method will draw the cached representation of the object
1163  * to the given device context.
1164  *
1165  * See Windows documentation for more details on IViewObject2 methods.
1166  */
1167 static HRESULT WINAPI DataCache_Draw(
1168             IViewObject2*    iface,
1169             DWORD            dwDrawAspect,
1170             LONG             lindex,
1171             void*            pvAspect,
1172             DVTARGETDEVICE*  ptd,
1173             HDC              hdcTargetDev,
1174             HDC              hdcDraw,
1175             LPCRECTL         lprcBounds,
1176             LPCRECTL         lprcWBounds,
1177             BOOL  (CALLBACK *pfnContinue)(ULONG_PTR dwContinue),
1178             ULONG_PTR        dwContinue)
1179 {
1180   PresentationDataHeader presData;
1181   HMETAFILE              presMetafile = 0;
1182   HRESULT                hres;
1183
1184   DataCache *this = impl_from_IViewObject2(iface);
1185
1186   TRACE("(%p, %lx, %ld, %p, %p, %p, %p, %p, %p, %lx)\n",
1187         iface,
1188         dwDrawAspect,
1189         lindex,
1190         pvAspect,
1191         hdcTargetDev,
1192         hdcDraw,
1193         lprcBounds,
1194         lprcWBounds,
1195         pfnContinue,
1196         dwContinue);
1197
1198   /*
1199    * Sanity check
1200    */
1201   if (lprcBounds==NULL)
1202     return E_INVALIDARG;
1203
1204   /*
1205    * First, we need to retrieve the dimensions of the
1206    * image in the metafile.
1207    */
1208   hres = DataCache_ReadPresentationData(this,
1209                                         dwDrawAspect,
1210                                         &presData);
1211
1212   if (FAILED(hres))
1213     return hres;
1214
1215   /*
1216    * Then, we can extract the metafile itself from the cached
1217    * data.
1218    *
1219    * FIXME Unless it isn't a metafile. I think it could be any CF_XXX type,
1220    * particularly CF_DIB.
1221    */
1222   presMetafile = DataCache_ReadPresMetafile(this,
1223                                             dwDrawAspect);
1224
1225   /*
1226    * If we have a metafile, just draw baby...
1227    * We have to be careful not to modify the state of the
1228    * DC.
1229    */
1230   if (presMetafile!=0)
1231   {
1232     INT   prevMapMode = SetMapMode(hdcDraw, MM_ANISOTROPIC);
1233     SIZE  oldWindowExt;
1234     SIZE  oldViewportExt;
1235     POINT oldViewportOrg;
1236
1237     SetWindowExtEx(hdcDraw,
1238                    presData.dwObjectExtentX,
1239                    presData.dwObjectExtentY,
1240                    &oldWindowExt);
1241
1242     SetViewportExtEx(hdcDraw,
1243                      lprcBounds->right - lprcBounds->left,
1244                      lprcBounds->bottom - lprcBounds->top,
1245                      &oldViewportExt);
1246
1247     SetViewportOrgEx(hdcDraw,
1248                      lprcBounds->left,
1249                      lprcBounds->top,
1250                      &oldViewportOrg);
1251
1252     PlayMetaFile(hdcDraw, presMetafile);
1253
1254     SetWindowExtEx(hdcDraw,
1255                    oldWindowExt.cx,
1256                    oldWindowExt.cy,
1257                    NULL);
1258
1259     SetViewportExtEx(hdcDraw,
1260                      oldViewportExt.cx,
1261                      oldViewportExt.cy,
1262                      NULL);
1263
1264     SetViewportOrgEx(hdcDraw,
1265                      oldViewportOrg.x,
1266                      oldViewportOrg.y,
1267                      NULL);
1268
1269     SetMapMode(hdcDraw, prevMapMode);
1270
1271     DeleteMetaFile(presMetafile);
1272   }
1273
1274   return S_OK;
1275 }
1276
1277 static HRESULT WINAPI DataCache_GetColorSet(
1278             IViewObject2*   iface,
1279             DWORD           dwDrawAspect,
1280             LONG            lindex,
1281             void*           pvAspect,
1282             DVTARGETDEVICE* ptd,
1283             HDC             hicTargetDevice,
1284             LOGPALETTE**    ppColorSet)
1285 {
1286   FIXME("stub\n");
1287   return E_NOTIMPL;
1288 }
1289
1290 static HRESULT WINAPI DataCache_Freeze(
1291             IViewObject2*   iface,
1292             DWORD           dwDrawAspect,
1293             LONG            lindex,
1294             void*           pvAspect,
1295             DWORD*          pdwFreeze)
1296 {
1297   FIXME("stub\n");
1298   return E_NOTIMPL;
1299 }
1300
1301 static HRESULT WINAPI DataCache_Unfreeze(
1302             IViewObject2*   iface,
1303             DWORD           dwFreeze)
1304 {
1305   FIXME("stub\n");
1306   return E_NOTIMPL;
1307 }
1308
1309 /************************************************************************
1310  * DataCache_SetAdvise (IViewObject2)
1311  *
1312  * This sets-up an advisory sink with the data cache. When the object's
1313  * view changes, this sink is called.
1314  *
1315  * See Windows documentation for more details on IViewObject2 methods.
1316  */
1317 static HRESULT WINAPI DataCache_SetAdvise(
1318             IViewObject2*   iface,
1319             DWORD           aspects,
1320             DWORD           advf,
1321             IAdviseSink*    pAdvSink)
1322 {
1323   DataCache *this = impl_from_IViewObject2(iface);
1324
1325   TRACE("(%p, %lx, %lx, %p)\n", iface, aspects, advf, pAdvSink);
1326
1327   /*
1328    * A call to this function removes the previous sink
1329    */
1330   if (this->sinkInterface != NULL)
1331   {
1332     IAdviseSink_Release(this->sinkInterface);
1333     this->sinkInterface  = NULL;
1334     this->sinkAspects    = 0;
1335     this->sinkAdviseFlag = 0;
1336   }
1337
1338   /*
1339    * Now, setup the new one.
1340    */
1341   if (pAdvSink!=NULL)
1342   {
1343     this->sinkInterface  = pAdvSink;
1344     this->sinkAspects    = aspects;
1345     this->sinkAdviseFlag = advf;
1346
1347     IAdviseSink_AddRef(this->sinkInterface);
1348   }
1349
1350   /*
1351    * When the ADVF_PRIMEFIRST flag is set, we have to advise the
1352    * sink immediately.
1353    */
1354   if (advf & ADVF_PRIMEFIRST)
1355   {
1356     DataCache_FireOnViewChange(this,
1357                                DVASPECT_CONTENT,
1358                                -1);
1359   }
1360
1361   return S_OK;
1362 }
1363
1364 /************************************************************************
1365  * DataCache_GetAdvise (IViewObject2)
1366  *
1367  * This method queries the current state of the advise sink
1368  * installed on the data cache.
1369  *
1370  * See Windows documentation for more details on IViewObject2 methods.
1371  */
1372 static HRESULT WINAPI DataCache_GetAdvise(
1373             IViewObject2*   iface,
1374             DWORD*          pAspects,
1375             DWORD*          pAdvf,
1376             IAdviseSink**   ppAdvSink)
1377 {
1378   DataCache *this = impl_from_IViewObject2(iface);
1379
1380   TRACE("(%p, %p, %p, %p)\n", iface, pAspects, pAdvf, ppAdvSink);
1381
1382   /*
1383    * Just copy all the requested values.
1384    */
1385   if (pAspects!=NULL)
1386     *pAspects = this->sinkAspects;
1387
1388   if (pAdvf!=NULL)
1389     *pAdvf = this->sinkAdviseFlag;
1390
1391   if (ppAdvSink!=NULL)
1392   {
1393     if (this->sinkInterface != NULL)
1394         IAdviseSink_QueryInterface(this->sinkInterface,
1395                                &IID_IAdviseSink,
1396                                (void**)ppAdvSink);
1397     else *ppAdvSink = NULL;
1398   }
1399
1400   return S_OK;
1401 }
1402
1403 /************************************************************************
1404  * DataCache_GetExtent (IViewObject2)
1405  *
1406  * This method retrieves the "natural" size of this cached object.
1407  *
1408  * See Windows documentation for more details on IViewObject2 methods.
1409  */
1410 static HRESULT WINAPI DataCache_GetExtent(
1411             IViewObject2*   iface,
1412             DWORD           dwDrawAspect,
1413             LONG            lindex,
1414             DVTARGETDEVICE* ptd,
1415             LPSIZEL         lpsizel)
1416 {
1417   PresentationDataHeader presData;
1418   HRESULT                hres = E_FAIL;
1419
1420   DataCache *this = impl_from_IViewObject2(iface);
1421
1422   TRACE("(%p, %lx, %ld, %p, %p)\n",
1423         iface, dwDrawAspect, lindex, ptd, lpsizel);
1424
1425   /*
1426    * Sanity check
1427    */
1428   if (lpsizel==NULL)
1429     return E_POINTER;
1430
1431   /*
1432    * Initialize the out parameter.
1433    */
1434   lpsizel->cx = 0;
1435   lpsizel->cy = 0;
1436
1437   /*
1438    * This flag should be set to -1.
1439    */
1440   if (lindex!=-1)
1441     FIXME("Unimplemented flag lindex = %ld\n", lindex);
1442
1443   /*
1444    * Right now, we support only the callback from
1445    * the default handler.
1446    */
1447   if (ptd!=NULL)
1448     FIXME("Unimplemented ptd = %p\n", ptd);
1449
1450   /*
1451    * Get the presentation information from the
1452    * cache.
1453    */
1454   hres = DataCache_ReadPresentationData(this,
1455                                         dwDrawAspect,
1456                                         &presData);
1457
1458   if (SUCCEEDED(hres))
1459   {
1460     lpsizel->cx = presData.dwObjectExtentX;
1461     lpsizel->cy = presData.dwObjectExtentY;
1462   }
1463
1464   /*
1465    * This method returns OLE_E_BLANK when it fails.
1466    */
1467   if (FAILED(hres))
1468     hres = OLE_E_BLANK;
1469
1470   return hres;
1471 }
1472
1473
1474 /*********************************************************
1475  * Method implementation for the IOleCache2
1476  * part of the DataCache class.
1477  */
1478
1479 /************************************************************************
1480  * DataCache_IOleCache2_QueryInterface (IUnknown)
1481  *
1482  * See Windows documentation for more details on IUnknown methods.
1483  */
1484 static HRESULT WINAPI DataCache_IOleCache2_QueryInterface(
1485             IOleCache2*     iface,
1486             REFIID          riid,
1487             void**          ppvObject)
1488 {
1489   DataCache *this = impl_from_IOleCache2(iface);
1490
1491   return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1492 }
1493
1494 /************************************************************************
1495  * DataCache_IOleCache2_AddRef (IUnknown)
1496  *
1497  * See Windows documentation for more details on IUnknown methods.
1498  */
1499 static ULONG WINAPI DataCache_IOleCache2_AddRef(
1500             IOleCache2*     iface)
1501 {
1502   DataCache *this = impl_from_IOleCache2(iface);
1503
1504   return IUnknown_AddRef(this->outerUnknown);
1505 }
1506
1507 /************************************************************************
1508  * DataCache_IOleCache2_Release (IUnknown)
1509  *
1510  * See Windows documentation for more details on IUnknown methods.
1511  */
1512 static ULONG WINAPI DataCache_IOleCache2_Release(
1513             IOleCache2*     iface)
1514 {
1515   DataCache *this = impl_from_IOleCache2(iface);
1516
1517   return IUnknown_Release(this->outerUnknown);
1518 }
1519
1520 static HRESULT WINAPI DataCache_Cache(
1521             IOleCache2*     iface,
1522             FORMATETC*      pformatetc,
1523             DWORD           advf,
1524             DWORD*          pdwConnection)
1525 {
1526   FIXME("stub\n");
1527   return E_NOTIMPL;
1528 }
1529
1530 static HRESULT WINAPI DataCache_Uncache(
1531             IOleCache2*     iface,
1532             DWORD           dwConnection)
1533 {
1534   FIXME("stub\n");
1535   return E_NOTIMPL;
1536 }
1537
1538 static HRESULT WINAPI DataCache_EnumCache(
1539             IOleCache2*     iface,
1540             IEnumSTATDATA** ppenumSTATDATA)
1541 {
1542   FIXME("stub\n");
1543   return E_NOTIMPL;
1544 }
1545
1546 static HRESULT WINAPI DataCache_InitCache(
1547             IOleCache2*     iface,
1548             IDataObject*    pDataObject)
1549 {
1550   FIXME("stub\n");
1551   return E_NOTIMPL;
1552 }
1553
1554 static HRESULT WINAPI DataCache_IOleCache2_SetData(
1555             IOleCache2*     iface,
1556             FORMATETC*      pformatetc,
1557             STGMEDIUM*      pmedium,
1558             BOOL            fRelease)
1559 {
1560   FIXME("stub\n");
1561   return E_NOTIMPL;
1562 }
1563
1564 static HRESULT WINAPI DataCache_UpdateCache(
1565             IOleCache2*     iface,
1566             LPDATAOBJECT    pDataObject,
1567             DWORD           grfUpdf,
1568             LPVOID          pReserved)
1569 {
1570   FIXME("stub\n");
1571   return E_NOTIMPL;
1572 }
1573
1574 static HRESULT WINAPI DataCache_DiscardCache(
1575             IOleCache2*     iface,
1576             DWORD           dwDiscardOptions)
1577 {
1578   FIXME("stub\n");
1579   return E_NOTIMPL;
1580 }
1581
1582
1583 /*********************************************************
1584  * Method implementation for the IOleCacheControl
1585  * part of the DataCache class.
1586  */
1587
1588 /************************************************************************
1589  * DataCache_IOleCacheControl_QueryInterface (IUnknown)
1590  *
1591  * See Windows documentation for more details on IUnknown methods.
1592  */
1593 static HRESULT WINAPI DataCache_IOleCacheControl_QueryInterface(
1594             IOleCacheControl* iface,
1595             REFIID            riid,
1596             void**            ppvObject)
1597 {
1598   DataCache *this = impl_from_IOleCacheControl(iface);
1599
1600   return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1601 }
1602
1603 /************************************************************************
1604  * DataCache_IOleCacheControl_AddRef (IUnknown)
1605  *
1606  * See Windows documentation for more details on IUnknown methods.
1607  */
1608 static ULONG WINAPI DataCache_IOleCacheControl_AddRef(
1609             IOleCacheControl* iface)
1610 {
1611   DataCache *this = impl_from_IOleCacheControl(iface);
1612
1613   return IUnknown_AddRef(this->outerUnknown);
1614 }
1615
1616 /************************************************************************
1617  * DataCache_IOleCacheControl_Release (IUnknown)
1618  *
1619  * See Windows documentation for more details on IUnknown methods.
1620  */
1621 static ULONG WINAPI DataCache_IOleCacheControl_Release(
1622             IOleCacheControl* iface)
1623 {
1624   DataCache *this = impl_from_IOleCacheControl(iface);
1625
1626   return IUnknown_Release(this->outerUnknown);
1627 }
1628
1629 static HRESULT WINAPI DataCache_OnRun(
1630             IOleCacheControl* iface,
1631             LPDATAOBJECT      pDataObject)
1632 {
1633   FIXME("stub\n");
1634   return E_NOTIMPL;
1635 }
1636
1637 static HRESULT WINAPI DataCache_OnStop(
1638             IOleCacheControl* iface)
1639 {
1640   FIXME("stub\n");
1641   return E_NOTIMPL;
1642 }
1643
1644 /*
1645  * Virtual function tables for the DataCache class.
1646  */
1647 static const IUnknownVtbl DataCache_NDIUnknown_VTable =
1648 {
1649   DataCache_NDIUnknown_QueryInterface,
1650   DataCache_NDIUnknown_AddRef,
1651   DataCache_NDIUnknown_Release
1652 };
1653
1654 static const IDataObjectVtbl DataCache_IDataObject_VTable =
1655 {
1656   DataCache_IDataObject_QueryInterface,
1657   DataCache_IDataObject_AddRef,
1658   DataCache_IDataObject_Release,
1659   DataCache_GetData,
1660   DataCache_GetDataHere,
1661   DataCache_QueryGetData,
1662   DataCache_GetCanonicalFormatEtc,
1663   DataCache_IDataObject_SetData,
1664   DataCache_EnumFormatEtc,
1665   DataCache_DAdvise,
1666   DataCache_DUnadvise,
1667   DataCache_EnumDAdvise
1668 };
1669
1670 static const IPersistStorageVtbl DataCache_IPersistStorage_VTable =
1671 {
1672   DataCache_IPersistStorage_QueryInterface,
1673   DataCache_IPersistStorage_AddRef,
1674   DataCache_IPersistStorage_Release,
1675   DataCache_GetClassID,
1676   DataCache_IsDirty,
1677   DataCache_InitNew,
1678   DataCache_Load,
1679   DataCache_Save,
1680   DataCache_SaveCompleted,
1681   DataCache_HandsOffStorage
1682 };
1683
1684 static const IViewObject2Vtbl DataCache_IViewObject2_VTable =
1685 {
1686   DataCache_IViewObject2_QueryInterface,
1687   DataCache_IViewObject2_AddRef,
1688   DataCache_IViewObject2_Release,
1689   DataCache_Draw,
1690   DataCache_GetColorSet,
1691   DataCache_Freeze,
1692   DataCache_Unfreeze,
1693   DataCache_SetAdvise,
1694   DataCache_GetAdvise,
1695   DataCache_GetExtent
1696 };
1697
1698 static const IOleCache2Vtbl DataCache_IOleCache2_VTable =
1699 {
1700   DataCache_IOleCache2_QueryInterface,
1701   DataCache_IOleCache2_AddRef,
1702   DataCache_IOleCache2_Release,
1703   DataCache_Cache,
1704   DataCache_Uncache,
1705   DataCache_EnumCache,
1706   DataCache_InitCache,
1707   DataCache_IOleCache2_SetData,
1708   DataCache_UpdateCache,
1709   DataCache_DiscardCache
1710 };
1711
1712 static const IOleCacheControlVtbl DataCache_IOleCacheControl_VTable =
1713 {
1714   DataCache_IOleCacheControl_QueryInterface,
1715   DataCache_IOleCacheControl_AddRef,
1716   DataCache_IOleCacheControl_Release,
1717   DataCache_OnRun,
1718   DataCache_OnStop
1719 };
1720
1721 /******************************************************************************
1722  *              CreateDataCache        [OLE32.@]
1723  */
1724 HRESULT WINAPI CreateDataCache(
1725   LPUNKNOWN pUnkOuter,
1726   REFCLSID  rclsid,
1727   REFIID    riid,
1728   LPVOID*   ppvObj)
1729 {
1730   DataCache* newCache = NULL;
1731   HRESULT    hr       = S_OK;
1732
1733   TRACE("(%s, %p, %s, %p)\n", debugstr_guid(rclsid), pUnkOuter, debugstr_guid(riid), ppvObj);
1734
1735   /*
1736    * Sanity check
1737    */
1738   if (ppvObj==0)
1739     return E_POINTER;
1740
1741   *ppvObj = 0;
1742
1743   /*
1744    * If this cache is constructed for aggregation, make sure
1745    * the caller is requesting the IUnknown interface.
1746    * This is necessary because it's the only time the non-delegating
1747    * IUnknown pointer can be returned to the outside.
1748    */
1749   if ( (pUnkOuter!=NULL) &&
1750        (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) != 0) )
1751     return CLASS_E_NOAGGREGATION;
1752
1753   /*
1754    * Try to construct a new instance of the class.
1755    */
1756   newCache = DataCache_Construct(rclsid,
1757                                  pUnkOuter);
1758
1759   if (newCache == 0)
1760     return E_OUTOFMEMORY;
1761
1762   /*
1763    * Make sure it supports the interface required by the caller.
1764    */
1765   hr = IUnknown_QueryInterface((IUnknown*)&(newCache->lpvtblNDIUnknown), riid, ppvObj);
1766
1767   /*
1768    * Release the reference obtained in the constructor. If
1769    * the QueryInterface was unsuccessful, it will free the class.
1770    */
1771   IUnknown_Release((IUnknown*)&(newCache->lpvtblNDIUnknown));
1772
1773   return hr;
1774 }
1775
1776 /*********************************************************
1777  * Method implementation for DataCache class.
1778  */
1779 static DataCache* DataCache_Construct(
1780   REFCLSID  clsid,
1781   LPUNKNOWN pUnkOuter)
1782 {
1783   DataCache* newObject = 0;
1784
1785   /*
1786    * Allocate space for the object.
1787    */
1788   newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(DataCache));
1789
1790   if (newObject==0)
1791     return newObject;
1792
1793   /*
1794    * Initialize the virtual function table.
1795    */
1796   newObject->lpVtbl = &DataCache_IDataObject_VTable;
1797   newObject->lpvtblNDIUnknown = &DataCache_NDIUnknown_VTable;
1798   newObject->lpvtblIPersistStorage = &DataCache_IPersistStorage_VTable;
1799   newObject->lpvtblIViewObject = &DataCache_IViewObject2_VTable;
1800   newObject->lpvtblIOleCache2 = &DataCache_IOleCache2_VTable;
1801   newObject->lpvtblIOleCacheControl = &DataCache_IOleCacheControl_VTable;
1802
1803   /*
1804    * Start with one reference count. The caller of this function
1805    * must release the interface pointer when it is done.
1806    */
1807   newObject->ref = 1;
1808
1809   /*
1810    * Initialize the outer unknown
1811    * We don't keep a reference on the outer unknown since, the way
1812    * aggregation works, our lifetime is at least as large as its
1813    * lifetime.
1814    */
1815   if (pUnkOuter==NULL)
1816     pUnkOuter = (IUnknown*)&(newObject->lpvtblNDIUnknown);
1817
1818   newObject->outerUnknown = pUnkOuter;
1819
1820   /*
1821    * Initialize the other members of the structure.
1822    */
1823   newObject->presentationStorage = NULL;
1824   newObject->sinkAspects = 0;
1825   newObject->sinkAdviseFlag = 0;
1826   newObject->sinkInterface = 0;
1827
1828   return newObject;
1829 }