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