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