Assorted spelling fixes.
[wine] / dlls / ole32 / datacache.c
1 /*
2  *      OLE 2 Data cache
3  *
4  *      Copyright 1999  Francis Beaudet
5  *      Copyright 2000  Abey George
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  * NOTES:
22  *    The OLE2 data cache supports a whole whack of
23  *    interfaces including:
24  *       IDataObject, IPersistStorage, IViewObject2,
25  *       IOleCache2 and IOleCacheControl.
26  *
27  *    Most of the implementation details are taken from: Inside OLE
28  *    second edition by Kraig Brockschmidt,
29  *
30  * NOTES
31  *  -  This implementation of the datacache will let your application
32  *     load documents that have embedded OLE objects in them and it will
33  *     also retrieve the metafile representation of those objects.
34  *  -  This implementation of the datacache will also allow your
35  *     application to save new documents with OLE objects in them.
36  *  -  The main thing that it doesn't do is allow you to activate
37  *     or modify the OLE objects in any way.
38  *  -  I haven't found any good documentation on the real usage of
39  *     the streams created by the data cache. In particular, How to
40  *     determine what the XXX stands for in the stream name
41  *     "\002OlePresXXX". It appears to just be a counter.
42  *  -  Also, I don't know the real content of the presentation stream
43  *     header. I was able to figure-out where the extent of the object
44  *     was stored and the aspect, but that's about it.
45  */
46 #include <assert.h>
47 #include <stdarg.h>
48 #include <string.h>
49
50 #define COBJMACROS
51 #define NONAMELESSUNION
52 #define NONAMELESSSTRUCT
53
54 #include "windef.h"
55 #include "winbase.h"
56 #include "wingdi.h"
57 #include "winuser.h"
58 #include "winerror.h"
59 #include "wine/unicode.h"
60 #include "ole2.h"
61 #include "wine/debug.h"
62
63 WINE_DEFAULT_DEBUG_CHANNEL(ole);
64
65 /****************************************************************************
66  * PresentationDataHeader
67  *
68  * This structure represents the header of the \002OlePresXXX stream in
69  * the OLE object strorage.
70  *
71  * Most fields are still unknown.
72  */
73 typedef struct PresentationDataHeader
74 {
75   DWORD unknown1;       /* -1 */
76   DWORD unknown2;       /* 3, possibly CF_METAFILEPICT */
77   DWORD unknown3;       /* 4, possibly TYMED_ISTREAM */
78   DVASPECT dvAspect;
79   DWORD unknown5;       /* -1 */
80
81   DWORD unknown6;
82   DWORD unknown7;       /* 0 */
83   DWORD dwObjectExtentX;
84   DWORD dwObjectExtentY;
85   DWORD dwSize;
86 } PresentationDataHeader;
87
88 /****************************************************************************
89  * DataCache
90  */
91 struct DataCache
92 {
93   /*
94    * List all interface VTables here
95    */
96   IDataObjectVtbl*      lpvtbl1;
97   IUnknownVtbl*         lpvtbl2;
98   IPersistStorageVtbl*  lpvtbl3;
99   IViewObject2Vtbl*     lpvtbl4;
100   IOleCache2Vtbl*       lpvtbl5;
101   IOleCacheControlVtbl* lpvtbl6;
102
103   /*
104    * Reference count of this object
105    */
106   ULONG ref;
107
108   /*
109    * IUnknown implementation of the outer object.
110    */
111   IUnknown* outerUnknown;
112
113   /*
114    * This storage pointer is set through a call to
115    * IPersistStorage_Load. This is where the visual
116    * representation of the object is stored.
117    */
118   IStorage* presentationStorage;
119
120   /*
121    * The user of this object can setup ONE advise sink
122    * connection with the object. These parameters describe
123    * that connection.
124    */
125   DWORD        sinkAspects;
126   DWORD        sinkAdviseFlag;
127   IAdviseSink* sinkInterface;
128
129 };
130
131 typedef struct DataCache DataCache;
132
133 /*
134  * Here, I define utility macros to help with the casting of the
135  * "this" parameter.
136  * There is a version to accommodate all of the VTables implemented
137  * by this object.
138  */
139 #define _ICOM_THIS_From_IDataObject(class,name)       class* this = (class*)name
140 #define _ICOM_THIS_From_NDIUnknown(class, name)       class* this = (class*)(((char*)name)-sizeof(void*))
141 #define _ICOM_THIS_From_IPersistStorage(class, name)  class* this = (class*)(((char*)name)-2*sizeof(void*))
142 #define _ICOM_THIS_From_IViewObject2(class, name)     class* this = (class*)(((char*)name)-3*sizeof(void*))
143 #define _ICOM_THIS_From_IOleCache2(class, name)       class* this = (class*)(((char*)name)-4*sizeof(void*))
144 #define _ICOM_THIS_From_IOleCacheControl(class, name) class* this = (class*)(((char*)name)-5*sizeof(void*))
145
146 /*
147  * Prototypes for the methods of the DataCache class.
148  */
149 static DataCache* DataCache_Construct(REFCLSID  clsid,
150                                       LPUNKNOWN pUnkOuter);
151 static void       DataCache_Destroy(DataCache* ptrToDestroy);
152 static HRESULT    DataCache_ReadPresentationData(DataCache*              this,
153                                                  DWORD                   drawAspect,
154                                                  PresentationDataHeader* header);
155 static HRESULT    DataCache_OpenPresStream(DataCache *this,
156                                            DWORD      drawAspect,
157                                            IStream  **pStm);
158 static HMETAFILE  DataCache_ReadPresMetafile(DataCache* this,
159                                              DWORD      drawAspect);
160 static void       DataCache_FireOnViewChange(DataCache* this,
161                                              DWORD      aspect,
162                                              LONG       lindex);
163
164 /*
165  * Prototypes for the methods of the DataCache class
166  * that implement non delegating IUnknown methods.
167  */
168 static HRESULT WINAPI DataCache_NDIUnknown_QueryInterface(
169             IUnknown*      iface,
170             REFIID         riid,
171             void**         ppvObject);
172 static ULONG WINAPI DataCache_NDIUnknown_AddRef(
173             IUnknown*      iface);
174 static ULONG WINAPI DataCache_NDIUnknown_Release(
175             IUnknown*      iface);
176
177 /*
178  * Prototypes for the methods of the DataCache class
179  * that implement IDataObject methods.
180  */
181 static HRESULT WINAPI DataCache_IDataObject_QueryInterface(
182             IDataObject*     iface,
183             REFIID           riid,
184             void**           ppvObject);
185 static ULONG WINAPI DataCache_IDataObject_AddRef(
186             IDataObject*     iface);
187 static ULONG WINAPI DataCache_IDataObject_Release(
188             IDataObject*     iface);
189 static HRESULT WINAPI DataCache_GetData(
190             IDataObject*     iface,
191             LPFORMATETC      pformatetcIn,
192             STGMEDIUM*       pmedium);
193 static HRESULT WINAPI DataCache_GetDataHere(
194             IDataObject*     iface,
195             LPFORMATETC      pformatetc,
196             STGMEDIUM*       pmedium);
197 static HRESULT WINAPI DataCache_QueryGetData(
198             IDataObject*     iface,
199             LPFORMATETC      pformatetc);
200 static HRESULT WINAPI DataCache_GetCanonicalFormatEtc(
201             IDataObject*     iface,
202             LPFORMATETC      pformatectIn,
203             LPFORMATETC      pformatetcOut);
204 static HRESULT WINAPI DataCache_IDataObject_SetData(
205             IDataObject*     iface,
206             LPFORMATETC      pformatetc,
207             STGMEDIUM*       pmedium,
208             BOOL             fRelease);
209 static HRESULT WINAPI DataCache_EnumFormatEtc(
210             IDataObject*     iface,
211             DWORD            dwDirection,
212             IEnumFORMATETC** ppenumFormatEtc);
213 static HRESULT WINAPI DataCache_DAdvise(
214             IDataObject*     iface,
215             FORMATETC*       pformatetc,
216             DWORD            advf,
217             IAdviseSink*     pAdvSink,
218             DWORD*           pdwConnection);
219 static HRESULT WINAPI DataCache_DUnadvise(
220             IDataObject*     iface,
221             DWORD            dwConnection);
222 static HRESULT WINAPI DataCache_EnumDAdvise(
223             IDataObject*     iface,
224             IEnumSTATDATA**  ppenumAdvise);
225
226 /*
227  * Prototypes for the methods of the DataCache class
228  * that implement IPersistStorage methods.
229  */
230 static HRESULT WINAPI DataCache_IPersistStorage_QueryInterface(
231             IPersistStorage* iface,
232             REFIID           riid,
233             void**           ppvObject);
234 static ULONG WINAPI DataCache_IPersistStorage_AddRef(
235             IPersistStorage* iface);
236 static ULONG WINAPI DataCache_IPersistStorage_Release(
237             IPersistStorage* iface);
238 static HRESULT WINAPI DataCache_GetClassID(
239             IPersistStorage* iface,
240             CLSID*           pClassID);
241 static HRESULT WINAPI DataCache_IsDirty(
242             IPersistStorage* iface);
243 static HRESULT WINAPI DataCache_InitNew(
244             IPersistStorage* iface,
245             IStorage*        pStg);
246 static HRESULT WINAPI DataCache_Load(
247             IPersistStorage* iface,
248             IStorage*        pStg);
249 static HRESULT WINAPI DataCache_Save(
250             IPersistStorage* iface,
251             IStorage*        pStg,
252             BOOL             fSameAsLoad);
253 static HRESULT WINAPI DataCache_SaveCompleted(
254             IPersistStorage* iface,
255             IStorage*        pStgNew);
256 static HRESULT WINAPI DataCache_HandsOffStorage(
257             IPersistStorage* iface);
258
259 /*
260  * Prototypes for the methods of the DataCache class
261  * that implement IViewObject2 methods.
262  */
263 static HRESULT WINAPI DataCache_IViewObject2_QueryInterface(
264             IViewObject2* iface,
265             REFIID           riid,
266             void**           ppvObject);
267 static ULONG WINAPI DataCache_IViewObject2_AddRef(
268             IViewObject2* iface);
269 static ULONG WINAPI DataCache_IViewObject2_Release(
270             IViewObject2* iface);
271 static HRESULT WINAPI DataCache_Draw(
272             IViewObject2*    iface,
273             DWORD            dwDrawAspect,
274             LONG             lindex,
275             void*            pvAspect,
276             DVTARGETDEVICE*  ptd,
277             HDC              hdcTargetDev,
278             HDC              hdcDraw,
279             LPCRECTL         lprcBounds,
280             LPCRECTL         lprcWBounds,
281             BOOL  (CALLBACK *pfnContinue)(ULONG_PTR dwContinue),
282             ULONG_PTR        dwContinue);
283 static HRESULT WINAPI DataCache_GetColorSet(
284             IViewObject2*   iface,
285             DWORD           dwDrawAspect,
286             LONG            lindex,
287             void*           pvAspect,
288             DVTARGETDEVICE* ptd,
289             HDC             hicTargetDevice,
290             LOGPALETTE**    ppColorSet);
291 static HRESULT WINAPI DataCache_Freeze(
292             IViewObject2*   iface,
293             DWORD           dwDrawAspect,
294             LONG            lindex,
295             void*           pvAspect,
296             DWORD*          pdwFreeze);
297 static HRESULT WINAPI DataCache_Unfreeze(
298             IViewObject2*   iface,
299             DWORD           dwFreeze);
300 static HRESULT WINAPI DataCache_SetAdvise(
301             IViewObject2*   iface,
302             DWORD           aspects,
303             DWORD           advf,
304             IAdviseSink*    pAdvSink);
305 static HRESULT WINAPI DataCache_GetAdvise(
306             IViewObject2*   iface,
307             DWORD*          pAspects,
308             DWORD*          pAdvf,
309             IAdviseSink**   ppAdvSink);
310 static HRESULT WINAPI DataCache_GetExtent(
311             IViewObject2*   iface,
312             DWORD           dwDrawAspect,
313             LONG            lindex,
314             DVTARGETDEVICE* ptd,
315             LPSIZEL         lpsizel);
316
317 /*
318  * Prototypes for the methods of the DataCache class
319  * that implement IOleCache2 methods.
320  */
321 static HRESULT WINAPI DataCache_IOleCache2_QueryInterface(
322             IOleCache2*     iface,
323             REFIID          riid,
324             void**          ppvObject);
325 static ULONG WINAPI DataCache_IOleCache2_AddRef(
326             IOleCache2*     iface);
327 static ULONG WINAPI DataCache_IOleCache2_Release(
328             IOleCache2*     iface);
329 static HRESULT WINAPI DataCache_Cache(
330             IOleCache2*     iface,
331             FORMATETC*      pformatetc,
332             DWORD           advf,
333             DWORD*          pdwConnection);
334 static HRESULT WINAPI DataCache_Uncache(
335             IOleCache2*     iface,
336             DWORD           dwConnection);
337 static HRESULT WINAPI DataCache_EnumCache(
338             IOleCache2*     iface,
339             IEnumSTATDATA** ppenumSTATDATA);
340 static HRESULT WINAPI DataCache_InitCache(
341             IOleCache2*     iface,
342             IDataObject*    pDataObject);
343 static HRESULT WINAPI DataCache_IOleCache2_SetData(
344             IOleCache2*     iface,
345             FORMATETC*      pformatetc,
346             STGMEDIUM*      pmedium,
347             BOOL            fRelease);
348 static HRESULT WINAPI DataCache_UpdateCache(
349             IOleCache2*     iface,
350             LPDATAOBJECT    pDataObject,
351             DWORD           grfUpdf,
352             LPVOID          pReserved);
353 static HRESULT WINAPI DataCache_DiscardCache(
354             IOleCache2*     iface,
355             DWORD           dwDiscardOptions);
356
357 /*
358  * Prototypes for the methods of the DataCache class
359  * that implement IOleCacheControl methods.
360  */
361 static HRESULT WINAPI DataCache_IOleCacheControl_QueryInterface(
362             IOleCacheControl* iface,
363             REFIID            riid,
364             void**            ppvObject);
365 static ULONG WINAPI DataCache_IOleCacheControl_AddRef(
366             IOleCacheControl* iface);
367 static ULONG WINAPI DataCache_IOleCacheControl_Release(
368             IOleCacheControl* iface);
369 static HRESULT WINAPI DataCache_OnRun(
370             IOleCacheControl* iface,
371             LPDATAOBJECT      pDataObject);
372 static HRESULT WINAPI DataCache_OnStop(
373             IOleCacheControl* iface);
374
375 /*
376  * Virtual function tables for the DataCache class.
377  */
378 static IUnknownVtbl DataCache_NDIUnknown_VTable =
379 {
380   DataCache_NDIUnknown_QueryInterface,
381   DataCache_NDIUnknown_AddRef,
382   DataCache_NDIUnknown_Release
383 };
384
385 static IDataObjectVtbl DataCache_IDataObject_VTable =
386 {
387   DataCache_IDataObject_QueryInterface,
388   DataCache_IDataObject_AddRef,
389   DataCache_IDataObject_Release,
390   DataCache_GetData,
391   DataCache_GetDataHere,
392   DataCache_QueryGetData,
393   DataCache_GetCanonicalFormatEtc,
394   DataCache_IDataObject_SetData,
395   DataCache_EnumFormatEtc,
396   DataCache_DAdvise,
397   DataCache_DUnadvise,
398   DataCache_EnumDAdvise
399 };
400
401 static IPersistStorageVtbl DataCache_IPersistStorage_VTable =
402 {
403   DataCache_IPersistStorage_QueryInterface,
404   DataCache_IPersistStorage_AddRef,
405   DataCache_IPersistStorage_Release,
406   DataCache_GetClassID,
407   DataCache_IsDirty,
408   DataCache_InitNew,
409   DataCache_Load,
410   DataCache_Save,
411   DataCache_SaveCompleted,
412   DataCache_HandsOffStorage
413 };
414
415 static IViewObject2Vtbl DataCache_IViewObject2_VTable =
416 {
417   DataCache_IViewObject2_QueryInterface,
418   DataCache_IViewObject2_AddRef,
419   DataCache_IViewObject2_Release,
420   DataCache_Draw,
421   DataCache_GetColorSet,
422   DataCache_Freeze,
423   DataCache_Unfreeze,
424   DataCache_SetAdvise,
425   DataCache_GetAdvise,
426   DataCache_GetExtent
427 };
428
429 static IOleCache2Vtbl DataCache_IOleCache2_VTable =
430 {
431   DataCache_IOleCache2_QueryInterface,
432   DataCache_IOleCache2_AddRef,
433   DataCache_IOleCache2_Release,
434   DataCache_Cache,
435   DataCache_Uncache,
436   DataCache_EnumCache,
437   DataCache_InitCache,
438   DataCache_IOleCache2_SetData,
439   DataCache_UpdateCache,
440   DataCache_DiscardCache
441 };
442
443 static IOleCacheControlVtbl DataCache_IOleCacheControl_VTable =
444 {
445   DataCache_IOleCacheControl_QueryInterface,
446   DataCache_IOleCacheControl_AddRef,
447   DataCache_IOleCacheControl_Release,
448   DataCache_OnRun,
449   DataCache_OnStop
450 };
451
452 /******************************************************************************
453  *              CreateDataCache        [OLE32.@]
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.u.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.u.LowPart = 0;
765                     offset.u.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.u.HighPart = 0;
835   offset.u.LowPart  = sizeof(PresentationDataHeader);
836
837   hres = IStream_Seek(
838            presStream,
839            offset,
840            STREAM_SEEK_SET,
841            NULL);
842
843   streamInfo.cbSize.u.LowPart -= offset.u.LowPart;
844
845   /*
846    * Allocate a buffer for the metafile bits.
847    */
848   metafileBits = HeapAlloc(GetProcessHeap(),
849                            0,
850                            streamInfo.cbSize.u.LowPart);
851
852   /*
853    * Read the metafile bits.
854    */
855   hres = IStream_Read(
856            presStream,
857            metafileBits,
858            streamInfo.cbSize.u.LowPart,
859            NULL);
860
861   /*
862    * Create a metafile with those bits.
863    */
864   if (SUCCEEDED(hres))
865   {
866     newMetafile = SetMetaFileBitsEx(streamInfo.cbSize.u.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   return InterlockedIncrement(&this->ref);
974 }
975
976 /************************************************************************
977  * DataCache_NDIUnknown_Release (IUnknown)
978  *
979  * See Windows documentation for more details on IUnknown methods.
980  *
981  * This version of QueryInterface will not delegate it's implementation
982  * to the outer unknown.
983  */
984 static ULONG WINAPI DataCache_NDIUnknown_Release(
985             IUnknown*      iface)
986 {
987   _ICOM_THIS_From_NDIUnknown(DataCache, iface);
988   ULONG ref;
989
990   /*
991    * Decrease the reference count on this object.
992    */
993   ref = InterlockedDecrement(&this->ref);
994
995   /*
996    * If the reference count goes down to 0, perform suicide.
997    */
998   if (ref == 0) DataCache_Destroy(this);
999
1000   return ref;
1001 }
1002
1003 /*********************************************************
1004  * Method implementation for the IDataObject
1005  * part of the DataCache class.
1006  */
1007
1008 /************************************************************************
1009  * DataCache_IDataObject_QueryInterface (IUnknown)
1010  *
1011  * See Windows documentation for more details on IUnknown methods.
1012  */
1013 static HRESULT WINAPI DataCache_IDataObject_QueryInterface(
1014             IDataObject*     iface,
1015             REFIID           riid,
1016             void**           ppvObject)
1017 {
1018   _ICOM_THIS_From_IDataObject(DataCache, iface);
1019
1020   return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1021 }
1022
1023 /************************************************************************
1024  * DataCache_IDataObject_AddRef (IUnknown)
1025  *
1026  * See Windows documentation for more details on IUnknown methods.
1027  */
1028 static ULONG WINAPI DataCache_IDataObject_AddRef(
1029             IDataObject*     iface)
1030 {
1031   _ICOM_THIS_From_IDataObject(DataCache, iface);
1032
1033   return IUnknown_AddRef(this->outerUnknown);
1034 }
1035
1036 /************************************************************************
1037  * DataCache_IDataObject_Release (IUnknown)
1038  *
1039  * See Windows documentation for more details on IUnknown methods.
1040  */
1041 static ULONG WINAPI DataCache_IDataObject_Release(
1042             IDataObject*     iface)
1043 {
1044   _ICOM_THIS_From_IDataObject(DataCache, iface);
1045
1046   return IUnknown_Release(this->outerUnknown);
1047 }
1048
1049 /************************************************************************
1050  * DataCache_GetData
1051  *
1052  * Get Data from a source dataobject using format pformatetcIn->cfFormat
1053  * See Windows documentation for more details on GetData.
1054  * TODO: Currently only CF_METAFILEPICT is implemented
1055  */
1056 static HRESULT WINAPI DataCache_GetData(
1057             IDataObject*     iface,
1058             LPFORMATETC      pformatetcIn,
1059             STGMEDIUM*       pmedium)
1060 {
1061   HRESULT hr = 0;
1062   HRESULT hrRet = E_UNEXPECTED;
1063   IPersistStorage *pPersistStorage = 0;
1064   IStorage *pStorage = 0;
1065   IStream *pStream = 0;
1066   OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
1067   HGLOBAL hGlobalMF = 0;
1068   void *mfBits = 0;
1069   PresentationDataHeader pdh;
1070   METAFILEPICT *mfPict;
1071   HMETAFILE hMetaFile = 0;
1072
1073   if (pformatetcIn->cfFormat == CF_METAFILEPICT)
1074   {
1075     /* Get the Persist Storage */
1076
1077     hr = IDataObject_QueryInterface(iface, &IID_IPersistStorage, (void**)&pPersistStorage);
1078
1079     if (hr != S_OK)
1080       goto cleanup;
1081
1082     /* Create a doc file to copy the doc to a storage */
1083
1084     hr = StgCreateDocfile(NULL, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &pStorage);
1085
1086     if (hr != S_OK)
1087       goto cleanup;
1088
1089     /* Save it to storage */
1090
1091     hr = OleSave(pPersistStorage, pStorage, FALSE);
1092
1093     if (hr != S_OK)
1094       goto cleanup;
1095
1096     /* Open the Presentation data srteam */
1097
1098     hr = IStorage_OpenStream(pStorage, name, 0, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &pStream);
1099
1100     if (hr != S_OK)
1101       goto cleanup;
1102
1103     /* Read the presentation header */
1104
1105     hr = IStream_Read(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
1106
1107     if (hr != S_OK)
1108       goto cleanup;
1109
1110     mfBits = HeapAlloc(GetProcessHeap(), 0, pdh.dwSize);
1111
1112     /* Read the Metafile bits */
1113
1114     hr = IStream_Read(pStream, mfBits, pdh.dwSize, NULL);
1115
1116     if (hr != S_OK)
1117       goto cleanup;
1118
1119     /* Create the metafile and place it in the STGMEDIUM structure */
1120
1121     hMetaFile = SetMetaFileBitsEx(pdh.dwSize, mfBits);
1122
1123     hGlobalMF = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, sizeof(METAFILEPICT));
1124     mfPict = (METAFILEPICT *)GlobalLock(hGlobalMF);
1125     mfPict->hMF = hMetaFile;
1126
1127     GlobalUnlock(hGlobalMF);
1128
1129     pmedium->u.hGlobal = hGlobalMF;
1130     pmedium->tymed = TYMED_MFPICT;
1131     hrRet = S_OK;
1132
1133 cleanup:
1134
1135     HeapFree(GetProcessHeap(), 0, mfBits);
1136
1137     if (pStream)
1138       IStream_Release(pStream);
1139
1140     if (pStorage)
1141       IStorage_Release(pStorage);
1142
1143     if (pPersistStorage)
1144       IPersistStorage_Release(pPersistStorage);
1145
1146     return hrRet;
1147   }
1148
1149   /* TODO: Other formats are not implemented */
1150
1151   return E_NOTIMPL;
1152 }
1153
1154 static HRESULT WINAPI DataCache_GetDataHere(
1155             IDataObject*     iface,
1156             LPFORMATETC      pformatetc,
1157             STGMEDIUM*       pmedium)
1158 {
1159   FIXME("stub\n");
1160   return E_NOTIMPL;
1161 }
1162
1163 static HRESULT WINAPI DataCache_QueryGetData(
1164             IDataObject*     iface,
1165             LPFORMATETC      pformatetc)
1166 {
1167   FIXME("stub\n");
1168   return E_NOTIMPL;
1169 }
1170
1171 /************************************************************************
1172  * DataCache_EnumFormatEtc (IDataObject)
1173  *
1174  * The data cache doesn't implement this method.
1175  *
1176  * See Windows documentation for more details on IDataObject methods.
1177  */
1178 static HRESULT WINAPI DataCache_GetCanonicalFormatEtc(
1179             IDataObject*     iface,
1180             LPFORMATETC      pformatectIn,
1181             LPFORMATETC      pformatetcOut)
1182 {
1183   TRACE("()\n");
1184   return E_NOTIMPL;
1185 }
1186
1187 /************************************************************************
1188  * DataCache_IDataObject_SetData (IDataObject)
1189  *
1190  * This method is delegated to the IOleCache2 implementation.
1191  *
1192  * See Windows documentation for more details on IDataObject methods.
1193  */
1194 static HRESULT WINAPI DataCache_IDataObject_SetData(
1195             IDataObject*     iface,
1196             LPFORMATETC      pformatetc,
1197             STGMEDIUM*       pmedium,
1198             BOOL             fRelease)
1199 {
1200   IOleCache2* oleCache = NULL;
1201   HRESULT     hres;
1202
1203   TRACE("(%p, %p, %p, %d)\n", iface, pformatetc, pmedium, fRelease);
1204
1205   hres = IDataObject_QueryInterface(iface, &IID_IOleCache2, (void**)&oleCache);
1206
1207   if (FAILED(hres))
1208     return E_UNEXPECTED;
1209
1210   hres = IOleCache2_SetData(oleCache, pformatetc, pmedium, fRelease);
1211
1212   IOleCache2_Release(oleCache);
1213
1214   return hres;
1215 }
1216
1217 /************************************************************************
1218  * DataCache_EnumFormatEtc (IDataObject)
1219  *
1220  * The data cache doesn't implement this method.
1221  *
1222  * See Windows documentation for more details on IDataObject methods.
1223  */
1224 static HRESULT WINAPI DataCache_EnumFormatEtc(
1225             IDataObject*     iface,
1226             DWORD            dwDirection,
1227             IEnumFORMATETC** ppenumFormatEtc)
1228 {
1229   TRACE("()\n");
1230   return E_NOTIMPL;
1231 }
1232
1233 /************************************************************************
1234  * DataCache_DAdvise (IDataObject)
1235  *
1236  * The data cache doesn't support connections.
1237  *
1238  * See Windows documentation for more details on IDataObject methods.
1239  */
1240 static HRESULT WINAPI DataCache_DAdvise(
1241             IDataObject*     iface,
1242             FORMATETC*       pformatetc,
1243             DWORD            advf,
1244             IAdviseSink*     pAdvSink,
1245             DWORD*           pdwConnection)
1246 {
1247   TRACE("()\n");
1248   return OLE_E_ADVISENOTSUPPORTED;
1249 }
1250
1251 /************************************************************************
1252  * DataCache_DUnadvise (IDataObject)
1253  *
1254  * The data cache doesn't support connections.
1255  *
1256  * See Windows documentation for more details on IDataObject methods.
1257  */
1258 static HRESULT WINAPI DataCache_DUnadvise(
1259             IDataObject*     iface,
1260             DWORD            dwConnection)
1261 {
1262   TRACE("()\n");
1263   return OLE_E_NOCONNECTION;
1264 }
1265
1266 /************************************************************************
1267  * DataCache_EnumDAdvise (IDataObject)
1268  *
1269  * The data cache doesn't support connections.
1270  *
1271  * See Windows documentation for more details on IDataObject methods.
1272  */
1273 static HRESULT WINAPI DataCache_EnumDAdvise(
1274             IDataObject*     iface,
1275             IEnumSTATDATA**  ppenumAdvise)
1276 {
1277   TRACE("()\n");
1278   return OLE_E_ADVISENOTSUPPORTED;
1279 }
1280
1281 /*********************************************************
1282  * Method implementation for the IDataObject
1283  * part of the DataCache class.
1284  */
1285
1286 /************************************************************************
1287  * DataCache_IPersistStorage_QueryInterface (IUnknown)
1288  *
1289  * See Windows documentation for more details on IUnknown methods.
1290  */
1291 static HRESULT WINAPI DataCache_IPersistStorage_QueryInterface(
1292             IPersistStorage* iface,
1293             REFIID           riid,
1294             void**           ppvObject)
1295 {
1296   _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1297
1298   return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1299 }
1300
1301 /************************************************************************
1302  * DataCache_IPersistStorage_AddRef (IUnknown)
1303  *
1304  * See Windows documentation for more details on IUnknown methods.
1305  */
1306 static ULONG WINAPI DataCache_IPersistStorage_AddRef(
1307             IPersistStorage* iface)
1308 {
1309   _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1310
1311   return IUnknown_AddRef(this->outerUnknown);
1312 }
1313
1314 /************************************************************************
1315  * DataCache_IPersistStorage_Release (IUnknown)
1316  *
1317  * See Windows documentation for more details on IUnknown methods.
1318  */
1319 static ULONG WINAPI DataCache_IPersistStorage_Release(
1320             IPersistStorage* iface)
1321 {
1322   _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1323
1324   return IUnknown_Release(this->outerUnknown);
1325 }
1326
1327 /************************************************************************
1328  * DataCache_GetClassID (IPersistStorage)
1329  *
1330  * The data cache doesn't implement this method.
1331  *
1332  * See Windows documentation for more details on IPersistStorage methods.
1333  */
1334 static HRESULT WINAPI DataCache_GetClassID(
1335             IPersistStorage* iface,
1336             CLSID*           pClassID)
1337 {
1338   TRACE("(%p, %p)\n", iface, pClassID);
1339   return E_NOTIMPL;
1340 }
1341
1342 /************************************************************************
1343  * DataCache_IsDirty (IPersistStorage)
1344  *
1345  * Until we actully connect to a running object and retrieve new
1346  * information to it, we never get dirty.
1347  *
1348  * See Windows documentation for more details on IPersistStorage methods.
1349  */
1350 static HRESULT WINAPI DataCache_IsDirty(
1351             IPersistStorage* iface)
1352 {
1353   TRACE("(%p)\n", iface);
1354
1355   return S_FALSE;
1356 }
1357
1358 /************************************************************************
1359  * DataCache_InitNew (IPersistStorage)
1360  *
1361  * The data cache implementation of IPersistStorage_InitNew simply stores
1362  * the storage pointer.
1363  *
1364  * See Windows documentation for more details on IPersistStorage methods.
1365  */
1366 static HRESULT WINAPI DataCache_InitNew(
1367             IPersistStorage* iface,
1368             IStorage*        pStg)
1369 {
1370   TRACE("(%p, %p)\n", iface, pStg);
1371
1372   return DataCache_Load(iface, pStg);
1373 }
1374
1375 /************************************************************************
1376  * DataCache_Load (IPersistStorage)
1377  *
1378  * The data cache implementation of IPersistStorage_Load doesn't
1379  * actually load anything. Instead, it holds on to the storage pointer
1380  * and it will load the presentation information when the
1381  * IDataObject_GetData or IViewObject2_Draw methods are called.
1382  *
1383  * See Windows documentation for more details on IPersistStorage methods.
1384  */
1385 static HRESULT WINAPI DataCache_Load(
1386             IPersistStorage* iface,
1387             IStorage*        pStg)
1388 {
1389   _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1390
1391   TRACE("(%p, %p)\n", iface, pStg);
1392
1393   if (this->presentationStorage != NULL)
1394   {
1395     IStorage_Release(this->presentationStorage);
1396   }
1397
1398   this->presentationStorage = pStg;
1399
1400   if (this->presentationStorage != NULL)
1401   {
1402     IStorage_AddRef(this->presentationStorage);
1403   }
1404   return S_OK;
1405 }
1406
1407 /************************************************************************
1408  * DataCache_Save (IPersistStorage)
1409  *
1410  * Until we actully connect to a running object and retrieve new
1411  * information to it, we never have to save anything. However, it is
1412  * our responsability to copy the information when saving to a new
1413  * storage.
1414  *
1415  * See Windows documentation for more details on IPersistStorage methods.
1416  */
1417 static HRESULT WINAPI DataCache_Save(
1418             IPersistStorage* iface,
1419             IStorage*        pStg,
1420             BOOL             fSameAsLoad)
1421 {
1422   _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1423
1424   TRACE("(%p, %p, %d)\n", iface, pStg, fSameAsLoad);
1425
1426   if ( (!fSameAsLoad) &&
1427        (this->presentationStorage!=NULL) )
1428   {
1429     return IStorage_CopyTo(this->presentationStorage,
1430                            0,
1431                            NULL,
1432                            NULL,
1433                            pStg);
1434   }
1435
1436   return S_OK;
1437 }
1438
1439 /************************************************************************
1440  * DataCache_SaveCompleted (IPersistStorage)
1441  *
1442  * This method is called to tell the cache to release the storage
1443  * pointer it's currentlu holding.
1444  *
1445  * See Windows documentation for more details on IPersistStorage methods.
1446  */
1447 static HRESULT WINAPI DataCache_SaveCompleted(
1448             IPersistStorage* iface,
1449             IStorage*        pStgNew)
1450 {
1451   TRACE("(%p, %p)\n", iface, pStgNew);
1452
1453   if (pStgNew)
1454   {
1455   /*
1456    * First, make sure we get our hands off any storage we have.
1457    */
1458
1459   DataCache_HandsOffStorage(iface);
1460
1461   /*
1462    * Then, attach to the new storage.
1463    */
1464
1465   DataCache_Load(iface, pStgNew);
1466   }
1467
1468   return S_OK;
1469 }
1470
1471 /************************************************************************
1472  * DataCache_HandsOffStorage (IPersistStorage)
1473  *
1474  * This method is called to tell the cache to release the storage
1475  * pointer it's currentlu holding.
1476  *
1477  * See Windows documentation for more details on IPersistStorage methods.
1478  */
1479 static HRESULT WINAPI DataCache_HandsOffStorage(
1480             IPersistStorage* iface)
1481 {
1482   _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1483
1484   TRACE("(%p)\n", iface);
1485
1486   if (this->presentationStorage != NULL)
1487   {
1488     IStorage_Release(this->presentationStorage);
1489     this->presentationStorage = NULL;
1490   }
1491
1492   return S_OK;
1493 }
1494
1495 /*********************************************************
1496  * Method implementation for the IViewObject2
1497  * part of the DataCache class.
1498  */
1499
1500 /************************************************************************
1501  * DataCache_IViewObject2_QueryInterface (IUnknown)
1502  *
1503  * See Windows documentation for more details on IUnknown methods.
1504  */
1505 static HRESULT WINAPI DataCache_IViewObject2_QueryInterface(
1506             IViewObject2* iface,
1507             REFIID           riid,
1508             void**           ppvObject)
1509 {
1510   _ICOM_THIS_From_IViewObject2(DataCache, iface);
1511
1512   return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1513 }
1514
1515 /************************************************************************
1516  * DataCache_IViewObject2_AddRef (IUnknown)
1517  *
1518  * See Windows documentation for more details on IUnknown methods.
1519  */
1520 static ULONG WINAPI DataCache_IViewObject2_AddRef(
1521             IViewObject2* iface)
1522 {
1523   _ICOM_THIS_From_IViewObject2(DataCache, iface);
1524
1525   return IUnknown_AddRef(this->outerUnknown);
1526 }
1527
1528 /************************************************************************
1529  * DataCache_IViewObject2_Release (IUnknown)
1530  *
1531  * See Windows documentation for more details on IUnknown methods.
1532  */
1533 static ULONG WINAPI DataCache_IViewObject2_Release(
1534             IViewObject2* iface)
1535 {
1536   _ICOM_THIS_From_IViewObject2(DataCache, iface);
1537
1538   return IUnknown_Release(this->outerUnknown);
1539 }
1540
1541 /************************************************************************
1542  * DataCache_Draw (IViewObject2)
1543  *
1544  * This method will draw the cached representation of the object
1545  * to the given device context.
1546  *
1547  * See Windows documentation for more details on IViewObject2 methods.
1548  */
1549 static HRESULT WINAPI DataCache_Draw(
1550             IViewObject2*    iface,
1551             DWORD            dwDrawAspect,
1552             LONG             lindex,
1553             void*            pvAspect,
1554             DVTARGETDEVICE*  ptd,
1555             HDC              hdcTargetDev,
1556             HDC              hdcDraw,
1557             LPCRECTL         lprcBounds,
1558             LPCRECTL         lprcWBounds,
1559             BOOL  (CALLBACK *pfnContinue)(ULONG_PTR dwContinue),
1560             ULONG_PTR        dwContinue)
1561 {
1562   PresentationDataHeader presData;
1563   HMETAFILE              presMetafile = 0;
1564   HRESULT                hres;
1565
1566   _ICOM_THIS_From_IViewObject2(DataCache, iface);
1567
1568   TRACE("(%p, %lx, %ld, %p, %p, %p, %p, %p, %p, %lx)\n",
1569         iface,
1570         dwDrawAspect,
1571         lindex,
1572         pvAspect,
1573         hdcTargetDev,
1574         hdcDraw,
1575         lprcBounds,
1576         lprcWBounds,
1577         pfnContinue,
1578         dwContinue);
1579
1580   /*
1581    * Sanity check
1582    */
1583   if (lprcBounds==NULL)
1584     return E_INVALIDARG;
1585
1586   /*
1587    * First, we need to retrieve the dimensions of the
1588    * image in the metafile.
1589    */
1590   hres = DataCache_ReadPresentationData(this,
1591                                         dwDrawAspect,
1592                                         &presData);
1593
1594   if (FAILED(hres))
1595     return hres;
1596
1597   /*
1598    * Then, we can extract the metafile itself from the cached
1599    * data.
1600    *
1601    * FIXME Unless it isn't a metafile. I think it could be any CF_XXX type,
1602    * particularly CF_DIB.
1603    */
1604   presMetafile = DataCache_ReadPresMetafile(this,
1605                                             dwDrawAspect);
1606
1607   /*
1608    * If we have a metafile, just draw baby...
1609    * We have to be careful not to modify the state of the
1610    * DC.
1611    */
1612   if (presMetafile!=0)
1613   {
1614     INT   prevMapMode = SetMapMode(hdcDraw, MM_ANISOTROPIC);
1615     SIZE  oldWindowExt;
1616     SIZE  oldViewportExt;
1617     POINT oldViewportOrg;
1618
1619     SetWindowExtEx(hdcDraw,
1620                    presData.dwObjectExtentX,
1621                    presData.dwObjectExtentY,
1622                    &oldWindowExt);
1623
1624     SetViewportExtEx(hdcDraw,
1625                      lprcBounds->right - lprcBounds->left,
1626                      lprcBounds->bottom - lprcBounds->top,
1627                      &oldViewportExt);
1628
1629     SetViewportOrgEx(hdcDraw,
1630                      lprcBounds->left,
1631                      lprcBounds->top,
1632                      &oldViewportOrg);
1633
1634     PlayMetaFile(hdcDraw, presMetafile);
1635
1636     SetWindowExtEx(hdcDraw,
1637                    oldWindowExt.cx,
1638                    oldWindowExt.cy,
1639                    NULL);
1640
1641     SetViewportExtEx(hdcDraw,
1642                      oldViewportExt.cx,
1643                      oldViewportExt.cy,
1644                      NULL);
1645
1646     SetViewportOrgEx(hdcDraw,
1647                      oldViewportOrg.x,
1648                      oldViewportOrg.y,
1649                      NULL);
1650
1651     SetMapMode(hdcDraw, prevMapMode);
1652
1653     DeleteMetaFile(presMetafile);
1654   }
1655
1656   return S_OK;
1657 }
1658
1659 static HRESULT WINAPI DataCache_GetColorSet(
1660             IViewObject2*   iface,
1661             DWORD           dwDrawAspect,
1662             LONG            lindex,
1663             void*           pvAspect,
1664             DVTARGETDEVICE* ptd,
1665             HDC             hicTargetDevice,
1666             LOGPALETTE**    ppColorSet)
1667 {
1668   FIXME("stub\n");
1669   return E_NOTIMPL;
1670 }
1671
1672 static HRESULT WINAPI DataCache_Freeze(
1673             IViewObject2*   iface,
1674             DWORD           dwDrawAspect,
1675             LONG            lindex,
1676             void*           pvAspect,
1677             DWORD*          pdwFreeze)
1678 {
1679   FIXME("stub\n");
1680   return E_NOTIMPL;
1681 }
1682
1683 static HRESULT WINAPI DataCache_Unfreeze(
1684             IViewObject2*   iface,
1685             DWORD           dwFreeze)
1686 {
1687   FIXME("stub\n");
1688   return E_NOTIMPL;
1689 }
1690
1691 /************************************************************************
1692  * DataCache_SetAdvise (IViewObject2)
1693  *
1694  * This sets-up an advisory sink with the data cache. When the object's
1695  * view changes, this sink is called.
1696  *
1697  * See Windows documentation for more details on IViewObject2 methods.
1698  */
1699 static HRESULT WINAPI DataCache_SetAdvise(
1700             IViewObject2*   iface,
1701             DWORD           aspects,
1702             DWORD           advf,
1703             IAdviseSink*    pAdvSink)
1704 {
1705   _ICOM_THIS_From_IViewObject2(DataCache, iface);
1706
1707   TRACE("(%p, %lx, %lx, %p)\n", iface, aspects, advf, pAdvSink);
1708
1709   /*
1710    * A call to this function removes the previous sink
1711    */
1712   if (this->sinkInterface != NULL)
1713   {
1714     IAdviseSink_Release(this->sinkInterface);
1715     this->sinkInterface  = NULL;
1716     this->sinkAspects    = 0;
1717     this->sinkAdviseFlag = 0;
1718   }
1719
1720   /*
1721    * Now, setup the new one.
1722    */
1723   if (pAdvSink!=NULL)
1724   {
1725     this->sinkInterface  = pAdvSink;
1726     this->sinkAspects    = aspects;
1727     this->sinkAdviseFlag = advf;
1728
1729     IAdviseSink_AddRef(this->sinkInterface);
1730   }
1731
1732   /*
1733    * When the ADVF_PRIMEFIRST flag is set, we have to advise the
1734    * sink immediately.
1735    */
1736   if (advf & ADVF_PRIMEFIRST)
1737   {
1738     DataCache_FireOnViewChange(this,
1739                                DVASPECT_CONTENT,
1740                                -1);
1741   }
1742
1743   return S_OK;
1744 }
1745
1746 /************************************************************************
1747  * DataCache_GetAdvise (IViewObject2)
1748  *
1749  * This method queries the current state of the advise sink
1750  * installed on the data cache.
1751  *
1752  * See Windows documentation for more details on IViewObject2 methods.
1753  */
1754 static HRESULT WINAPI DataCache_GetAdvise(
1755             IViewObject2*   iface,
1756             DWORD*          pAspects,
1757             DWORD*          pAdvf,
1758             IAdviseSink**   ppAdvSink)
1759 {
1760   _ICOM_THIS_From_IViewObject2(DataCache, iface);
1761
1762   TRACE("(%p, %p, %p, %p)\n", iface, pAspects, pAdvf, ppAdvSink);
1763
1764   /*
1765    * Just copy all the requested values.
1766    */
1767   if (pAspects!=NULL)
1768     *pAspects = this->sinkAspects;
1769
1770   if (pAdvf!=NULL)
1771     *pAdvf = this->sinkAdviseFlag;
1772
1773   if (ppAdvSink!=NULL)
1774   {
1775     IAdviseSink_QueryInterface(this->sinkInterface,
1776                                &IID_IAdviseSink,
1777                                (void**)ppAdvSink);
1778   }
1779
1780   return S_OK;
1781 }
1782
1783 /************************************************************************
1784  * DataCache_GetExtent (IViewObject2)
1785  *
1786  * This method retrieves the "natural" size of this cached object.
1787  *
1788  * See Windows documentation for more details on IViewObject2 methods.
1789  */
1790 static HRESULT WINAPI DataCache_GetExtent(
1791             IViewObject2*   iface,
1792             DWORD           dwDrawAspect,
1793             LONG            lindex,
1794             DVTARGETDEVICE* ptd,
1795             LPSIZEL         lpsizel)
1796 {
1797   PresentationDataHeader presData;
1798   HRESULT                hres = E_FAIL;
1799
1800   _ICOM_THIS_From_IViewObject2(DataCache, iface);
1801
1802   TRACE("(%p, %lx, %ld, %p, %p)\n",
1803         iface, dwDrawAspect, lindex, ptd, lpsizel);
1804
1805   /*
1806    * Sanity check
1807    */
1808   if (lpsizel==NULL)
1809     return E_POINTER;
1810
1811   /*
1812    * Initialize the out parameter.
1813    */
1814   lpsizel->cx = 0;
1815   lpsizel->cy = 0;
1816
1817   /*
1818    * This flag should be set to -1.
1819    */
1820   if (lindex!=-1)
1821     FIXME("Unimplemented flag lindex = %ld\n", lindex);
1822
1823   /*
1824    * Right now, we support only the callback from
1825    * the default handler.
1826    */
1827   if (ptd!=NULL)
1828     FIXME("Unimplemented ptd = %p\n", ptd);
1829
1830   /*
1831    * Get the presentation information from the
1832    * cache.
1833    */
1834   hres = DataCache_ReadPresentationData(this,
1835                                         dwDrawAspect,
1836                                         &presData);
1837
1838   if (SUCCEEDED(hres))
1839   {
1840     lpsizel->cx = presData.dwObjectExtentX;
1841     lpsizel->cy = presData.dwObjectExtentY;
1842   }
1843
1844   /*
1845    * This method returns OLE_E_BLANK when it fails.
1846    */
1847   if (FAILED(hres))
1848     hres = OLE_E_BLANK;
1849
1850   return hres;
1851 }
1852
1853
1854 /*********************************************************
1855  * Method implementation for the IOleCache2
1856  * part of the DataCache class.
1857  */
1858
1859 /************************************************************************
1860  * DataCache_IOleCache2_QueryInterface (IUnknown)
1861  *
1862  * See Windows documentation for more details on IUnknown methods.
1863  */
1864 static HRESULT WINAPI DataCache_IOleCache2_QueryInterface(
1865             IOleCache2*     iface,
1866             REFIID          riid,
1867             void**          ppvObject)
1868 {
1869   _ICOM_THIS_From_IOleCache2(DataCache, iface);
1870
1871   return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1872 }
1873
1874 /************************************************************************
1875  * DataCache_IOleCache2_AddRef (IUnknown)
1876  *
1877  * See Windows documentation for more details on IUnknown methods.
1878  */
1879 static ULONG WINAPI DataCache_IOleCache2_AddRef(
1880             IOleCache2*     iface)
1881 {
1882   _ICOM_THIS_From_IOleCache2(DataCache, iface);
1883
1884   return IUnknown_AddRef(this->outerUnknown);
1885 }
1886
1887 /************************************************************************
1888  * DataCache_IOleCache2_Release (IUnknown)
1889  *
1890  * See Windows documentation for more details on IUnknown methods.
1891  */
1892 static ULONG WINAPI DataCache_IOleCache2_Release(
1893             IOleCache2*     iface)
1894 {
1895   _ICOM_THIS_From_IOleCache2(DataCache, iface);
1896
1897   return IUnknown_Release(this->outerUnknown);
1898 }
1899
1900 static HRESULT WINAPI DataCache_Cache(
1901             IOleCache2*     iface,
1902             FORMATETC*      pformatetc,
1903             DWORD           advf,
1904             DWORD*          pdwConnection)
1905 {
1906   FIXME("stub\n");
1907   return E_NOTIMPL;
1908 }
1909
1910 static HRESULT WINAPI DataCache_Uncache(
1911             IOleCache2*     iface,
1912             DWORD           dwConnection)
1913 {
1914   FIXME("stub\n");
1915   return E_NOTIMPL;
1916 }
1917
1918 static HRESULT WINAPI DataCache_EnumCache(
1919             IOleCache2*     iface,
1920             IEnumSTATDATA** ppenumSTATDATA)
1921 {
1922   FIXME("stub\n");
1923   return E_NOTIMPL;
1924 }
1925
1926 static HRESULT WINAPI DataCache_InitCache(
1927             IOleCache2*     iface,
1928             IDataObject*    pDataObject)
1929 {
1930   FIXME("stub\n");
1931   return E_NOTIMPL;
1932 }
1933
1934 static HRESULT WINAPI DataCache_IOleCache2_SetData(
1935             IOleCache2*     iface,
1936             FORMATETC*      pformatetc,
1937             STGMEDIUM*      pmedium,
1938             BOOL            fRelease)
1939 {
1940   FIXME("stub\n");
1941   return E_NOTIMPL;
1942 }
1943
1944 static HRESULT WINAPI DataCache_UpdateCache(
1945             IOleCache2*     iface,
1946             LPDATAOBJECT    pDataObject,
1947             DWORD           grfUpdf,
1948             LPVOID          pReserved)
1949 {
1950   FIXME("stub\n");
1951   return E_NOTIMPL;
1952 }
1953
1954 static HRESULT WINAPI DataCache_DiscardCache(
1955             IOleCache2*     iface,
1956             DWORD           dwDiscardOptions)
1957 {
1958   FIXME("stub\n");
1959   return E_NOTIMPL;
1960 }
1961
1962
1963 /*********************************************************
1964  * Method implementation for the IOleCacheControl
1965  * part of the DataCache class.
1966  */
1967
1968 /************************************************************************
1969  * DataCache_IOleCacheControl_QueryInterface (IUnknown)
1970  *
1971  * See Windows documentation for more details on IUnknown methods.
1972  */
1973 static HRESULT WINAPI DataCache_IOleCacheControl_QueryInterface(
1974             IOleCacheControl* iface,
1975             REFIID            riid,
1976             void**            ppvObject)
1977 {
1978   _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
1979
1980   return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1981 }
1982
1983 /************************************************************************
1984  * DataCache_IOleCacheControl_AddRef (IUnknown)
1985  *
1986  * See Windows documentation for more details on IUnknown methods.
1987  */
1988 static ULONG WINAPI DataCache_IOleCacheControl_AddRef(
1989             IOleCacheControl* iface)
1990 {
1991   _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
1992
1993   return IUnknown_AddRef(this->outerUnknown);
1994 }
1995
1996 /************************************************************************
1997  * DataCache_IOleCacheControl_Release (IUnknown)
1998  *
1999  * See Windows documentation for more details on IUnknown methods.
2000  */
2001 static ULONG WINAPI DataCache_IOleCacheControl_Release(
2002             IOleCacheControl* iface)
2003 {
2004   _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
2005
2006   return IUnknown_Release(this->outerUnknown);
2007 }
2008
2009 static HRESULT WINAPI DataCache_OnRun(
2010             IOleCacheControl* iface,
2011             LPDATAOBJECT      pDataObject)
2012 {
2013   FIXME("stub\n");
2014   return E_NOTIMPL;
2015 }
2016
2017 static HRESULT WINAPI DataCache_OnStop(
2018             IOleCacheControl* iface)
2019 {
2020   FIXME("stub\n");
2021   return E_NOTIMPL;
2022 }