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