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