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