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