Cleaned up debug channels a bit.
[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
606   hres = IStorage_OpenStream(
607            this->presentationStorage,
608            streamName,
609            NULL,
610            STGM_READ | STGM_SHARE_EXCLUSIVE,
611            0,
612            &presStream);
613
614   if (FAILED(hres))
615     return hres;
616
617   hres = IStream_Read(
618            presStream,
619            header,
620            sizeof(PresentationDataHeader),
621            NULL);
622
623   /*
624    * Cleanup.
625    */
626   IStream_Release(presStream);
627
628   /*
629    * We don't want to propagate any other error
630    * code than a failure.
631    */
632   if (hres!=S_OK)
633     hres = E_FAIL;
634
635   return hres;
636 }
637
638 /************************************************************************
639  * DataCache_FireOnViewChange
640  *
641  * This method will fire an OnViewChange notification to the advise
642  * sink registered with the datacache.
643  *
644  * See IAdviseSink::OnViewChange for more details.
645  */
646 static void DataCache_FireOnViewChange(
647   DataCache* this,
648   DWORD      aspect,
649   LONG       lindex)
650 {
651   TRACE("(%p, %lx, %ld)\n", this, aspect, lindex);
652
653   /*
654    * The sink supplies a filter when it registers
655    * we make sure we only send the notifications when that
656    * filter matches.
657    */
658   if ((this->sinkAspects & aspect) != 0)
659   {
660     if (this->sinkInterface != NULL)
661     {
662       IAdviseSink_OnViewChange(this->sinkInterface,
663                                aspect,
664                                lindex);
665
666       /*
667        * Some sinks want to be unregistered automatically when
668        * the first notification goes out.
669        */
670       if ( (this->sinkAdviseFlag & ADVF_ONLYONCE) != 0)
671       {
672         IAdviseSink_Release(this->sinkInterface);
673
674         this->sinkInterface  = NULL;
675         this->sinkAspects    = 0;
676         this->sinkAdviseFlag = 0;
677       }
678     }
679   }
680 }
681
682 /************************************************************************
683  * DataCache_ReadPresentationData
684  *
685  * This method will read information for the requested presentation 
686  * into the given structure.
687  *
688  * Param:
689  *   this       - Pointer to the DataCache object
690  *   drawAspect - The aspect of the object that we wish to draw.
691  *   header     - The structure containing information about this
692  *                aspect of the object.
693  *
694  * NOTE:
695  *   This method only supports the DVASPECT_CONTENT aspect.
696  */
697 static HRESULT DataCache_FindPresStreamName(
698   DataCache* this,
699   DWORD      drawAspect,
700   OLECHAR*   buffer)
701 {
702   OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
703
704   if (drawAspect!=DVASPECT_CONTENT)
705     return E_FAIL;
706
707   memcpy(buffer, name, sizeof(name));
708
709   return S_OK;
710 }
711
712 /************************************************************************
713  * DataCache_ReadPresentationData
714  *
715  * This method will read information for the requested presentation 
716  * into the given structure.
717  *
718  * Param:
719  *   this       - Pointer to the DataCache object
720  *   drawAspect - The aspect of the object that we wish to draw.
721  *
722  * Returns:
723  *   This method returns a metafile handle if it is successful.
724  *   it will return 0 if not.
725  */
726 static HMETAFILE DataCache_ReadPresMetafile(
727   DataCache* this,
728   DWORD      drawAspect)
729 {
730   LARGE_INTEGER offset;
731   IStream*      presStream = NULL;
732   OLECHAR       streamName[20];
733   HRESULT       hres;
734   void*         metafileBits;
735   STATSTG       streamInfo;
736   HMETAFILE     newMetafile = 0;
737
738   /*
739    * Get the name for the presentation stream.
740    */
741   hres = DataCache_FindPresStreamName(
742            this, 
743            drawAspect,
744            streamName);
745
746   if (FAILED(hres))
747     return hres;
748
749   /*
750    * Open the stream and read the header.
751    */
752   hres = IStorage_OpenStream(
753            this->presentationStorage,
754            streamName,
755            NULL,
756            STGM_READ | STGM_SHARE_EXCLUSIVE,
757            0,
758            &presStream);
759
760   if (FAILED(hres))
761     return hres;
762
763   /*
764    * Get the size of the stream.
765    */
766   hres = IStream_Stat(presStream,
767                       &streamInfo,
768                       STATFLAG_NONAME);
769
770   /*
771    * Skip the header
772    */
773   offset.s.HighPart = 0;
774   offset.s.LowPart  = sizeof(PresentationDataHeader);
775
776   hres = IStream_Seek(
777            presStream,
778            offset,
779            STREAM_SEEK_SET,
780            NULL);
781
782   /*
783    * Allocate a buffer for the metafile bits.
784    */
785   metafileBits = HeapAlloc(GetProcessHeap(), 
786                            0, 
787                            streamInfo.cbSize.s.LowPart);
788
789   /*
790    * Read the metafile bits.
791    */
792   hres = IStream_Read(
793            presStream,
794            metafileBits,
795            streamInfo.cbSize.s.LowPart,
796            NULL);
797
798   /*
799    * Create a metafile with those bits.
800    */
801   if (SUCCEEDED(hres))
802   {
803     newMetafile = SetMetaFileBitsEx(streamInfo.cbSize.s.LowPart, metafileBits);
804   }
805
806   /*
807    * Cleanup.
808    */
809   HeapFree(GetProcessHeap(), 0, metafileBits);
810   IStream_Release(presStream);
811
812   if (newMetafile==0)
813     hres = E_FAIL;
814
815   return newMetafile;
816 }
817
818 /*********************************************************
819  * Method implementation for the  non delegating IUnknown
820  * part of the DataCache class.
821  */
822
823 /************************************************************************
824  * DataCache_NDIUnknown_QueryInterface (IUnknown)
825  *
826  * See Windows documentation for more details on IUnknown methods.
827  *
828  * This version of QueryInterface will not delegate it's implementation
829  * to the outer unknown.
830  */
831 static HRESULT WINAPI DataCache_NDIUnknown_QueryInterface(
832             IUnknown*      iface,
833             REFIID         riid,
834             void**         ppvObject)
835 {
836   _ICOM_THIS_From_NDIUnknown(DataCache, iface);
837
838   /*
839    * Perform a sanity check on the parameters.
840    */
841   if ( (this==0) || (ppvObject==0) )
842     return E_INVALIDARG;
843   
844   /*
845    * Initialize the return parameter.
846    */
847   *ppvObject = 0;
848
849   /*
850    * Compare the riid with the interface IDs implemented by this object.
851    */
852   if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0) 
853   {
854     *ppvObject = iface;
855   }
856   else if (memcmp(&IID_IDataObject, riid, sizeof(IID_IDataObject)) == 0) 
857   {
858     *ppvObject = (IDataObject*)&(this->lpvtbl1);
859   }
860   else if ( (memcmp(&IID_IPersistStorage, riid, sizeof(IID_IPersistStorage)) == 0)  ||
861             (memcmp(&IID_IPersist, riid, sizeof(IID_IPersist)) == 0) )
862   {
863     *ppvObject = (IPersistStorage*)&(this->lpvtbl3);
864   }
865   else if ( (memcmp(&IID_IViewObject, riid, sizeof(IID_IViewObject)) == 0) ||
866             (memcmp(&IID_IViewObject2, riid, sizeof(IID_IViewObject2)) == 0) )
867   {
868     *ppvObject = (IViewObject2*)&(this->lpvtbl4);
869   }
870   else if ( (memcmp(&IID_IOleCache, riid, sizeof(IID_IOleCache)) == 0) ||
871             (memcmp(&IID_IOleCache2, riid, sizeof(IID_IOleCache2)) == 0) )
872   {
873     *ppvObject = (IOleCache2*)&(this->lpvtbl5);
874   }
875   else if (memcmp(&IID_IOleCacheControl, riid, sizeof(IID_IOleCacheControl)) == 0) 
876   {
877     *ppvObject = (IOleCacheControl*)&(this->lpvtbl6);
878   }
879
880   /*
881    * Check that we obtained an interface.
882    */
883   if ((*ppvObject)==0)
884   {
885     WARN( "() : asking for un supported interface %s\n", debugstr_guid(riid));
886     return E_NOINTERFACE;
887   }
888   
889   /*
890    * Query Interface always increases the reference count by one when it is
891    * successful. 
892    */
893   IUnknown_AddRef((IUnknown*)*ppvObject);
894
895   return S_OK;;  
896 }
897
898 /************************************************************************
899  * DataCache_NDIUnknown_AddRef (IUnknown)
900  *
901  * See Windows documentation for more details on IUnknown methods.
902  *
903  * This version of QueryInterface will not delegate it's implementation
904  * to the outer unknown.
905  */
906 static ULONG WINAPI DataCache_NDIUnknown_AddRef( 
907             IUnknown*      iface)
908 {
909   _ICOM_THIS_From_NDIUnknown(DataCache, iface);
910
911   this->ref++;
912
913   return this->ref;
914 }
915
916 /************************************************************************
917  * DataCache_NDIUnknown_Release (IUnknown)
918  *
919  * See Windows documentation for more details on IUnknown methods.
920  *
921  * This version of QueryInterface will not delegate it's implementation
922  * to the outer unknown.
923  */
924 static ULONG WINAPI DataCache_NDIUnknown_Release( 
925             IUnknown*      iface)
926 {
927   _ICOM_THIS_From_NDIUnknown(DataCache, iface);
928
929   /*
930    * Decrease the reference count on this object.
931    */
932   this->ref--;
933
934   /*
935    * If the reference count goes down to 0, perform suicide.
936    */
937   if (this->ref==0)
938   {
939     DataCache_Destroy(this);
940
941     return 0;
942   }
943   
944   return this->ref;
945 }
946
947 /*********************************************************
948  * Method implementation for the IDataObject
949  * part of the DataCache class.
950  */
951
952 /************************************************************************
953  * DataCache_IDataObject_QueryInterface (IUnknown)
954  *
955  * See Windows documentation for more details on IUnknown methods.
956  */
957 static HRESULT WINAPI DataCache_IDataObject_QueryInterface(
958             IDataObject*     iface,
959             REFIID           riid,
960             void**           ppvObject)
961 {
962   _ICOM_THIS_From_IDataObject(DataCache, iface);
963
964   return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);  
965 }
966
967 /************************************************************************
968  * DataCache_IDataObject_AddRef (IUnknown)
969  *
970  * See Windows documentation for more details on IUnknown methods.
971  */
972 static ULONG WINAPI DataCache_IDataObject_AddRef( 
973             IDataObject*     iface)
974 {
975   _ICOM_THIS_From_IDataObject(DataCache, iface);
976
977   return IUnknown_AddRef(this->outerUnknown);  
978 }
979
980 /************************************************************************
981  * DataCache_IDataObject_Release (IUnknown)
982  *
983  * See Windows documentation for more details on IUnknown methods.
984  */
985 static ULONG WINAPI DataCache_IDataObject_Release( 
986             IDataObject*     iface)
987 {
988   _ICOM_THIS_From_IDataObject(DataCache, iface);
989
990   return IUnknown_Release(this->outerUnknown);  
991 }
992
993 static HRESULT WINAPI DataCache_GetData(
994             IDataObject*     iface,
995             LPFORMATETC      pformatetcIn, 
996             STGMEDIUM*       pmedium)
997 {
998   FIXME("stub\n");
999   return E_NOTIMPL;
1000 }
1001
1002 static HRESULT WINAPI DataCache_GetDataHere(
1003             IDataObject*     iface, 
1004             LPFORMATETC      pformatetc,
1005             STGMEDIUM*       pmedium)
1006 {
1007   FIXME("stub\n");
1008   return E_NOTIMPL;
1009 }
1010
1011 static HRESULT WINAPI DataCache_QueryGetData(
1012             IDataObject*     iface,
1013             LPFORMATETC      pformatetc)
1014 {
1015   FIXME("stub\n");
1016   return E_NOTIMPL;
1017 }
1018
1019 /************************************************************************
1020  * DataCache_EnumFormatEtc (IDataObject)
1021  *
1022  * The data cache doesn't implement this method.
1023  *
1024  * See Windows documentation for more details on IDataObject methods.
1025  */
1026 static HRESULT WINAPI DataCache_GetCanonicalFormatEtc(
1027             IDataObject*     iface, 
1028             LPFORMATETC      pformatectIn, 
1029             LPFORMATETC      pformatetcOut)
1030 {
1031   TRACE("()\n");
1032   return E_NOTIMPL;
1033 }
1034
1035 /************************************************************************
1036  * DataCache_IDataObject_SetData (IDataObject)
1037  *
1038  * This method is delegated to the IOleCache2 implementation.
1039  *
1040  * See Windows documentation for more details on IDataObject methods.
1041  */
1042 static HRESULT WINAPI DataCache_IDataObject_SetData(
1043             IDataObject*     iface,
1044             LPFORMATETC      pformatetc, 
1045             STGMEDIUM*       pmedium, 
1046             BOOL             fRelease)
1047 {
1048   IOleCache2* oleCache = NULL;
1049   HRESULT     hres;
1050
1051   TRACE("(%p, %p, %p, %d)\n", iface, pformatetc, pmedium, fRelease);
1052
1053   hres = IDataObject_QueryInterface(iface, &IID_IOleCache2, (void**)&oleCache);
1054
1055   if (FAILED(hres))
1056     return E_UNEXPECTED;
1057
1058   hres = IOleCache2_SetData(oleCache, pformatetc, pmedium, fRelease);
1059
1060   IOleCache2_Release(oleCache);
1061
1062   return hres;;
1063 }
1064
1065 /************************************************************************
1066  * DataCache_EnumFormatEtc (IDataObject)
1067  *
1068  * The data cache doesn't implement this method.
1069  *
1070  * See Windows documentation for more details on IDataObject methods.
1071  */
1072 static HRESULT WINAPI DataCache_EnumFormatEtc(
1073             IDataObject*     iface,       
1074             DWORD            dwDirection,
1075             IEnumFORMATETC** ppenumFormatEtc)
1076 {
1077   TRACE("()\n");
1078   return E_NOTIMPL;
1079 }
1080
1081 /************************************************************************
1082  * DataCache_DAdvise (IDataObject)
1083  *
1084  * The data cache doesn't support connections.
1085  *
1086  * See Windows documentation for more details on IDataObject methods.
1087  */
1088 static HRESULT WINAPI DataCache_DAdvise(
1089             IDataObject*     iface, 
1090             FORMATETC*       pformatetc, 
1091             DWORD            advf, 
1092             IAdviseSink*     pAdvSink, 
1093             DWORD*           pdwConnection)
1094 {
1095   TRACE("()\n");
1096   return OLE_E_ADVISENOTSUPPORTED;
1097 }
1098
1099 /************************************************************************
1100  * DataCache_DUnadvise (IDataObject)
1101  *
1102  * The data cache doesn't support connections.
1103  *
1104  * See Windows documentation for more details on IDataObject methods.
1105  */
1106 static HRESULT WINAPI DataCache_DUnadvise(
1107             IDataObject*     iface,
1108             DWORD            dwConnection)
1109 {
1110   TRACE("()\n");
1111   return OLE_E_NOCONNECTION;
1112 }
1113
1114 /************************************************************************
1115  * DataCache_EnumDAdvise (IDataObject)
1116  *
1117  * The data cache doesn't support connections.
1118  *
1119  * See Windows documentation for more details on IDataObject methods.
1120  */
1121 static HRESULT WINAPI DataCache_EnumDAdvise(
1122             IDataObject*     iface,
1123             IEnumSTATDATA**  ppenumAdvise)
1124 {
1125   TRACE("()\n");
1126   return OLE_E_ADVISENOTSUPPORTED;
1127 }
1128
1129 /*********************************************************
1130  * Method implementation for the IDataObject
1131  * part of the DataCache class.
1132  */
1133
1134 /************************************************************************
1135  * DataCache_IPersistStorage_QueryInterface (IUnknown)
1136  *
1137  * See Windows documentation for more details on IUnknown methods.
1138  */
1139 static HRESULT WINAPI DataCache_IPersistStorage_QueryInterface(
1140             IPersistStorage* iface,
1141             REFIID           riid,
1142             void**           ppvObject)
1143 {
1144   _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1145
1146   return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);  
1147 }
1148
1149 /************************************************************************
1150  * DataCache_IPersistStorage_AddRef (IUnknown)
1151  *
1152  * See Windows documentation for more details on IUnknown methods.
1153  */
1154 static ULONG WINAPI DataCache_IPersistStorage_AddRef( 
1155             IPersistStorage* iface)
1156 {
1157   _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1158
1159   return IUnknown_AddRef(this->outerUnknown);  
1160 }
1161
1162 /************************************************************************
1163  * DataCache_IPersistStorage_Release (IUnknown)
1164  *
1165  * See Windows documentation for more details on IUnknown methods.
1166  */
1167 static ULONG WINAPI DataCache_IPersistStorage_Release( 
1168             IPersistStorage* iface)
1169 {
1170   _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1171
1172   return IUnknown_Release(this->outerUnknown);  
1173 }
1174
1175 /************************************************************************
1176  * DataCache_GetClassID (IPersistStorage)
1177  *
1178  * The data cache doesn't implement this method.
1179  *
1180  * See Windows documentation for more details on IPersistStorage methods.
1181  */
1182 static HRESULT WINAPI DataCache_GetClassID( 
1183             IPersistStorage* iface,
1184             CLSID*           pClassID)
1185 {
1186   TRACE("(%p, %p)\n", iface, pClassID);
1187   return E_NOTIMPL;
1188 }
1189
1190 /************************************************************************
1191  * DataCache_IsDirty (IPersistStorage)
1192  *
1193  * Until we actully connect to a running object and retrieve new 
1194  * information to it, we never get dirty.
1195  *
1196  * See Windows documentation for more details on IPersistStorage methods.
1197  */
1198 static HRESULT WINAPI DataCache_IsDirty( 
1199             IPersistStorage* iface)
1200 {
1201   TRACE("(%p)\n", iface);
1202
1203   return S_FALSE;
1204 }
1205
1206 /************************************************************************
1207  * DataCache_InitNew (IPersistStorage)
1208  *
1209  * The data cache implementation of IPersistStorage_InitNew simply stores
1210  * the storage pointer.
1211  *
1212  * See Windows documentation for more details on IPersistStorage methods.
1213  */
1214 static HRESULT WINAPI DataCache_InitNew( 
1215             IPersistStorage* iface, 
1216             IStorage*        pStg)
1217 {
1218   TRACE("(%p, %p)\n", iface, pStg);
1219
1220   return DataCache_Load(iface, pStg);
1221 }
1222
1223 /************************************************************************
1224  * DataCache_Load (IPersistStorage)
1225  *
1226  * The data cache implementation of IPersistStorage_Load doesn't 
1227  * actually load anything. Instead, it holds on to the storage pointer
1228  * and it will load the presentation information when the 
1229  * IDataObject_GetData or IViewObject2_Draw methods are called.
1230  *
1231  * See Windows documentation for more details on IPersistStorage methods.
1232  */
1233 static HRESULT WINAPI DataCache_Load( 
1234             IPersistStorage* iface,
1235             IStorage*        pStg)
1236 {
1237   _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1238
1239   TRACE("(%p, %p)\n", iface, pStg);
1240
1241   if (this->presentationStorage != NULL)
1242   {
1243     IStorage_Release(this->presentationStorage);
1244   }
1245
1246   this->presentationStorage = pStg;
1247
1248   if (this->presentationStorage != NULL)
1249   {
1250     IStorage_AddRef(this->presentationStorage);
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   if (pStgNew)
1302   {
1303   /*
1304    * First, make sure we get our hands off any storage we have.
1305    */
1306
1307   DataCache_HandsOffStorage(iface);
1308
1309   /*
1310    * Then, attach to the new storage.
1311    */
1312
1313   DataCache_Load(iface, pStgNew);
1314   }
1315
1316   return S_OK;
1317 }
1318
1319 /************************************************************************
1320  * DataCache_HandsOffStorage (IPersistStorage)
1321  *
1322  * This method is called to tell the cache to release the storage
1323  * pointer it's currentlu holding.
1324  *
1325  * See Windows documentation for more details on IPersistStorage methods.
1326  */
1327 static HRESULT WINAPI DataCache_HandsOffStorage(
1328             IPersistStorage* iface)
1329 {
1330   _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1331
1332   TRACE("(%p)\n", iface);
1333
1334   if (this->presentationStorage != NULL)
1335   {
1336     IStorage_Release(this->presentationStorage);
1337     this->presentationStorage = NULL;
1338   }
1339
1340   return S_OK;
1341 }
1342
1343 /*********************************************************
1344  * Method implementation for the IViewObject2
1345  * part of the DataCache class.
1346  */
1347
1348 /************************************************************************
1349  * DataCache_IViewObject2_QueryInterface (IUnknown)
1350  *
1351  * See Windows documentation for more details on IUnknown methods.
1352  */
1353 static HRESULT WINAPI DataCache_IViewObject2_QueryInterface(
1354             IViewObject2* iface,
1355             REFIID           riid,
1356             void**           ppvObject)
1357 {
1358   _ICOM_THIS_From_IViewObject2(DataCache, iface);
1359
1360   return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);  
1361 }
1362
1363 /************************************************************************
1364  * DataCache_IViewObject2_AddRef (IUnknown)
1365  *
1366  * See Windows documentation for more details on IUnknown methods.
1367  */
1368 static ULONG WINAPI DataCache_IViewObject2_AddRef( 
1369             IViewObject2* iface)
1370 {
1371   _ICOM_THIS_From_IViewObject2(DataCache, iface);
1372
1373   return IUnknown_AddRef(this->outerUnknown);  
1374 }
1375
1376 /************************************************************************
1377  * DataCache_IViewObject2_Release (IUnknown)
1378  *
1379  * See Windows documentation for more details on IUnknown methods.
1380  */
1381 static ULONG WINAPI DataCache_IViewObject2_Release( 
1382             IViewObject2* iface)
1383 {
1384   _ICOM_THIS_From_IViewObject2(DataCache, iface);
1385
1386   return IUnknown_Release(this->outerUnknown);  
1387 }
1388
1389 /************************************************************************
1390  * DataCache_Draw (IViewObject2)
1391  *
1392  * This method will draw the cached representation of the object
1393  * to the given device context.
1394  *
1395  * See Windows documentation for more details on IViewObject2 methods.
1396  */
1397 static HRESULT WINAPI DataCache_Draw(
1398             IViewObject2*    iface,
1399             DWORD            dwDrawAspect,
1400             LONG             lindex,
1401             void*            pvAspect,
1402             DVTARGETDEVICE*  ptd, 
1403             HDC              hdcTargetDev, 
1404             HDC              hdcDraw,
1405             LPCRECTL         lprcBounds,
1406             LPCRECTL         lprcWBounds,
1407             IVO_ContCallback pfnContinue,
1408             DWORD            dwContinue)
1409 {
1410   PresentationDataHeader presData;
1411   HMETAFILE              presMetafile = 0;
1412   HRESULT                hres;
1413
1414   _ICOM_THIS_From_IViewObject2(DataCache, iface);
1415
1416   TRACE("(%p, %lx, %ld, %p, %x, %x, %p, %p, %p, %lx)\n",
1417         iface,
1418         dwDrawAspect,
1419         lindex,
1420         pvAspect,
1421         hdcTargetDev, 
1422         hdcDraw,
1423         lprcBounds,
1424         lprcWBounds,
1425         pfnContinue,
1426         dwContinue);
1427
1428   /*
1429    * Sanity check
1430    */
1431   if (lprcBounds==NULL)
1432     return E_INVALIDARG;
1433
1434   /*
1435    * First, we need to retrieve the dimensions of the
1436    * image in the metafile.
1437    */
1438   hres = DataCache_ReadPresentationData(this,
1439                                         dwDrawAspect,
1440                                         &presData);
1441
1442   if (FAILED(hres))
1443     return hres;
1444
1445   /*
1446    * Then, we can extract the metafile itself from the cached
1447    * data.
1448    */
1449   presMetafile = DataCache_ReadPresMetafile(this,
1450                                             dwDrawAspect);
1451
1452   /*
1453    * If we have a metafile, just draw baby...
1454    * We have to be careful not to modify the state of the
1455    * DC.
1456    */
1457   if (presMetafile!=0)
1458   {
1459     INT   prevMapMode = SetMapMode(hdcDraw, MM_ANISOTROPIC);
1460     SIZE  oldWindowExt;
1461     SIZE  oldViewportExt;
1462     POINT oldViewportOrg;
1463
1464     SetWindowExtEx(hdcDraw,
1465                    presData.objectExtentX,
1466                    presData.objectExtentY,
1467                    &oldWindowExt);
1468
1469     SetViewportExtEx(hdcDraw, 
1470                      lprcBounds->right - lprcBounds->left,
1471                      lprcBounds->bottom - lprcBounds->top,
1472                      &oldViewportExt);
1473
1474     SetViewportOrgEx(hdcDraw,
1475                      lprcBounds->left,
1476                      lprcBounds->top,
1477                      &oldViewportOrg);
1478
1479     PlayMetaFile(hdcDraw, presMetafile);
1480
1481     SetWindowExtEx(hdcDraw,
1482                    oldWindowExt.cx,
1483                    oldWindowExt.cy,
1484                    NULL);
1485
1486     SetViewportExtEx(hdcDraw, 
1487                      oldViewportExt.cx,
1488                      oldViewportExt.cy,
1489                      NULL);
1490
1491     SetViewportOrgEx(hdcDraw,
1492                      oldViewportOrg.x,
1493                      oldViewportOrg.y,
1494                      NULL);
1495
1496     SetMapMode(hdcDraw, prevMapMode);
1497
1498     DeleteMetaFile(presMetafile);
1499   }
1500
1501   return S_OK;
1502 }
1503
1504 static HRESULT WINAPI DataCache_GetColorSet(
1505             IViewObject2*   iface, 
1506             DWORD           dwDrawAspect, 
1507             LONG            lindex, 
1508             void*           pvAspect, 
1509             DVTARGETDEVICE* ptd, 
1510             HDC             hicTargetDevice, 
1511             LOGPALETTE**    ppColorSet)
1512 {
1513   FIXME("stub\n");
1514   return E_NOTIMPL;
1515 }
1516
1517 static HRESULT WINAPI DataCache_Freeze(
1518             IViewObject2*   iface,
1519             DWORD           dwDrawAspect,
1520             LONG            lindex,
1521             void*           pvAspect, 
1522             DWORD*          pdwFreeze)
1523 {
1524   FIXME("stub\n");
1525   return E_NOTIMPL;
1526 }
1527
1528 static HRESULT WINAPI DataCache_Unfreeze(
1529             IViewObject2*   iface,
1530             DWORD           dwFreeze)
1531 {
1532   FIXME("stub\n");
1533   return E_NOTIMPL;
1534 }
1535
1536 /************************************************************************
1537  * DataCache_SetAdvise (IViewObject2)
1538  *
1539  * This sets-up an advisory sink with the data cache. When the object's
1540  * view changes, this sink is called.
1541  *
1542  * See Windows documentation for more details on IViewObject2 methods.
1543  */
1544 static HRESULT WINAPI DataCache_SetAdvise(
1545             IViewObject2*   iface,
1546             DWORD           aspects, 
1547             DWORD           advf, 
1548             IAdviseSink*    pAdvSink)
1549 {
1550   _ICOM_THIS_From_IViewObject2(DataCache, iface);
1551
1552   TRACE("(%p, %lx, %lx, %p)\n", iface, aspects, advf, pAdvSink);
1553
1554   /*
1555    * A call to this function removes the previous sink
1556    */
1557   if (this->sinkInterface != NULL)
1558   {
1559     IAdviseSink_Release(this->sinkInterface);
1560     this->sinkInterface  = NULL;
1561     this->sinkAspects    = 0; 
1562     this->sinkAdviseFlag = 0;
1563   }
1564
1565   /*
1566    * Now, setup the new one.
1567    */
1568   if (pAdvSink!=NULL)
1569   {
1570     this->sinkInterface  = pAdvSink;
1571     this->sinkAspects    = aspects; 
1572     this->sinkAdviseFlag = advf;    
1573
1574     IAdviseSink_AddRef(this->sinkInterface);
1575   }
1576
1577   /*
1578    * When the ADVF_PRIMEFIRST flag is set, we have to advise the
1579    * sink immediately.
1580    */
1581   if (advf & ADVF_PRIMEFIRST)
1582   {
1583     DataCache_FireOnViewChange(this,
1584                                DVASPECT_CONTENT,
1585                                -1);
1586   }
1587
1588   return S_OK;
1589 }
1590
1591 /************************************************************************
1592  * DataCache_GetAdvise (IViewObject2)
1593  *
1594  * This method queries the current state of the advise sink 
1595  * installed on the data cache.
1596  *
1597  * See Windows documentation for more details on IViewObject2 methods.
1598  */
1599 static HRESULT WINAPI DataCache_GetAdvise(
1600             IViewObject2*   iface, 
1601             DWORD*          pAspects, 
1602             DWORD*          pAdvf, 
1603             IAdviseSink**   ppAdvSink)
1604 {
1605   _ICOM_THIS_From_IViewObject2(DataCache, iface);
1606
1607   TRACE("(%p, %p, %p, %p)\n", iface, pAspects, pAdvf, ppAdvSink);
1608
1609   /*
1610    * Just copy all the requested values.
1611    */
1612   if (pAspects!=NULL)
1613     *pAspects = this->sinkAspects;
1614
1615   if (pAdvf!=NULL)
1616     *pAdvf = this->sinkAdviseFlag;
1617
1618   if (ppAdvSink!=NULL)
1619   {
1620     IAdviseSink_QueryInterface(this->sinkInterface, 
1621                                &IID_IAdviseSink, 
1622                                (void**)ppAdvSink);
1623   }
1624
1625   return S_OK;
1626 }
1627
1628 /************************************************************************
1629  * DataCache_GetExtent (IViewObject2)
1630  *
1631  * This method retrieves the "natural" size of this cached object.
1632  *
1633  * See Windows documentation for more details on IViewObject2 methods.
1634  */
1635 static HRESULT WINAPI DataCache_GetExtent(
1636             IViewObject2*   iface, 
1637             DWORD           dwDrawAspect, 
1638             LONG            lindex, 
1639             DVTARGETDEVICE* ptd, 
1640             LPSIZEL         lpsizel)
1641 {
1642   PresentationDataHeader presData;
1643   HRESULT                hres = E_FAIL;
1644
1645   _ICOM_THIS_From_IViewObject2(DataCache, iface);
1646
1647   TRACE("(%p, %lx, %ld, %p, %p)\n", 
1648         iface, dwDrawAspect, lindex, ptd, lpsizel);
1649
1650   /*
1651    * Sanity check
1652    */
1653   if (lpsizel==NULL)
1654     return E_POINTER;
1655
1656   /*
1657    * Initialize the out parameter.
1658    */
1659   lpsizel->cx = 0;
1660   lpsizel->cy = 0;
1661
1662   /*
1663    * This flag should be set to -1.
1664    */
1665   if (lindex!=-1)
1666     FIXME("Unimplemented flag lindex = %ld\n", lindex);
1667
1668   /*
1669    * Right now, we suport only the callback from
1670    * the default handler.
1671    */
1672   if (ptd!=NULL)
1673     FIXME("Unimplemented ptd = %p\n", ptd);
1674   
1675   /*
1676    * Get the presentation information from the 
1677    * cache.
1678    */
1679   hres = DataCache_ReadPresentationData(this,
1680                                         dwDrawAspect,
1681                                         &presData);
1682
1683   if (SUCCEEDED(hres))
1684   {
1685     lpsizel->cx = presData.objectExtentX;
1686     lpsizel->cy = presData.objectExtentY;
1687   }
1688
1689   /*
1690    * This method returns OLE_E_BLANK when it fails.
1691    */
1692   if (FAILED(hres))
1693     hres = OLE_E_BLANK;
1694
1695   return hres;
1696 }
1697
1698
1699 /*********************************************************
1700  * Method implementation for the IOleCache2
1701  * part of the DataCache class.
1702  */
1703
1704 /************************************************************************
1705  * DataCache_IOleCache2_QueryInterface (IUnknown)
1706  *
1707  * See Windows documentation for more details on IUnknown methods.
1708  */
1709 static HRESULT WINAPI DataCache_IOleCache2_QueryInterface(
1710             IOleCache2*     iface,
1711             REFIID          riid,
1712             void**          ppvObject)
1713 {
1714   _ICOM_THIS_From_IOleCache2(DataCache, iface);
1715
1716   return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);  
1717 }
1718
1719 /************************************************************************
1720  * DataCache_IOleCache2_AddRef (IUnknown)
1721  *
1722  * See Windows documentation for more details on IUnknown methods.
1723  */
1724 static ULONG WINAPI DataCache_IOleCache2_AddRef( 
1725             IOleCache2*     iface)
1726 {
1727   _ICOM_THIS_From_IOleCache2(DataCache, iface);
1728
1729   return IUnknown_AddRef(this->outerUnknown);  
1730 }
1731
1732 /************************************************************************
1733  * DataCache_IOleCache2_Release (IUnknown)
1734  *
1735  * See Windows documentation for more details on IUnknown methods.
1736  */
1737 static ULONG WINAPI DataCache_IOleCache2_Release( 
1738             IOleCache2*     iface)
1739 {
1740   _ICOM_THIS_From_IOleCache2(DataCache, iface);
1741
1742   return IUnknown_Release(this->outerUnknown);  
1743 }
1744
1745 static HRESULT WINAPI DataCache_Cache(
1746             IOleCache2*     iface,
1747             FORMATETC*      pformatetc,
1748             DWORD           advf,
1749             DWORD*          pdwConnection)
1750 {
1751   FIXME("stub\n");
1752   return E_NOTIMPL;
1753 }
1754
1755 static HRESULT WINAPI DataCache_Uncache(
1756             IOleCache2*     iface,
1757             DWORD           dwConnection)
1758 {
1759   FIXME("stub\n");
1760   return E_NOTIMPL;
1761 }
1762
1763 static HRESULT WINAPI DataCache_EnumCache(
1764             IOleCache2*     iface,
1765             IEnumSTATDATA** ppenumSTATDATA)
1766 {
1767   FIXME("stub\n");
1768   return E_NOTIMPL;
1769 }
1770
1771 static HRESULT WINAPI DataCache_InitCache(
1772             IOleCache2*     iface,
1773             IDataObject*    pDataObject)
1774 {
1775   FIXME("stub\n");
1776   return E_NOTIMPL;
1777 }
1778
1779 static HRESULT WINAPI DataCache_IOleCache2_SetData(
1780             IOleCache2*     iface,
1781             FORMATETC*      pformatetc,
1782             STGMEDIUM*      pmedium,
1783             BOOL            fRelease)
1784 {
1785   FIXME("stub\n");
1786   return E_NOTIMPL;
1787 }
1788
1789 static HRESULT WINAPI DataCache_UpdateCache(
1790             IOleCache2*     iface,
1791             LPDATAOBJECT    pDataObject, 
1792             DWORD           grfUpdf,
1793             LPVOID          pReserved)
1794 {
1795   FIXME("stub\n");
1796   return E_NOTIMPL;
1797 }
1798
1799 static HRESULT WINAPI DataCache_DiscardCache(
1800             IOleCache2*     iface,
1801             DWORD           dwDiscardOptions)
1802 {
1803   FIXME("stub\n");
1804   return E_NOTIMPL;
1805 }
1806
1807
1808 /*********************************************************
1809  * Method implementation for the IOleCacheControl
1810  * part of the DataCache class.
1811  */
1812
1813 /************************************************************************
1814  * DataCache_IOleCacheControl_QueryInterface (IUnknown)
1815  *
1816  * See Windows documentation for more details on IUnknown methods.
1817  */
1818 static HRESULT WINAPI DataCache_IOleCacheControl_QueryInterface(
1819             IOleCacheControl* iface,
1820             REFIID            riid,
1821             void**            ppvObject)
1822 {
1823   _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
1824
1825   return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);  
1826 }
1827
1828 /************************************************************************
1829  * DataCache_IOleCacheControl_AddRef (IUnknown)
1830  *
1831  * See Windows documentation for more details on IUnknown methods.
1832  */
1833 static ULONG WINAPI DataCache_IOleCacheControl_AddRef( 
1834             IOleCacheControl* iface)
1835 {
1836   _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
1837
1838   return IUnknown_AddRef(this->outerUnknown);  
1839 }
1840
1841 /************************************************************************
1842  * DataCache_IOleCacheControl_Release (IUnknown)
1843  *
1844  * See Windows documentation for more details on IUnknown methods.
1845  */
1846 static ULONG WINAPI DataCache_IOleCacheControl_Release( 
1847             IOleCacheControl* iface)
1848 {
1849   _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
1850
1851   return IUnknown_Release(this->outerUnknown);  
1852 }
1853
1854 static HRESULT WINAPI DataCache_OnRun(
1855             IOleCacheControl* iface,
1856             LPDATAOBJECT      pDataObject)
1857 {
1858   FIXME("stub\n");
1859   return E_NOTIMPL;
1860 }
1861
1862 static HRESULT WINAPI DataCache_OnStop(
1863             IOleCacheControl* iface)
1864 {
1865   FIXME("stub\n");
1866   return E_NOTIMPL;
1867 }
1868
1869