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