4 * Copyright 1999 Francis Beaudet
7 * The OLE2 data cache supports a whole whack of
8 * interfaces including:
9 * IDataObject, IPersistStorage, IViewObject2,
10 * IOleCache2 and IOleCacheControl.
12 * Most of the implementation details are taken from: Inside OLE
13 * second edition by Kraig Brockschmidt,
16 * - This implementation of the datacache will let your application
17 * load documents that have embedded OLE objects in them and it will
18 * also retrieve the metafile representation of those objects.
19 * - This implementation of the datacache will also allow your
20 * application to save new documents with OLE objects in them.
21 * - The main thing that it doesn't do is allow you to activate
22 * or modify the OLE objects in any way.
23 * - I haven't found any good documentation on the real usage of
24 * the streams created by the data cache. In particular, How to
25 * determine what the XXX stands for in the stream name
26 * "\002OlePresXXX". I have an intuition that this is related to
27 * the cached aspect of the object but I'm not sure it could
29 * - Also, I don't know the real content of the presentation stream
30 * header. I was able to figure-out where the extent of the object
31 * was stored but that's about it.
37 #include "wine/obj_oleview.h"
38 #include "wine/obj_cache.h"
39 #include "debugtools.h"
41 DEFAULT_DEBUG_CHANNEL(ole)
43 /****************************************************************************
44 * PresentationDataHeader
46 * This structure represents the header of the \002OlePresXXX stream in
47 * the OLE object strorage.
49 * Most fields are still unknown.
51 typedef struct PresentationDataHeader
64 } PresentationDataHeader;
66 /****************************************************************************
72 * List all interface VTables here
74 ICOM_VTABLE(IDataObject)* lpvtbl1;
75 ICOM_VTABLE(IUnknown)* lpvtbl2;
76 ICOM_VTABLE(IPersistStorage)* lpvtbl3;
77 ICOM_VTABLE(IViewObject2)* lpvtbl4;
78 ICOM_VTABLE(IOleCache2)* lpvtbl5;
79 ICOM_VTABLE(IOleCacheControl)* lpvtbl6;
82 * Reference count of this object
87 * IUnknown implementation of the outer object.
89 IUnknown* outerUnknown;
92 * This storage pointer is set through a call to
93 * IPersistStorage_Load. This is where the visual
94 * representation of the object is stored.
96 IStorage* presentationStorage;
99 * The user of this object can setup ONE advise sink
100 * connection with the object. These parameters describe
104 DWORD sinkAdviseFlag;
105 IAdviseSink* sinkInterface;
109 typedef struct DataCache DataCache;
112 * Here, I define utility macros to help with the casting of the
114 * There is a version to accomodate all of the VTables implemented
117 #define _ICOM_THIS_From_IDataObject(class,name) class* this = (class*)name;
118 #define _ICOM_THIS_From_NDIUnknown(class, name) class* this = (class*)(((char*)name)-sizeof(void*));
119 #define _ICOM_THIS_From_IPersistStorage(class, name) class* this = (class*)(((char*)name)-2*sizeof(void*));
120 #define _ICOM_THIS_From_IViewObject2(class, name) class* this = (class*)(((char*)name)-3*sizeof(void*));
121 #define _ICOM_THIS_From_IOleCache2(class, name) class* this = (class*)(((char*)name)-4*sizeof(void*));
122 #define _ICOM_THIS_From_IOleCacheControl(class, name) class* this = (class*)(((char*)name)-5*sizeof(void*));
125 * Prototypes for the methods of the DataCache class.
127 static DataCache* DataCache_Construct(REFCLSID clsid,
128 LPUNKNOWN pUnkOuter);
129 static void DataCache_Destroy(DataCache* ptrToDestroy);
130 static HRESULT DataCache_ReadPresentationData(DataCache* this,
132 PresentationDataHeader* header);
133 static HRESULT DataCache_FindPresStreamName(DataCache* this,
136 static HMETAFILE DataCache_ReadPresMetafile(DataCache* this,
138 static void DataCache_FireOnViewChange(DataCache* this,
143 * Prototypes for the methods of the DataCache class
144 * that implement non delegating IUnknown methods.
146 static HRESULT WINAPI DataCache_NDIUnknown_QueryInterface(
150 static ULONG WINAPI DataCache_NDIUnknown_AddRef(
152 static ULONG WINAPI DataCache_NDIUnknown_Release(
156 * Prototypes for the methods of the DataCache class
157 * that implement IDataObject methods.
159 static HRESULT WINAPI DataCache_IDataObject_QueryInterface(
163 static ULONG WINAPI DataCache_IDataObject_AddRef(
165 static ULONG WINAPI DataCache_IDataObject_Release(
167 static HRESULT WINAPI DataCache_GetData(
169 LPFORMATETC pformatetcIn,
171 static HRESULT WINAPI DataCache_GetDataHere(
173 LPFORMATETC pformatetc,
175 static HRESULT WINAPI DataCache_QueryGetData(
177 LPFORMATETC pformatetc);
178 static HRESULT WINAPI DataCache_GetCanonicalFormatEtc(
180 LPFORMATETC pformatectIn,
181 LPFORMATETC pformatetcOut);
182 static HRESULT WINAPI DataCache_IDataObject_SetData(
184 LPFORMATETC pformatetc,
187 static HRESULT WINAPI DataCache_EnumFormatEtc(
190 IEnumFORMATETC** ppenumFormatEtc);
191 static HRESULT WINAPI DataCache_DAdvise(
193 FORMATETC* pformatetc,
195 IAdviseSink* pAdvSink,
196 DWORD* pdwConnection);
197 static HRESULT WINAPI DataCache_DUnadvise(
200 static HRESULT WINAPI DataCache_EnumDAdvise(
202 IEnumSTATDATA** ppenumAdvise);
205 * Prototypes for the methods of the DataCache class
206 * that implement IPersistStorage methods.
208 static HRESULT WINAPI DataCache_IPersistStorage_QueryInterface(
209 IPersistStorage* iface,
212 static ULONG WINAPI DataCache_IPersistStorage_AddRef(
213 IPersistStorage* iface);
214 static ULONG WINAPI DataCache_IPersistStorage_Release(
215 IPersistStorage* iface);
216 static HRESULT WINAPI DataCache_GetClassID(
217 IPersistStorage* iface,
219 static HRESULT WINAPI DataCache_IsDirty(
220 IPersistStorage* iface);
221 static HRESULT WINAPI DataCache_InitNew(
222 IPersistStorage* iface,
224 static HRESULT WINAPI DataCache_Load(
225 IPersistStorage* iface,
227 static HRESULT WINAPI DataCache_Save(
228 IPersistStorage* iface,
231 static HRESULT WINAPI DataCache_SaveCompleted(
232 IPersistStorage* iface,
234 static HRESULT WINAPI DataCache_HandsOffStorage(
235 IPersistStorage* iface);
238 * Prototypes for the methods of the DataCache class
239 * that implement IViewObject2 methods.
241 static HRESULT WINAPI DataCache_IViewObject2_QueryInterface(
245 static ULONG WINAPI DataCache_IViewObject2_AddRef(
246 IViewObject2* iface);
247 static ULONG WINAPI DataCache_IViewObject2_Release(
248 IViewObject2* iface);
249 static HRESULT WINAPI DataCache_Draw(
258 LPCRECTL lprcWBounds,
259 IVO_ContCallback pfnContinue,
261 static HRESULT WINAPI DataCache_GetColorSet(
268 LOGPALETTE** ppColorSet);
269 static HRESULT WINAPI DataCache_Freeze(
275 static HRESULT WINAPI DataCache_Unfreeze(
278 static HRESULT WINAPI DataCache_SetAdvise(
282 IAdviseSink* pAdvSink);
283 static HRESULT WINAPI DataCache_GetAdvise(
287 IAdviseSink** ppAdvSink);
288 static HRESULT WINAPI DataCache_GetExtent(
296 * Prototypes for the methods of the DataCache class
297 * that implement IOleCache2 methods.
299 static HRESULT WINAPI DataCache_IOleCache2_QueryInterface(
303 static ULONG WINAPI DataCache_IOleCache2_AddRef(
305 static ULONG WINAPI DataCache_IOleCache2_Release(
307 static HRESULT WINAPI DataCache_Cache(
309 FORMATETC* pformatetc,
311 DWORD* pdwConnection);
312 static HRESULT WINAPI DataCache_Uncache(
315 static HRESULT WINAPI DataCache_EnumCache(
317 IEnumSTATDATA** ppenumSTATDATA);
318 static HRESULT WINAPI DataCache_InitCache(
320 IDataObject* pDataObject);
321 static HRESULT WINAPI DataCache_IOleCache2_SetData(
323 FORMATETC* pformatetc,
326 static HRESULT WINAPI DataCache_UpdateCache(
328 LPDATAOBJECT pDataObject,
331 static HRESULT WINAPI DataCache_DiscardCache(
333 DWORD dwDiscardOptions);
336 * Prototypes for the methods of the DataCache class
337 * that implement IOleCacheControl methods.
339 static HRESULT WINAPI DataCache_IOleCacheControl_QueryInterface(
340 IOleCacheControl* iface,
343 static ULONG WINAPI DataCache_IOleCacheControl_AddRef(
344 IOleCacheControl* iface);
345 static ULONG WINAPI DataCache_IOleCacheControl_Release(
346 IOleCacheControl* iface);
347 static HRESULT WINAPI DataCache_OnRun(
348 IOleCacheControl* iface,
349 LPDATAOBJECT pDataObject);
350 static HRESULT WINAPI DataCache_OnStop(
351 IOleCacheControl* iface);
354 * Virtual function tables for the DataCache class.
356 static ICOM_VTABLE(IUnknown) DataCache_NDIUnknown_VTable =
358 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
359 DataCache_NDIUnknown_QueryInterface,
360 DataCache_NDIUnknown_AddRef,
361 DataCache_NDIUnknown_Release
364 static ICOM_VTABLE(IDataObject) DataCache_IDataObject_VTable =
366 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
367 DataCache_IDataObject_QueryInterface,
368 DataCache_IDataObject_AddRef,
369 DataCache_IDataObject_Release,
371 DataCache_GetDataHere,
372 DataCache_QueryGetData,
373 DataCache_GetCanonicalFormatEtc,
374 DataCache_IDataObject_SetData,
375 DataCache_EnumFormatEtc,
378 DataCache_EnumDAdvise
381 static ICOM_VTABLE(IPersistStorage) DataCache_IPersistStorage_VTable =
383 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
384 DataCache_IPersistStorage_QueryInterface,
385 DataCache_IPersistStorage_AddRef,
386 DataCache_IPersistStorage_Release,
387 DataCache_GetClassID,
392 DataCache_SaveCompleted,
393 DataCache_HandsOffStorage
396 static ICOM_VTABLE(IViewObject2) DataCache_IViewObject2_VTable =
398 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
399 DataCache_IViewObject2_QueryInterface,
400 DataCache_IViewObject2_AddRef,
401 DataCache_IViewObject2_Release,
403 DataCache_GetColorSet,
411 static ICOM_VTABLE(IOleCache2) DataCache_IOleCache2_VTable =
413 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
414 DataCache_IOleCache2_QueryInterface,
415 DataCache_IOleCache2_AddRef,
416 DataCache_IOleCache2_Release,
421 DataCache_IOleCache2_SetData,
422 DataCache_UpdateCache,
423 DataCache_DiscardCache
426 static ICOM_VTABLE(IOleCacheControl) DataCache_IOleCacheControl_VTable =
428 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
429 DataCache_IOleCacheControl_QueryInterface,
430 DataCache_IOleCacheControl_AddRef,
431 DataCache_IOleCacheControl_Release,
436 /******************************************************************************
437 * CreateDataCache [OLE32.54]
439 HRESULT WINAPI CreateDataCache(
445 DataCache* newCache = NULL;
450 WINE_StringFromCLSID((LPCLSID)rclsid,xclsid);
451 WINE_StringFromCLSID((LPCLSID)riid,xriid);
453 TRACE("(%s, %p, %s, %p)\n", xclsid, pUnkOuter, xriid, ppvObj);
464 * If this cache is constructed for aggregation, make sure
465 * the caller is requesting the IUnknown interface.
466 * This is necessary because it's the only time the non-delegating
467 * IUnknown pointer can be returned to the outside.
469 if ( (pUnkOuter!=NULL) &&
470 (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) != 0) )
471 return CLASS_E_NOAGGREGATION;
474 * Try to construct a new instance of the class.
476 newCache = DataCache_Construct(rclsid,
480 return E_OUTOFMEMORY;
483 * Make sure it supports the interface required by the caller.
485 hr = IUnknown_QueryInterface((IUnknown*)&(newCache->lpvtbl2), riid, ppvObj);
488 * Release the reference obtained in the constructor. If
489 * the QueryInterface was unsuccessful, it will free the class.
491 IUnknown_Release((IUnknown*)&(newCache->lpvtbl2));
496 /*********************************************************
497 * Method implementation for DataCache class.
499 static DataCache* DataCache_Construct(
503 DataCache* newObject = 0;
506 * Allocate space for the object.
508 newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(DataCache));
514 * Initialize the virtual function table.
516 newObject->lpvtbl1 = &DataCache_IDataObject_VTable;
517 newObject->lpvtbl2 = &DataCache_NDIUnknown_VTable;
518 newObject->lpvtbl3 = &DataCache_IPersistStorage_VTable;
519 newObject->lpvtbl4 = &DataCache_IViewObject2_VTable;
520 newObject->lpvtbl5 = &DataCache_IOleCache2_VTable;
521 newObject->lpvtbl6 = &DataCache_IOleCacheControl_VTable;
524 * Start with one reference count. The caller of this function
525 * must release the interface pointer when it is done.
530 * Initialize the outer unknown
531 * We don't keep a reference on the outer unknown since, the way
532 * aggregation works, our lifetime is at least as large as it's
536 pUnkOuter = (IUnknown*)&(newObject->lpvtbl2);
538 newObject->outerUnknown = pUnkOuter;
541 * Initialize the other members of the structure.
543 newObject->presentationStorage = NULL;
544 newObject->sinkAspects = 0;
545 newObject->sinkAdviseFlag = 0;
546 newObject->sinkInterface = 0;
551 static void DataCache_Destroy(
552 DataCache* ptrToDestroy)
556 if (ptrToDestroy->sinkInterface != NULL)
558 IAdviseSink_Release(ptrToDestroy->sinkInterface);
559 ptrToDestroy->sinkInterface = NULL;
562 if (ptrToDestroy->presentationStorage != NULL)
564 IStorage_Release(ptrToDestroy->presentationStorage);
565 ptrToDestroy->presentationStorage = NULL;
569 * Free the datacache pointer.
571 HeapFree(GetProcessHeap(), 0, ptrToDestroy);
574 /************************************************************************
575 * DataCache_ReadPresentationData
577 * This method will read information for the requested presentation
578 * into the given structure.
581 * this - Pointer to the DataCache object
582 * drawAspect - The aspect of the object that we wish to draw.
583 * header - The structure containing information about this
584 * aspect of the object.
586 static HRESULT DataCache_ReadPresentationData(
589 PresentationDataHeader* header)
591 IStream* presStream = NULL;
592 OLECHAR streamName[20];
596 * Get the name for the presentation stream.
598 hres = DataCache_FindPresStreamName(
607 * Open the stream and read the header.
609 hres = IStorage_OpenStream(
610 this->presentationStorage,
613 STGM_READ | STGM_SHARE_EXCLUSIVE,
623 sizeof(PresentationDataHeader),
629 IStream_Release(presStream);
632 * We don't want to propagate any other error
633 * code than a failure.
641 /************************************************************************
642 * DataCache_FireOnViewChange
644 * This method will fire an OnViewChange notification to the advise
645 * sink registered with the datacache.
647 * See IAdviseSink::OnViewChange for more details.
649 static void DataCache_FireOnViewChange(
654 TRACE("(%p, %lx, %ld)\n", this, aspect, lindex);
657 * The sink supplies a filter when it registers
658 * we make sure we only send the notifications when that
661 if ((this->sinkAspects & aspect) != 0)
663 if (this->sinkInterface != NULL)
665 IAdviseSink_OnViewChange(this->sinkInterface,
670 * Some sinks want to be unregistered automatically when
671 * the first notification goes out.
673 if ( (this->sinkAdviseFlag & ADVF_ONLYONCE) != 0)
675 IAdviseSink_Release(this->sinkInterface);
677 this->sinkInterface = NULL;
678 this->sinkAspects = 0;
679 this->sinkAdviseFlag = 0;
685 /************************************************************************
686 * DataCache_ReadPresentationData
688 * This method will read information for the requested presentation
689 * into the given structure.
692 * this - Pointer to the DataCache object
693 * drawAspect - The aspect of the object that we wish to draw.
694 * header - The structure containing information about this
695 * aspect of the object.
698 * This method only supports the DVASPECT_CONTENT aspect.
700 static HRESULT DataCache_FindPresStreamName(
705 OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
707 if (drawAspect!=DVASPECT_CONTENT)
710 memcpy(buffer, name, sizeof(name));
715 /************************************************************************
716 * DataCache_ReadPresentationData
718 * This method will read information for the requested presentation
719 * into the given structure.
722 * this - Pointer to the DataCache object
723 * drawAspect - The aspect of the object that we wish to draw.
726 * This method returns a metafile handle if it is successful.
727 * it will return 0 if not.
729 static HMETAFILE DataCache_ReadPresMetafile(
733 LARGE_INTEGER offset;
734 IStream* presStream = NULL;
735 OLECHAR streamName[20];
739 HMETAFILE newMetafile = 0;
742 * Get the name for the presentation stream.
744 hres = DataCache_FindPresStreamName(
753 * Open the stream and read the header.
755 hres = IStorage_OpenStream(
756 this->presentationStorage,
759 STGM_READ | STGM_SHARE_EXCLUSIVE,
767 * Get the size of the stream.
769 hres = IStream_Stat(presStream,
776 offset.s.HighPart = 0;
777 offset.s.LowPart = sizeof(PresentationDataHeader);
786 * Allocate a buffer for the metafile bits.
788 metafileBits = HeapAlloc(GetProcessHeap(),
790 streamInfo.cbSize.s.LowPart);
793 * Read the metafile bits.
798 streamInfo.cbSize.s.LowPart,
802 * Create a metafile with those bits.
806 newMetafile = SetMetaFileBitsEx(streamInfo.cbSize.s.LowPart, metafileBits);
812 HeapFree(GetProcessHeap(), 0, metafileBits);
813 IStream_Release(presStream);
821 /*********************************************************
822 * Method implementation for the non delegating IUnknown
823 * part of the DataCache class.
826 /************************************************************************
827 * DataCache_NDIUnknown_QueryInterface (IUnknown)
829 * See Windows documentation for more details on IUnknown methods.
831 * This version of QueryInterface will not delegate it's implementation
832 * to the outer unknown.
834 static HRESULT WINAPI DataCache_NDIUnknown_QueryInterface(
839 _ICOM_THIS_From_NDIUnknown(DataCache, iface);
842 * Perform a sanity check on the parameters.
844 if ( (this==0) || (ppvObject==0) )
848 * Initialize the return parameter.
853 * Compare the riid with the interface IDs implemented by this object.
855 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
859 else if (memcmp(&IID_IDataObject, riid, sizeof(IID_IDataObject)) == 0)
861 *ppvObject = (IDataObject*)&(this->lpvtbl1);
863 else if ( (memcmp(&IID_IPersistStorage, riid, sizeof(IID_IPersistStorage)) == 0) ||
864 (memcmp(&IID_IPersist, riid, sizeof(IID_IPersist)) == 0) )
866 *ppvObject = (IPersistStorage*)&(this->lpvtbl3);
868 else if ( (memcmp(&IID_IViewObject, riid, sizeof(IID_IViewObject)) == 0) ||
869 (memcmp(&IID_IViewObject2, riid, sizeof(IID_IViewObject2)) == 0) )
871 *ppvObject = (IViewObject2*)&(this->lpvtbl4);
873 else if ( (memcmp(&IID_IOleCache, riid, sizeof(IID_IOleCache)) == 0) ||
874 (memcmp(&IID_IOleCache2, riid, sizeof(IID_IOleCache2)) == 0) )
876 *ppvObject = (IOleCache2*)&(this->lpvtbl5);
878 else if (memcmp(&IID_IOleCacheControl, riid, sizeof(IID_IOleCacheControl)) == 0)
880 *ppvObject = (IOleCacheControl*)&(this->lpvtbl6);
884 * Check that we obtained an interface.
890 WINE_StringFromCLSID((LPCLSID)riid,clsid);
893 "() : asking for un supported interface %s\n",
896 return E_NOINTERFACE;
900 * Query Interface always increases the reference count by one when it is
903 IUnknown_AddRef((IUnknown*)*ppvObject);
908 /************************************************************************
909 * DataCache_NDIUnknown_AddRef (IUnknown)
911 * See Windows documentation for more details on IUnknown methods.
913 * This version of QueryInterface will not delegate it's implementation
914 * to the outer unknown.
916 static ULONG WINAPI DataCache_NDIUnknown_AddRef(
919 _ICOM_THIS_From_NDIUnknown(DataCache, iface);
926 /************************************************************************
927 * DataCache_NDIUnknown_Release (IUnknown)
929 * See Windows documentation for more details on IUnknown methods.
931 * This version of QueryInterface will not delegate it's implementation
932 * to the outer unknown.
934 static ULONG WINAPI DataCache_NDIUnknown_Release(
937 _ICOM_THIS_From_NDIUnknown(DataCache, iface);
940 * Decrease the reference count on this object.
945 * If the reference count goes down to 0, perform suicide.
949 DataCache_Destroy(this);
957 /*********************************************************
958 * Method implementation for the IDataObject
959 * part of the DataCache class.
962 /************************************************************************
963 * DataCache_IDataObject_QueryInterface (IUnknown)
965 * See Windows documentation for more details on IUnknown methods.
967 static HRESULT WINAPI DataCache_IDataObject_QueryInterface(
972 _ICOM_THIS_From_IDataObject(DataCache, iface);
974 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
977 /************************************************************************
978 * DataCache_IDataObject_AddRef (IUnknown)
980 * See Windows documentation for more details on IUnknown methods.
982 static ULONG WINAPI DataCache_IDataObject_AddRef(
985 _ICOM_THIS_From_IDataObject(DataCache, iface);
987 return IUnknown_AddRef(this->outerUnknown);
990 /************************************************************************
991 * DataCache_IDataObject_Release (IUnknown)
993 * See Windows documentation for more details on IUnknown methods.
995 static ULONG WINAPI DataCache_IDataObject_Release(
998 _ICOM_THIS_From_IDataObject(DataCache, iface);
1000 return IUnknown_Release(this->outerUnknown);
1003 static HRESULT WINAPI DataCache_GetData(
1005 LPFORMATETC pformatetcIn,
1012 static HRESULT WINAPI DataCache_GetDataHere(
1014 LPFORMATETC pformatetc,
1021 static HRESULT WINAPI DataCache_QueryGetData(
1023 LPFORMATETC pformatetc)
1029 /************************************************************************
1030 * DataCache_EnumFormatEtc (IDataObject)
1032 * The data cache doesn't implement this method.
1034 * See Windows documentation for more details on IDataObject methods.
1036 static HRESULT WINAPI DataCache_GetCanonicalFormatEtc(
1038 LPFORMATETC pformatectIn,
1039 LPFORMATETC pformatetcOut)
1045 /************************************************************************
1046 * DataCache_IDataObject_SetData (IDataObject)
1048 * This method is delegated to the IOleCache2 implementation.
1050 * See Windows documentation for more details on IDataObject methods.
1052 static HRESULT WINAPI DataCache_IDataObject_SetData(
1054 LPFORMATETC pformatetc,
1058 IOleCache2* oleCache = NULL;
1061 TRACE("(%p, %p, %p, %d)\n", iface, pformatetc, pmedium, fRelease);
1063 hres = IDataObject_QueryInterface(iface, &IID_IOleCache2, (void**)&oleCache);
1066 return E_UNEXPECTED;
1068 hres = IOleCache2_SetData(oleCache, pformatetc, pmedium, fRelease);
1070 IOleCache2_Release(oleCache);
1075 /************************************************************************
1076 * DataCache_EnumFormatEtc (IDataObject)
1078 * The data cache doesn't implement this method.
1080 * See Windows documentation for more details on IDataObject methods.
1082 static HRESULT WINAPI DataCache_EnumFormatEtc(
1085 IEnumFORMATETC** ppenumFormatEtc)
1091 /************************************************************************
1092 * DataCache_DAdvise (IDataObject)
1094 * The data cache doesn't support connections.
1096 * See Windows documentation for more details on IDataObject methods.
1098 static HRESULT WINAPI DataCache_DAdvise(
1100 FORMATETC* pformatetc,
1102 IAdviseSink* pAdvSink,
1103 DWORD* pdwConnection)
1106 return OLE_E_ADVISENOTSUPPORTED;
1109 /************************************************************************
1110 * DataCache_DUnadvise (IDataObject)
1112 * The data cache doesn't support connections.
1114 * See Windows documentation for more details on IDataObject methods.
1116 static HRESULT WINAPI DataCache_DUnadvise(
1121 return OLE_E_NOCONNECTION;
1124 /************************************************************************
1125 * DataCache_EnumDAdvise (IDataObject)
1127 * The data cache doesn't support connections.
1129 * See Windows documentation for more details on IDataObject methods.
1131 static HRESULT WINAPI DataCache_EnumDAdvise(
1133 IEnumSTATDATA** ppenumAdvise)
1136 return OLE_E_ADVISENOTSUPPORTED;
1139 /*********************************************************
1140 * Method implementation for the IDataObject
1141 * part of the DataCache class.
1144 /************************************************************************
1145 * DataCache_IPersistStorage_QueryInterface (IUnknown)
1147 * See Windows documentation for more details on IUnknown methods.
1149 static HRESULT WINAPI DataCache_IPersistStorage_QueryInterface(
1150 IPersistStorage* iface,
1154 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1156 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1159 /************************************************************************
1160 * DataCache_IPersistStorage_AddRef (IUnknown)
1162 * See Windows documentation for more details on IUnknown methods.
1164 static ULONG WINAPI DataCache_IPersistStorage_AddRef(
1165 IPersistStorage* iface)
1167 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1169 return IUnknown_AddRef(this->outerUnknown);
1172 /************************************************************************
1173 * DataCache_IPersistStorage_Release (IUnknown)
1175 * See Windows documentation for more details on IUnknown methods.
1177 static ULONG WINAPI DataCache_IPersistStorage_Release(
1178 IPersistStorage* iface)
1180 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1182 return IUnknown_Release(this->outerUnknown);
1185 /************************************************************************
1186 * DataCache_GetClassID (IPersistStorage)
1188 * The data cache doesn't implement this method.
1190 * See Windows documentation for more details on IPersistStorage methods.
1192 static HRESULT WINAPI DataCache_GetClassID(
1193 IPersistStorage* iface,
1196 TRACE("(%p, %p)\n", iface, pClassID);
1200 /************************************************************************
1201 * DataCache_IsDirty (IPersistStorage)
1203 * Until we actully connect to a running object and retrieve new
1204 * information to it, we never get dirty.
1206 * See Windows documentation for more details on IPersistStorage methods.
1208 static HRESULT WINAPI DataCache_IsDirty(
1209 IPersistStorage* iface)
1211 TRACE("(%p)\n", iface);
1216 /************************************************************************
1217 * DataCache_InitNew (IPersistStorage)
1219 * The data cache implementation of IPersistStorage_InitNew simply stores
1220 * the storage pointer.
1222 * See Windows documentation for more details on IPersistStorage methods.
1224 static HRESULT WINAPI DataCache_InitNew(
1225 IPersistStorage* iface,
1228 TRACE("(%p, %p)\n", iface, pStg);
1230 return DataCache_Load(iface, pStg);
1233 /************************************************************************
1234 * DataCache_Load (IPersistStorage)
1236 * The data cache implementation of IPersistStorage_Load doesn't
1237 * actually load anything. Instead, it holds on to the storage pointer
1238 * and it will load the presentation information when the
1239 * IDataObject_GetData or IViewObject2_Draw methods are called.
1241 * See Windows documentation for more details on IPersistStorage methods.
1243 static HRESULT WINAPI DataCache_Load(
1244 IPersistStorage* iface,
1247 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1249 TRACE("(%p, %p)\n", iface, pStg);
1251 if (this->presentationStorage != NULL)
1253 IStorage_Release(this->presentationStorage);
1256 this->presentationStorage = pStg;
1258 if (this->presentationStorage != NULL)
1260 IStorage_AddRef(this->presentationStorage);
1266 /************************************************************************
1267 * DataCache_Save (IPersistStorage)
1269 * Until we actully connect to a running object and retrieve new
1270 * information to it, we never have to save anything. However, it is
1271 * our responsability to copy the information when saving to a new
1274 * See Windows documentation for more details on IPersistStorage methods.
1276 static HRESULT WINAPI DataCache_Save(
1277 IPersistStorage* iface,
1281 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1283 TRACE("(%p, %p, %d)\n", iface, pStg, fSameAsLoad);
1285 if ( (!fSameAsLoad) &&
1286 (this->presentationStorage!=NULL) )
1288 return IStorage_CopyTo(this->presentationStorage,
1298 /************************************************************************
1299 * DataCache_SaveCompleted (IPersistStorage)
1301 * This method is called to tell the cache to release the storage
1302 * pointer it's currentlu holding.
1304 * See Windows documentation for more details on IPersistStorage methods.
1306 static HRESULT WINAPI DataCache_SaveCompleted(
1307 IPersistStorage* iface,
1310 TRACE("(%p, %p)\n", iface, pStgNew);
1313 * First, make sure we get our hands off any storage we have.
1315 DataCache_HandsOffStorage(iface);
1318 * Then, attach to the new storage.
1320 DataCache_Load(iface, pStgNew);
1325 /************************************************************************
1326 * DataCache_HandsOffStorage (IPersistStorage)
1328 * This method is called to tell the cache to release the storage
1329 * pointer it's currentlu holding.
1331 * See Windows documentation for more details on IPersistStorage methods.
1333 static HRESULT WINAPI DataCache_HandsOffStorage(
1334 IPersistStorage* iface)
1336 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1338 TRACE("(%p)\n", iface);
1340 if (this->presentationStorage != NULL)
1342 IStorage_Release(this->presentationStorage);
1343 this->presentationStorage = NULL;
1349 /*********************************************************
1350 * Method implementation for the IViewObject2
1351 * part of the DataCache class.
1354 /************************************************************************
1355 * DataCache_IViewObject2_QueryInterface (IUnknown)
1357 * See Windows documentation for more details on IUnknown methods.
1359 static HRESULT WINAPI DataCache_IViewObject2_QueryInterface(
1360 IViewObject2* iface,
1364 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1366 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1369 /************************************************************************
1370 * DataCache_IViewObject2_AddRef (IUnknown)
1372 * See Windows documentation for more details on IUnknown methods.
1374 static ULONG WINAPI DataCache_IViewObject2_AddRef(
1375 IViewObject2* iface)
1377 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1379 return IUnknown_AddRef(this->outerUnknown);
1382 /************************************************************************
1383 * DataCache_IViewObject2_Release (IUnknown)
1385 * See Windows documentation for more details on IUnknown methods.
1387 static ULONG WINAPI DataCache_IViewObject2_Release(
1388 IViewObject2* iface)
1390 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1392 return IUnknown_Release(this->outerUnknown);
1395 /************************************************************************
1396 * DataCache_Draw (IViewObject2)
1398 * This method will draw the cached representation of the object
1399 * to the given device context.
1401 * See Windows documentation for more details on IViewObject2 methods.
1403 static HRESULT WINAPI DataCache_Draw(
1404 IViewObject2* iface,
1408 DVTARGETDEVICE* ptd,
1411 LPCRECTL lprcBounds,
1412 LPCRECTL lprcWBounds,
1413 IVO_ContCallback pfnContinue,
1416 PresentationDataHeader presData;
1417 HMETAFILE presMetafile = 0;
1420 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1422 TRACE("(%p, %lx, %ld, %p, %x, %x, %p, %p, %p, %lx)\n",
1437 if (lprcBounds==NULL)
1438 return E_INVALIDARG;
1441 * First, we need to retrieve the dimensions of the
1442 * image in the metafile.
1444 hres = DataCache_ReadPresentationData(this,
1452 * Then, we can extract the metafile itself from the cached
1455 presMetafile = DataCache_ReadPresMetafile(this,
1459 * If we have a metafile, just draw baby...
1460 * We have to be careful not to modify the state of the
1463 if (presMetafile!=0)
1465 INT prevMapMode = SetMapMode(hdcDraw, MM_ANISOTROPIC);
1467 SIZE oldViewportExt;
1468 POINT oldViewportOrg;
1470 SetWindowExtEx(hdcDraw,
1471 presData.objectExtentX,
1472 presData.objectExtentY,
1475 SetViewportExtEx(hdcDraw,
1476 lprcBounds->right - lprcBounds->left,
1477 lprcBounds->bottom - lprcBounds->top,
1480 SetViewportOrgEx(hdcDraw,
1485 PlayMetaFile(hdcDraw, presMetafile);
1487 SetWindowExtEx(hdcDraw,
1492 SetViewportExtEx(hdcDraw,
1497 SetViewportOrgEx(hdcDraw,
1502 SetMapMode(hdcDraw, prevMapMode);
1504 DeleteMetaFile(presMetafile);
1510 static HRESULT WINAPI DataCache_GetColorSet(
1511 IViewObject2* iface,
1515 DVTARGETDEVICE* ptd,
1516 HDC hicTargetDevice,
1517 LOGPALETTE** ppColorSet)
1523 static HRESULT WINAPI DataCache_Freeze(
1524 IViewObject2* iface,
1534 static HRESULT WINAPI DataCache_Unfreeze(
1535 IViewObject2* iface,
1542 /************************************************************************
1543 * DataCache_SetAdvise (IViewObject2)
1545 * This sets-up an advisory sink with the data cache. When the object's
1546 * view changes, this sink is called.
1548 * See Windows documentation for more details on IViewObject2 methods.
1550 static HRESULT WINAPI DataCache_SetAdvise(
1551 IViewObject2* iface,
1554 IAdviseSink* pAdvSink)
1556 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1558 TRACE("(%p, %lx, %lx, %p)\n", iface, aspects, advf, pAdvSink);
1561 * A call to this function removes the previous sink
1563 if (this->sinkInterface != NULL)
1565 IAdviseSink_Release(this->sinkInterface);
1566 this->sinkInterface = NULL;
1567 this->sinkAspects = 0;
1568 this->sinkAdviseFlag = 0;
1572 * Now, setup the new one.
1576 this->sinkInterface = pAdvSink;
1577 this->sinkAspects = aspects;
1578 this->sinkAdviseFlag = advf;
1580 IAdviseSink_AddRef(this->sinkInterface);
1584 * When the ADVF_PRIMEFIRST flag is set, we have to advise the
1587 if (advf & ADVF_PRIMEFIRST)
1589 DataCache_FireOnViewChange(this,
1597 /************************************************************************
1598 * DataCache_GetAdvise (IViewObject2)
1600 * This method queries the current state of the advise sink
1601 * installed on the data cache.
1603 * See Windows documentation for more details on IViewObject2 methods.
1605 static HRESULT WINAPI DataCache_GetAdvise(
1606 IViewObject2* iface,
1609 IAdviseSink** ppAdvSink)
1611 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1613 TRACE("(%p, %p, %p, %p)\n", iface, pAspects, pAdvf, ppAdvSink);
1616 * Just copy all the requested values.
1619 *pAspects = this->sinkAspects;
1622 *pAdvf = this->sinkAdviseFlag;
1624 if (ppAdvSink!=NULL)
1626 IAdviseSink_QueryInterface(this->sinkInterface,
1634 /************************************************************************
1635 * DataCache_GetExtent (IViewObject2)
1637 * This method retrieves the "natural" size of this cached object.
1639 * See Windows documentation for more details on IViewObject2 methods.
1641 static HRESULT WINAPI DataCache_GetExtent(
1642 IViewObject2* iface,
1645 DVTARGETDEVICE* ptd,
1648 PresentationDataHeader presData;
1649 HRESULT hres = E_FAIL;
1651 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1653 TRACE("(%p, %lx, %ld, %p, %p)\n",
1654 iface, dwDrawAspect, lindex, ptd, lpsizel);
1663 * Initialize the out parameter.
1669 * This flag should be set to -1.
1672 FIXME("Unimplemented flag lindex = %ld\n", lindex);
1675 * Right now, we suport only the callback from
1676 * the default handler.
1679 FIXME("Unimplemented ptd = %p\n", ptd);
1682 * Get the presentation information from the
1685 hres = DataCache_ReadPresentationData(this,
1689 if (SUCCEEDED(hres))
1691 lpsizel->cx = presData.objectExtentX;
1692 lpsizel->cy = presData.objectExtentY;
1696 * This method returns OLE_E_BLANK when it fails.
1705 /*********************************************************
1706 * Method implementation for the IOleCache2
1707 * part of the DataCache class.
1710 /************************************************************************
1711 * DataCache_IOleCache2_QueryInterface (IUnknown)
1713 * See Windows documentation for more details on IUnknown methods.
1715 static HRESULT WINAPI DataCache_IOleCache2_QueryInterface(
1720 _ICOM_THIS_From_IOleCache2(DataCache, iface);
1722 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1725 /************************************************************************
1726 * DataCache_IOleCache2_AddRef (IUnknown)
1728 * See Windows documentation for more details on IUnknown methods.
1730 static ULONG WINAPI DataCache_IOleCache2_AddRef(
1733 _ICOM_THIS_From_IOleCache2(DataCache, iface);
1735 return IUnknown_AddRef(this->outerUnknown);
1738 /************************************************************************
1739 * DataCache_IOleCache2_Release (IUnknown)
1741 * See Windows documentation for more details on IUnknown methods.
1743 static ULONG WINAPI DataCache_IOleCache2_Release(
1746 _ICOM_THIS_From_IOleCache2(DataCache, iface);
1748 return IUnknown_Release(this->outerUnknown);
1751 static HRESULT WINAPI DataCache_Cache(
1753 FORMATETC* pformatetc,
1755 DWORD* pdwConnection)
1761 static HRESULT WINAPI DataCache_Uncache(
1769 static HRESULT WINAPI DataCache_EnumCache(
1771 IEnumSTATDATA** ppenumSTATDATA)
1777 static HRESULT WINAPI DataCache_InitCache(
1779 IDataObject* pDataObject)
1785 static HRESULT WINAPI DataCache_IOleCache2_SetData(
1787 FORMATETC* pformatetc,
1795 static HRESULT WINAPI DataCache_UpdateCache(
1797 LPDATAOBJECT pDataObject,
1805 static HRESULT WINAPI DataCache_DiscardCache(
1807 DWORD dwDiscardOptions)
1814 /*********************************************************
1815 * Method implementation for the IOleCacheControl
1816 * part of the DataCache class.
1819 /************************************************************************
1820 * DataCache_IOleCacheControl_QueryInterface (IUnknown)
1822 * See Windows documentation for more details on IUnknown methods.
1824 static HRESULT WINAPI DataCache_IOleCacheControl_QueryInterface(
1825 IOleCacheControl* iface,
1829 _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
1831 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1834 /************************************************************************
1835 * DataCache_IOleCacheControl_AddRef (IUnknown)
1837 * See Windows documentation for more details on IUnknown methods.
1839 static ULONG WINAPI DataCache_IOleCacheControl_AddRef(
1840 IOleCacheControl* iface)
1842 _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
1844 return IUnknown_AddRef(this->outerUnknown);
1847 /************************************************************************
1848 * DataCache_IOleCacheControl_Release (IUnknown)
1850 * See Windows documentation for more details on IUnknown methods.
1852 static ULONG WINAPI DataCache_IOleCacheControl_Release(
1853 IOleCacheControl* iface)
1855 _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
1857 return IUnknown_Release(this->outerUnknown);
1860 static HRESULT WINAPI DataCache_OnRun(
1861 IOleCacheControl* iface,
1862 LPDATAOBJECT pDataObject)
1868 static HRESULT WINAPI DataCache_OnStop(
1869 IOleCacheControl* iface)