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