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