4 * Copyright 1999 Francis Beaudet
5 * Copyright 2000 Abey George
8 * The OLE2 data cache supports a whole whack of
9 * interfaces including:
10 * IDataObject, IPersistStorage, IViewObject2,
11 * IOleCache2 and IOleCacheControl.
13 * Most of the implementation details are taken from: Inside OLE
14 * second edition by Kraig Brockschmidt,
17 * - This implementation of the datacache will let your application
18 * load documents that have embedded OLE objects in them and it will
19 * also retrieve the metafile representation of those objects.
20 * - This implementation of the datacache will also allow your
21 * application to save new documents with OLE objects in them.
22 * - The main thing that it doesn't do is allow you to activate
23 * or modify the OLE objects in any way.
24 * - I haven't found any good documentation on the real usage of
25 * the streams created by the data cache. In particular, How to
26 * determine what the XXX stands for in the stream name
27 * "\002OlePresXXX". It appears to just be a counter.
28 * - Also, I don't know the real content of the presentation stream
29 * header. I was able to figure-out where the extent of the object
30 * was stored and the aspect, but that's about it.
38 #include "wine/obj_oleview.h"
39 #include "wine/obj_cache.h"
40 #include "wine/unicode.h"
42 #include "debugtools.h"
44 DEFAULT_DEBUG_CHANNEL(ole);
46 /****************************************************************************
47 * PresentationDataHeader
49 * This structure represents the header of the \002OlePresXXX stream in
50 * the OLE object strorage.
52 * Most fields are still unknown.
54 typedef struct PresentationDataHeader
56 DWORD unknown1; /* -1 */
57 DWORD unknown2; /* 3, possibly CF_METAFILEPICT */
58 DWORD unknown3; /* 4, possibly TYMED_ISTREAM */
60 DWORD unknown5; /* -1 */
63 DWORD unknown7; /* 0 */
64 DWORD dwObjectExtentX;
65 DWORD dwObjectExtentY;
67 } PresentationDataHeader;
69 /****************************************************************************
75 * List all interface VTables here
77 ICOM_VTABLE(IDataObject)* lpvtbl1;
78 ICOM_VTABLE(IUnknown)* lpvtbl2;
79 ICOM_VTABLE(IPersistStorage)* lpvtbl3;
80 ICOM_VTABLE(IViewObject2)* lpvtbl4;
81 ICOM_VTABLE(IOleCache2)* lpvtbl5;
82 ICOM_VTABLE(IOleCacheControl)* lpvtbl6;
85 * Reference count of this object
90 * IUnknown implementation of the outer object.
92 IUnknown* outerUnknown;
95 * This storage pointer is set through a call to
96 * IPersistStorage_Load. This is where the visual
97 * representation of the object is stored.
99 IStorage* presentationStorage;
102 * The user of this object can setup ONE advise sink
103 * connection with the object. These parameters describe
107 DWORD sinkAdviseFlag;
108 IAdviseSink* sinkInterface;
112 typedef struct DataCache DataCache;
115 * Here, I define utility macros to help with the casting of the
117 * There is a version to accomodate all of the VTables implemented
120 #define _ICOM_THIS_From_IDataObject(class,name) class* this = (class*)name;
121 #define _ICOM_THIS_From_NDIUnknown(class, name) class* this = (class*)(((char*)name)-sizeof(void*));
122 #define _ICOM_THIS_From_IPersistStorage(class, name) class* this = (class*)(((char*)name)-2*sizeof(void*));
123 #define _ICOM_THIS_From_IViewObject2(class, name) class* this = (class*)(((char*)name)-3*sizeof(void*));
124 #define _ICOM_THIS_From_IOleCache2(class, name) class* this = (class*)(((char*)name)-4*sizeof(void*));
125 #define _ICOM_THIS_From_IOleCacheControl(class, name) class* this = (class*)(((char*)name)-5*sizeof(void*));
128 * Prototypes for the methods of the DataCache class.
130 static DataCache* DataCache_Construct(REFCLSID clsid,
131 LPUNKNOWN pUnkOuter);
132 static void DataCache_Destroy(DataCache* ptrToDestroy);
133 static HRESULT DataCache_ReadPresentationData(DataCache* this,
135 PresentationDataHeader* header);
136 static HRESULT DataCache_OpenPresStream(DataCache *this,
139 static HMETAFILE DataCache_ReadPresMetafile(DataCache* this,
141 static void DataCache_FireOnViewChange(DataCache* this,
146 * Prototypes for the methods of the DataCache class
147 * that implement non delegating IUnknown methods.
149 static HRESULT WINAPI DataCache_NDIUnknown_QueryInterface(
153 static ULONG WINAPI DataCache_NDIUnknown_AddRef(
155 static ULONG WINAPI DataCache_NDIUnknown_Release(
159 * Prototypes for the methods of the DataCache class
160 * that implement IDataObject methods.
162 static HRESULT WINAPI DataCache_IDataObject_QueryInterface(
166 static ULONG WINAPI DataCache_IDataObject_AddRef(
168 static ULONG WINAPI DataCache_IDataObject_Release(
170 static HRESULT WINAPI DataCache_GetData(
172 LPFORMATETC pformatetcIn,
174 static HRESULT WINAPI DataCache_GetDataHere(
176 LPFORMATETC pformatetc,
178 static HRESULT WINAPI DataCache_QueryGetData(
180 LPFORMATETC pformatetc);
181 static HRESULT WINAPI DataCache_GetCanonicalFormatEtc(
183 LPFORMATETC pformatectIn,
184 LPFORMATETC pformatetcOut);
185 static HRESULT WINAPI DataCache_IDataObject_SetData(
187 LPFORMATETC pformatetc,
190 static HRESULT WINAPI DataCache_EnumFormatEtc(
193 IEnumFORMATETC** ppenumFormatEtc);
194 static HRESULT WINAPI DataCache_DAdvise(
196 FORMATETC* pformatetc,
198 IAdviseSink* pAdvSink,
199 DWORD* pdwConnection);
200 static HRESULT WINAPI DataCache_DUnadvise(
203 static HRESULT WINAPI DataCache_EnumDAdvise(
205 IEnumSTATDATA** ppenumAdvise);
208 * Prototypes for the methods of the DataCache class
209 * that implement IPersistStorage methods.
211 static HRESULT WINAPI DataCache_IPersistStorage_QueryInterface(
212 IPersistStorage* iface,
215 static ULONG WINAPI DataCache_IPersistStorage_AddRef(
216 IPersistStorage* iface);
217 static ULONG WINAPI DataCache_IPersistStorage_Release(
218 IPersistStorage* iface);
219 static HRESULT WINAPI DataCache_GetClassID(
220 IPersistStorage* iface,
222 static HRESULT WINAPI DataCache_IsDirty(
223 IPersistStorage* iface);
224 static HRESULT WINAPI DataCache_InitNew(
225 IPersistStorage* iface,
227 static HRESULT WINAPI DataCache_Load(
228 IPersistStorage* iface,
230 static HRESULT WINAPI DataCache_Save(
231 IPersistStorage* iface,
234 static HRESULT WINAPI DataCache_SaveCompleted(
235 IPersistStorage* iface,
237 static HRESULT WINAPI DataCache_HandsOffStorage(
238 IPersistStorage* iface);
241 * Prototypes for the methods of the DataCache class
242 * that implement IViewObject2 methods.
244 static HRESULT WINAPI DataCache_IViewObject2_QueryInterface(
248 static ULONG WINAPI DataCache_IViewObject2_AddRef(
249 IViewObject2* iface);
250 static ULONG WINAPI DataCache_IViewObject2_Release(
251 IViewObject2* iface);
252 static HRESULT WINAPI DataCache_Draw(
261 LPCRECTL lprcWBounds,
262 IVO_ContCallback pfnContinue,
264 static HRESULT WINAPI DataCache_GetColorSet(
271 LOGPALETTE** ppColorSet);
272 static HRESULT WINAPI DataCache_Freeze(
278 static HRESULT WINAPI DataCache_Unfreeze(
281 static HRESULT WINAPI DataCache_SetAdvise(
285 IAdviseSink* pAdvSink);
286 static HRESULT WINAPI DataCache_GetAdvise(
290 IAdviseSink** ppAdvSink);
291 static HRESULT WINAPI DataCache_GetExtent(
299 * Prototypes for the methods of the DataCache class
300 * that implement IOleCache2 methods.
302 static HRESULT WINAPI DataCache_IOleCache2_QueryInterface(
306 static ULONG WINAPI DataCache_IOleCache2_AddRef(
308 static ULONG WINAPI DataCache_IOleCache2_Release(
310 static HRESULT WINAPI DataCache_Cache(
312 FORMATETC* pformatetc,
314 DWORD* pdwConnection);
315 static HRESULT WINAPI DataCache_Uncache(
318 static HRESULT WINAPI DataCache_EnumCache(
320 IEnumSTATDATA** ppenumSTATDATA);
321 static HRESULT WINAPI DataCache_InitCache(
323 IDataObject* pDataObject);
324 static HRESULT WINAPI DataCache_IOleCache2_SetData(
326 FORMATETC* pformatetc,
329 static HRESULT WINAPI DataCache_UpdateCache(
331 LPDATAOBJECT pDataObject,
334 static HRESULT WINAPI DataCache_DiscardCache(
336 DWORD dwDiscardOptions);
339 * Prototypes for the methods of the DataCache class
340 * that implement IOleCacheControl methods.
342 static HRESULT WINAPI DataCache_IOleCacheControl_QueryInterface(
343 IOleCacheControl* iface,
346 static ULONG WINAPI DataCache_IOleCacheControl_AddRef(
347 IOleCacheControl* iface);
348 static ULONG WINAPI DataCache_IOleCacheControl_Release(
349 IOleCacheControl* iface);
350 static HRESULT WINAPI DataCache_OnRun(
351 IOleCacheControl* iface,
352 LPDATAOBJECT pDataObject);
353 static HRESULT WINAPI DataCache_OnStop(
354 IOleCacheControl* iface);
357 * Virtual function tables for the DataCache class.
359 static ICOM_VTABLE(IUnknown) DataCache_NDIUnknown_VTable =
361 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
362 DataCache_NDIUnknown_QueryInterface,
363 DataCache_NDIUnknown_AddRef,
364 DataCache_NDIUnknown_Release
367 static ICOM_VTABLE(IDataObject) DataCache_IDataObject_VTable =
369 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
370 DataCache_IDataObject_QueryInterface,
371 DataCache_IDataObject_AddRef,
372 DataCache_IDataObject_Release,
374 DataCache_GetDataHere,
375 DataCache_QueryGetData,
376 DataCache_GetCanonicalFormatEtc,
377 DataCache_IDataObject_SetData,
378 DataCache_EnumFormatEtc,
381 DataCache_EnumDAdvise
384 static ICOM_VTABLE(IPersistStorage) DataCache_IPersistStorage_VTable =
386 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
387 DataCache_IPersistStorage_QueryInterface,
388 DataCache_IPersistStorage_AddRef,
389 DataCache_IPersistStorage_Release,
390 DataCache_GetClassID,
395 DataCache_SaveCompleted,
396 DataCache_HandsOffStorage
399 static ICOM_VTABLE(IViewObject2) DataCache_IViewObject2_VTable =
401 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
402 DataCache_IViewObject2_QueryInterface,
403 DataCache_IViewObject2_AddRef,
404 DataCache_IViewObject2_Release,
406 DataCache_GetColorSet,
414 static ICOM_VTABLE(IOleCache2) DataCache_IOleCache2_VTable =
416 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
417 DataCache_IOleCache2_QueryInterface,
418 DataCache_IOleCache2_AddRef,
419 DataCache_IOleCache2_Release,
424 DataCache_IOleCache2_SetData,
425 DataCache_UpdateCache,
426 DataCache_DiscardCache
429 static ICOM_VTABLE(IOleCacheControl) DataCache_IOleCacheControl_VTable =
431 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
432 DataCache_IOleCacheControl_QueryInterface,
433 DataCache_IOleCacheControl_AddRef,
434 DataCache_IOleCacheControl_Release,
439 /******************************************************************************
440 * CreateDataCache [OLE32.54]
442 HRESULT WINAPI CreateDataCache(
448 DataCache* newCache = NULL;
451 TRACE("(%s, %p, %s, %p)\n", debugstr_guid(rclsid), pUnkOuter, debugstr_guid(riid), ppvObj);
462 * If this cache is constructed for aggregation, make sure
463 * the caller is requesting the IUnknown interface.
464 * This is necessary because it's the only time the non-delegating
465 * IUnknown pointer can be returned to the outside.
467 if ( (pUnkOuter!=NULL) &&
468 (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) != 0) )
469 return CLASS_E_NOAGGREGATION;
472 * Try to construct a new instance of the class.
474 newCache = DataCache_Construct(rclsid,
478 return E_OUTOFMEMORY;
481 * Make sure it supports the interface required by the caller.
483 hr = IUnknown_QueryInterface((IUnknown*)&(newCache->lpvtbl2), riid, ppvObj);
486 * Release the reference obtained in the constructor. If
487 * the QueryInterface was unsuccessful, it will free the class.
489 IUnknown_Release((IUnknown*)&(newCache->lpvtbl2));
494 /*********************************************************
495 * Method implementation for DataCache class.
497 static DataCache* DataCache_Construct(
501 DataCache* newObject = 0;
504 * Allocate space for the object.
506 newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(DataCache));
512 * Initialize the virtual function table.
514 newObject->lpvtbl1 = &DataCache_IDataObject_VTable;
515 newObject->lpvtbl2 = &DataCache_NDIUnknown_VTable;
516 newObject->lpvtbl3 = &DataCache_IPersistStorage_VTable;
517 newObject->lpvtbl4 = &DataCache_IViewObject2_VTable;
518 newObject->lpvtbl5 = &DataCache_IOleCache2_VTable;
519 newObject->lpvtbl6 = &DataCache_IOleCacheControl_VTable;
522 * Start with one reference count. The caller of this function
523 * must release the interface pointer when it is done.
528 * Initialize the outer unknown
529 * We don't keep a reference on the outer unknown since, the way
530 * aggregation works, our lifetime is at least as large as it's
534 pUnkOuter = (IUnknown*)&(newObject->lpvtbl2);
536 newObject->outerUnknown = pUnkOuter;
539 * Initialize the other members of the structure.
541 newObject->presentationStorage = NULL;
542 newObject->sinkAspects = 0;
543 newObject->sinkAdviseFlag = 0;
544 newObject->sinkInterface = 0;
549 static void DataCache_Destroy(
550 DataCache* ptrToDestroy)
554 if (ptrToDestroy->sinkInterface != NULL)
556 IAdviseSink_Release(ptrToDestroy->sinkInterface);
557 ptrToDestroy->sinkInterface = NULL;
560 if (ptrToDestroy->presentationStorage != NULL)
562 IStorage_Release(ptrToDestroy->presentationStorage);
563 ptrToDestroy->presentationStorage = NULL;
567 * Free the datacache pointer.
569 HeapFree(GetProcessHeap(), 0, ptrToDestroy);
572 /************************************************************************
573 * DataCache_ReadPresentationData
575 * This method will read information for the requested presentation
576 * into the given structure.
579 * this - Pointer to the DataCache object
580 * drawAspect - The aspect of the object that we wish to draw.
581 * header - The structure containing information about this
582 * aspect of the object.
584 static HRESULT DataCache_ReadPresentationData(
587 PresentationDataHeader* header)
589 IStream* presStream = NULL;
593 * Open the presentation stream.
595 hres = DataCache_OpenPresStream(
610 sizeof(PresentationDataHeader),
616 IStream_Release(presStream);
619 * We don't want to propagate any other error
620 * code than a failure.
628 /************************************************************************
629 * DataCache_FireOnViewChange
631 * This method will fire an OnViewChange notification to the advise
632 * sink registered with the datacache.
634 * See IAdviseSink::OnViewChange for more details.
636 static void DataCache_FireOnViewChange(
641 TRACE("(%p, %lx, %ld)\n", this, aspect, lindex);
644 * The sink supplies a filter when it registers
645 * we make sure we only send the notifications when that
648 if ((this->sinkAspects & aspect) != 0)
650 if (this->sinkInterface != NULL)
652 IAdviseSink_OnViewChange(this->sinkInterface,
657 * Some sinks want to be unregistered automatically when
658 * the first notification goes out.
660 if ( (this->sinkAdviseFlag & ADVF_ONLYONCE) != 0)
662 IAdviseSink_Release(this->sinkInterface);
664 this->sinkInterface = NULL;
665 this->sinkAspects = 0;
666 this->sinkAdviseFlag = 0;
672 /* Helper for DataCache_OpenPresStream */
673 static BOOL DataCache_IsPresentationStream(const STATSTG *elem)
675 /* The presentation streams have names of the form "\002OlePresXXX",
676 * where XXX goes from 000 to 999. */
677 static const WCHAR OlePres[] = { 2,'O','l','e','P','r','e','s' };
679 LPCWSTR name = elem->pwcsName;
681 return (elem->type == STGTY_STREAM)
682 && (elem->cbSize.s.LowPart >= sizeof(PresentationDataHeader))
683 && (strlenW(name) == 11)
684 && (strncmpW(name, OlePres, 8) == 0)
685 && (name[8] >= '0') && (name[8] <= '9')
686 && (name[9] >= '0') && (name[9] <= '9')
687 && (name[10] >= '0') && (name[10] <= '9');
690 /************************************************************************
691 * DataCache_OpenPresStream
693 * This method will find the stream for the given presentation. It makes
694 * no attempt at fallback.
697 * this - Pointer to the DataCache object
698 * drawAspect - The aspect of the object that we wish to draw.
699 * pStm - A returned stream. It points to the beginning of the
700 * - presentation data, including the header.
703 * S_OK The requested stream has been opened.
704 * OLE_E_BLANK The requested stream could not be found.
705 * Quite a few others I'm too lazy to map correctly.
708 * Algorithm: Scan the elements of the presentation storage, looking
709 * for presentation streams. For each presentation stream,
710 * load the header and check to see if the aspect maches.
712 * If a fallback is desired, just opening the first presentation stream
715 static HRESULT DataCache_OpenPresStream(
724 if (!ppStm) return E_POINTER;
726 hr = IStorage_EnumElements(this->presentationStorage, 0, NULL, 0, &pEnum);
727 if (FAILED(hr)) return hr;
729 while ((hr = IEnumSTATSTG_Next(pEnum, 1, &elem, NULL)) == S_OK)
731 if (DataCache_IsPresentationStream(&elem))
735 hr = IStorage_OpenStream(this->presentationStorage, elem.pwcsName,
736 NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0,
740 PresentationDataHeader header;
743 hr = IStream_Read(pStm, &header, sizeof(header), &actual_read);
745 /* can't use SUCCEEDED(hr): S_FALSE counts as an error */
746 if (hr == S_OK && actual_read == sizeof(header)
747 && header.dvAspect == drawAspect)
749 /* Rewind the stream before returning it. */
750 LARGE_INTEGER offset;
751 offset.s.LowPart = 0;
752 offset.s.HighPart = 0;
753 IStream_Seek(pStm, offset, STREAM_SEEK_SET, NULL);
757 CoTaskMemFree(elem.pwcsName);
758 IEnumSTATSTG_Release(pEnum);
763 IStream_Release(pStm);
767 CoTaskMemFree(elem.pwcsName);
770 IEnumSTATSTG_Release(pEnum);
772 return (hr == S_FALSE ? OLE_E_BLANK : hr);
775 /************************************************************************
776 * DataCache_ReadPresentationData
778 * This method will read information for the requested presentation
779 * into the given structure.
782 * this - Pointer to the DataCache object
783 * drawAspect - The aspect of the object that we wish to draw.
786 * This method returns a metafile handle if it is successful.
787 * it will return 0 if not.
789 static HMETAFILE DataCache_ReadPresMetafile(
793 LARGE_INTEGER offset;
794 IStream* presStream = NULL;
798 HMETAFILE newMetafile = 0;
801 * Open the presentation stream.
803 hres = DataCache_OpenPresStream(
812 * Get the size of the stream.
814 hres = IStream_Stat(presStream,
821 offset.s.HighPart = 0;
822 offset.s.LowPart = sizeof(PresentationDataHeader);
830 streamInfo.cbSize.s.LowPart -= offset.s.LowPart;
833 * Allocate a buffer for the metafile bits.
835 metafileBits = HeapAlloc(GetProcessHeap(),
837 streamInfo.cbSize.s.LowPart);
840 * Read the metafile bits.
845 streamInfo.cbSize.s.LowPart,
849 * Create a metafile with those bits.
853 newMetafile = SetMetaFileBitsEx(streamInfo.cbSize.s.LowPart, metafileBits);
859 HeapFree(GetProcessHeap(), 0, metafileBits);
860 IStream_Release(presStream);
868 /*********************************************************
869 * Method implementation for the non delegating IUnknown
870 * part of the DataCache class.
873 /************************************************************************
874 * DataCache_NDIUnknown_QueryInterface (IUnknown)
876 * See Windows documentation for more details on IUnknown methods.
878 * This version of QueryInterface will not delegate it's implementation
879 * to the outer unknown.
881 static HRESULT WINAPI DataCache_NDIUnknown_QueryInterface(
886 _ICOM_THIS_From_NDIUnknown(DataCache, iface);
889 * Perform a sanity check on the parameters.
891 if ( (this==0) || (ppvObject==0) )
895 * Initialize the return parameter.
900 * Compare the riid with the interface IDs implemented by this object.
902 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
906 else if (memcmp(&IID_IDataObject, riid, sizeof(IID_IDataObject)) == 0)
908 *ppvObject = (IDataObject*)&(this->lpvtbl1);
910 else if ( (memcmp(&IID_IPersistStorage, riid, sizeof(IID_IPersistStorage)) == 0) ||
911 (memcmp(&IID_IPersist, riid, sizeof(IID_IPersist)) == 0) )
913 *ppvObject = (IPersistStorage*)&(this->lpvtbl3);
915 else if ( (memcmp(&IID_IViewObject, riid, sizeof(IID_IViewObject)) == 0) ||
916 (memcmp(&IID_IViewObject2, riid, sizeof(IID_IViewObject2)) == 0) )
918 *ppvObject = (IViewObject2*)&(this->lpvtbl4);
920 else if ( (memcmp(&IID_IOleCache, riid, sizeof(IID_IOleCache)) == 0) ||
921 (memcmp(&IID_IOleCache2, riid, sizeof(IID_IOleCache2)) == 0) )
923 *ppvObject = (IOleCache2*)&(this->lpvtbl5);
925 else if (memcmp(&IID_IOleCacheControl, riid, sizeof(IID_IOleCacheControl)) == 0)
927 *ppvObject = (IOleCacheControl*)&(this->lpvtbl6);
931 * Check that we obtained an interface.
935 WARN( "() : asking for un supported interface %s\n", debugstr_guid(riid));
936 return E_NOINTERFACE;
940 * Query Interface always increases the reference count by one when it is
943 IUnknown_AddRef((IUnknown*)*ppvObject);
948 /************************************************************************
949 * DataCache_NDIUnknown_AddRef (IUnknown)
951 * See Windows documentation for more details on IUnknown methods.
953 * This version of QueryInterface will not delegate it's implementation
954 * to the outer unknown.
956 static ULONG WINAPI DataCache_NDIUnknown_AddRef(
959 _ICOM_THIS_From_NDIUnknown(DataCache, iface);
966 /************************************************************************
967 * DataCache_NDIUnknown_Release (IUnknown)
969 * See Windows documentation for more details on IUnknown methods.
971 * This version of QueryInterface will not delegate it's implementation
972 * to the outer unknown.
974 static ULONG WINAPI DataCache_NDIUnknown_Release(
977 _ICOM_THIS_From_NDIUnknown(DataCache, iface);
980 * Decrease the reference count on this object.
985 * If the reference count goes down to 0, perform suicide.
989 DataCache_Destroy(this);
997 /*********************************************************
998 * Method implementation for the IDataObject
999 * part of the DataCache class.
1002 /************************************************************************
1003 * DataCache_IDataObject_QueryInterface (IUnknown)
1005 * See Windows documentation for more details on IUnknown methods.
1007 static HRESULT WINAPI DataCache_IDataObject_QueryInterface(
1012 _ICOM_THIS_From_IDataObject(DataCache, iface);
1014 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1017 /************************************************************************
1018 * DataCache_IDataObject_AddRef (IUnknown)
1020 * See Windows documentation for more details on IUnknown methods.
1022 static ULONG WINAPI DataCache_IDataObject_AddRef(
1025 _ICOM_THIS_From_IDataObject(DataCache, iface);
1027 return IUnknown_AddRef(this->outerUnknown);
1030 /************************************************************************
1031 * DataCache_IDataObject_Release (IUnknown)
1033 * See Windows documentation for more details on IUnknown methods.
1035 static ULONG WINAPI DataCache_IDataObject_Release(
1038 _ICOM_THIS_From_IDataObject(DataCache, iface);
1040 return IUnknown_Release(this->outerUnknown);
1043 /************************************************************************
1046 * Get Data from a source dataobject using format pformatetcIn->cfFormat
1047 * See Windows documentation for more details on GetData.
1048 * TODO: Currently only CF_METAFILEPICT is implemented
1050 static HRESULT WINAPI DataCache_GetData(
1052 LPFORMATETC pformatetcIn,
1056 HRESULT hrRet = E_UNEXPECTED;
1057 IPersistStorage *pPersistStorage = 0;
1058 IStorage *pStorage = 0;
1059 IStream *pStream = 0;
1060 OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
1061 HGLOBAL hGlobalMF = 0;
1063 PresentationDataHeader pdh;
1064 METAFILEPICT *mfPict;
1065 HMETAFILE hMetaFile = 0;
1067 if (pformatetcIn->cfFormat == CF_METAFILEPICT)
1069 /* Get the Persist Storage */
1071 hr = IDataObject_QueryInterface(iface, &IID_IPersistStorage, (void**)&pPersistStorage);
1076 /* Create a doc file to copy the doc to a storage */
1078 hr = StgCreateDocfile(NULL, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &pStorage);
1083 /* Save it to storage */
1085 hr = OleSave(pPersistStorage, pStorage, FALSE);
1090 /* Open the Presentation data srteam */
1092 hr = IStorage_OpenStream(pStorage, name, 0, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &pStream);
1097 /* Read the presentation header */
1099 hr = IStream_Read(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
1104 mfBits = HeapAlloc(GetProcessHeap(), 0, pdh.dwSize);
1106 /* Read the Metafile bits */
1108 hr = IStream_Read(pStream, mfBits, pdh.dwSize, NULL);
1113 /* Create the metafile and place it in the STGMEDIUM structure */
1115 hMetaFile = SetMetaFileBitsEx(pdh.dwSize, mfBits);
1117 hGlobalMF = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, sizeof(METAFILEPICT));
1118 mfPict = (METAFILEPICT *)GlobalLock(hGlobalMF);
1119 mfPict->hMF = hMetaFile;
1121 GlobalUnlock(hGlobalMF);
1123 pmedium->u.hGlobal = hGlobalMF;
1124 pmedium->tymed = TYMED_MFPICT;
1130 HeapFree(GetProcessHeap(), 0, mfBits);
1133 IStream_Release(pStream);
1136 IStorage_Release(pStorage);
1138 if (pPersistStorage)
1139 IPersistStorage_Release(pPersistStorage);
1144 /* TODO: Other formats are not implemented */
1149 static HRESULT WINAPI DataCache_GetDataHere(
1151 LPFORMATETC pformatetc,
1158 static HRESULT WINAPI DataCache_QueryGetData(
1160 LPFORMATETC pformatetc)
1166 /************************************************************************
1167 * DataCache_EnumFormatEtc (IDataObject)
1169 * The data cache doesn't implement this method.
1171 * See Windows documentation for more details on IDataObject methods.
1173 static HRESULT WINAPI DataCache_GetCanonicalFormatEtc(
1175 LPFORMATETC pformatectIn,
1176 LPFORMATETC pformatetcOut)
1182 /************************************************************************
1183 * DataCache_IDataObject_SetData (IDataObject)
1185 * This method is delegated to the IOleCache2 implementation.
1187 * See Windows documentation for more details on IDataObject methods.
1189 static HRESULT WINAPI DataCache_IDataObject_SetData(
1191 LPFORMATETC pformatetc,
1195 IOleCache2* oleCache = NULL;
1198 TRACE("(%p, %p, %p, %d)\n", iface, pformatetc, pmedium, fRelease);
1200 hres = IDataObject_QueryInterface(iface, &IID_IOleCache2, (void**)&oleCache);
1203 return E_UNEXPECTED;
1205 hres = IOleCache2_SetData(oleCache, pformatetc, pmedium, fRelease);
1207 IOleCache2_Release(oleCache);
1212 /************************************************************************
1213 * DataCache_EnumFormatEtc (IDataObject)
1215 * The data cache doesn't implement this method.
1217 * See Windows documentation for more details on IDataObject methods.
1219 static HRESULT WINAPI DataCache_EnumFormatEtc(
1222 IEnumFORMATETC** ppenumFormatEtc)
1228 /************************************************************************
1229 * DataCache_DAdvise (IDataObject)
1231 * The data cache doesn't support connections.
1233 * See Windows documentation for more details on IDataObject methods.
1235 static HRESULT WINAPI DataCache_DAdvise(
1237 FORMATETC* pformatetc,
1239 IAdviseSink* pAdvSink,
1240 DWORD* pdwConnection)
1243 return OLE_E_ADVISENOTSUPPORTED;
1246 /************************************************************************
1247 * DataCache_DUnadvise (IDataObject)
1249 * The data cache doesn't support connections.
1251 * See Windows documentation for more details on IDataObject methods.
1253 static HRESULT WINAPI DataCache_DUnadvise(
1258 return OLE_E_NOCONNECTION;
1261 /************************************************************************
1262 * DataCache_EnumDAdvise (IDataObject)
1264 * The data cache doesn't support connections.
1266 * See Windows documentation for more details on IDataObject methods.
1268 static HRESULT WINAPI DataCache_EnumDAdvise(
1270 IEnumSTATDATA** ppenumAdvise)
1273 return OLE_E_ADVISENOTSUPPORTED;
1276 /*********************************************************
1277 * Method implementation for the IDataObject
1278 * part of the DataCache class.
1281 /************************************************************************
1282 * DataCache_IPersistStorage_QueryInterface (IUnknown)
1284 * See Windows documentation for more details on IUnknown methods.
1286 static HRESULT WINAPI DataCache_IPersistStorage_QueryInterface(
1287 IPersistStorage* iface,
1291 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1293 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1296 /************************************************************************
1297 * DataCache_IPersistStorage_AddRef (IUnknown)
1299 * See Windows documentation for more details on IUnknown methods.
1301 static ULONG WINAPI DataCache_IPersistStorage_AddRef(
1302 IPersistStorage* iface)
1304 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1306 return IUnknown_AddRef(this->outerUnknown);
1309 /************************************************************************
1310 * DataCache_IPersistStorage_Release (IUnknown)
1312 * See Windows documentation for more details on IUnknown methods.
1314 static ULONG WINAPI DataCache_IPersistStorage_Release(
1315 IPersistStorage* iface)
1317 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1319 return IUnknown_Release(this->outerUnknown);
1322 /************************************************************************
1323 * DataCache_GetClassID (IPersistStorage)
1325 * The data cache doesn't implement this method.
1327 * See Windows documentation for more details on IPersistStorage methods.
1329 static HRESULT WINAPI DataCache_GetClassID(
1330 IPersistStorage* iface,
1333 TRACE("(%p, %p)\n", iface, pClassID);
1337 /************************************************************************
1338 * DataCache_IsDirty (IPersistStorage)
1340 * Until we actully connect to a running object and retrieve new
1341 * information to it, we never get dirty.
1343 * See Windows documentation for more details on IPersistStorage methods.
1345 static HRESULT WINAPI DataCache_IsDirty(
1346 IPersistStorage* iface)
1348 TRACE("(%p)\n", iface);
1353 /************************************************************************
1354 * DataCache_InitNew (IPersistStorage)
1356 * The data cache implementation of IPersistStorage_InitNew simply stores
1357 * the storage pointer.
1359 * See Windows documentation for more details on IPersistStorage methods.
1361 static HRESULT WINAPI DataCache_InitNew(
1362 IPersistStorage* iface,
1365 TRACE("(%p, %p)\n", iface, pStg);
1367 return DataCache_Load(iface, pStg);
1370 /************************************************************************
1371 * DataCache_Load (IPersistStorage)
1373 * The data cache implementation of IPersistStorage_Load doesn't
1374 * actually load anything. Instead, it holds on to the storage pointer
1375 * and it will load the presentation information when the
1376 * IDataObject_GetData or IViewObject2_Draw methods are called.
1378 * See Windows documentation for more details on IPersistStorage methods.
1380 static HRESULT WINAPI DataCache_Load(
1381 IPersistStorage* iface,
1384 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1386 TRACE("(%p, %p)\n", iface, pStg);
1388 if (this->presentationStorage != NULL)
1390 IStorage_Release(this->presentationStorage);
1393 this->presentationStorage = pStg;
1395 if (this->presentationStorage != NULL)
1397 IStorage_AddRef(this->presentationStorage);
1402 /************************************************************************
1403 * DataCache_Save (IPersistStorage)
1405 * Until we actully connect to a running object and retrieve new
1406 * information to it, we never have to save anything. However, it is
1407 * our responsability to copy the information when saving to a new
1410 * See Windows documentation for more details on IPersistStorage methods.
1412 static HRESULT WINAPI DataCache_Save(
1413 IPersistStorage* iface,
1417 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1419 TRACE("(%p, %p, %d)\n", iface, pStg, fSameAsLoad);
1421 if ( (!fSameAsLoad) &&
1422 (this->presentationStorage!=NULL) )
1424 return IStorage_CopyTo(this->presentationStorage,
1434 /************************************************************************
1435 * DataCache_SaveCompleted (IPersistStorage)
1437 * This method is called to tell the cache to release the storage
1438 * pointer it's currentlu holding.
1440 * See Windows documentation for more details on IPersistStorage methods.
1442 static HRESULT WINAPI DataCache_SaveCompleted(
1443 IPersistStorage* iface,
1446 TRACE("(%p, %p)\n", iface, pStgNew);
1451 * First, make sure we get our hands off any storage we have.
1454 DataCache_HandsOffStorage(iface);
1457 * Then, attach to the new storage.
1460 DataCache_Load(iface, pStgNew);
1466 /************************************************************************
1467 * DataCache_HandsOffStorage (IPersistStorage)
1469 * This method is called to tell the cache to release the storage
1470 * pointer it's currentlu holding.
1472 * See Windows documentation for more details on IPersistStorage methods.
1474 static HRESULT WINAPI DataCache_HandsOffStorage(
1475 IPersistStorage* iface)
1477 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1479 TRACE("(%p)\n", iface);
1481 if (this->presentationStorage != NULL)
1483 IStorage_Release(this->presentationStorage);
1484 this->presentationStorage = NULL;
1490 /*********************************************************
1491 * Method implementation for the IViewObject2
1492 * part of the DataCache class.
1495 /************************************************************************
1496 * DataCache_IViewObject2_QueryInterface (IUnknown)
1498 * See Windows documentation for more details on IUnknown methods.
1500 static HRESULT WINAPI DataCache_IViewObject2_QueryInterface(
1501 IViewObject2* iface,
1505 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1507 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1510 /************************************************************************
1511 * DataCache_IViewObject2_AddRef (IUnknown)
1513 * See Windows documentation for more details on IUnknown methods.
1515 static ULONG WINAPI DataCache_IViewObject2_AddRef(
1516 IViewObject2* iface)
1518 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1520 return IUnknown_AddRef(this->outerUnknown);
1523 /************************************************************************
1524 * DataCache_IViewObject2_Release (IUnknown)
1526 * See Windows documentation for more details on IUnknown methods.
1528 static ULONG WINAPI DataCache_IViewObject2_Release(
1529 IViewObject2* iface)
1531 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1533 return IUnknown_Release(this->outerUnknown);
1536 /************************************************************************
1537 * DataCache_Draw (IViewObject2)
1539 * This method will draw the cached representation of the object
1540 * to the given device context.
1542 * See Windows documentation for more details on IViewObject2 methods.
1544 static HRESULT WINAPI DataCache_Draw(
1545 IViewObject2* iface,
1549 DVTARGETDEVICE* ptd,
1552 LPCRECTL lprcBounds,
1553 LPCRECTL lprcWBounds,
1554 IVO_ContCallback pfnContinue,
1557 PresentationDataHeader presData;
1558 HMETAFILE presMetafile = 0;
1561 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1563 TRACE("(%p, %lx, %ld, %p, %x, %x, %p, %p, %p, %lx)\n",
1578 if (lprcBounds==NULL)
1579 return E_INVALIDARG;
1582 * First, we need to retrieve the dimensions of the
1583 * image in the metafile.
1585 hres = DataCache_ReadPresentationData(this,
1593 * Then, we can extract the metafile itself from the cached
1596 * FIXME Unless it isn't a metafile. I think it could be any CF_XXX type,
1597 * particularly CF_DIB.
1599 presMetafile = DataCache_ReadPresMetafile(this,
1603 * If we have a metafile, just draw baby...
1604 * We have to be careful not to modify the state of the
1607 if (presMetafile!=0)
1609 INT prevMapMode = SetMapMode(hdcDraw, MM_ANISOTROPIC);
1611 SIZE oldViewportExt;
1612 POINT oldViewportOrg;
1614 SetWindowExtEx(hdcDraw,
1615 presData.dwObjectExtentX,
1616 presData.dwObjectExtentY,
1619 SetViewportExtEx(hdcDraw,
1620 lprcBounds->right - lprcBounds->left,
1621 lprcBounds->bottom - lprcBounds->top,
1624 SetViewportOrgEx(hdcDraw,
1629 PlayMetaFile(hdcDraw, presMetafile);
1631 SetWindowExtEx(hdcDraw,
1636 SetViewportExtEx(hdcDraw,
1641 SetViewportOrgEx(hdcDraw,
1646 SetMapMode(hdcDraw, prevMapMode);
1648 DeleteMetaFile(presMetafile);
1654 static HRESULT WINAPI DataCache_GetColorSet(
1655 IViewObject2* iface,
1659 DVTARGETDEVICE* ptd,
1660 HDC hicTargetDevice,
1661 LOGPALETTE** ppColorSet)
1667 static HRESULT WINAPI DataCache_Freeze(
1668 IViewObject2* iface,
1678 static HRESULT WINAPI DataCache_Unfreeze(
1679 IViewObject2* iface,
1686 /************************************************************************
1687 * DataCache_SetAdvise (IViewObject2)
1689 * This sets-up an advisory sink with the data cache. When the object's
1690 * view changes, this sink is called.
1692 * See Windows documentation for more details on IViewObject2 methods.
1694 static HRESULT WINAPI DataCache_SetAdvise(
1695 IViewObject2* iface,
1698 IAdviseSink* pAdvSink)
1700 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1702 TRACE("(%p, %lx, %lx, %p)\n", iface, aspects, advf, pAdvSink);
1705 * A call to this function removes the previous sink
1707 if (this->sinkInterface != NULL)
1709 IAdviseSink_Release(this->sinkInterface);
1710 this->sinkInterface = NULL;
1711 this->sinkAspects = 0;
1712 this->sinkAdviseFlag = 0;
1716 * Now, setup the new one.
1720 this->sinkInterface = pAdvSink;
1721 this->sinkAspects = aspects;
1722 this->sinkAdviseFlag = advf;
1724 IAdviseSink_AddRef(this->sinkInterface);
1728 * When the ADVF_PRIMEFIRST flag is set, we have to advise the
1731 if (advf & ADVF_PRIMEFIRST)
1733 DataCache_FireOnViewChange(this,
1741 /************************************************************************
1742 * DataCache_GetAdvise (IViewObject2)
1744 * This method queries the current state of the advise sink
1745 * installed on the data cache.
1747 * See Windows documentation for more details on IViewObject2 methods.
1749 static HRESULT WINAPI DataCache_GetAdvise(
1750 IViewObject2* iface,
1753 IAdviseSink** ppAdvSink)
1755 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1757 TRACE("(%p, %p, %p, %p)\n", iface, pAspects, pAdvf, ppAdvSink);
1760 * Just copy all the requested values.
1763 *pAspects = this->sinkAspects;
1766 *pAdvf = this->sinkAdviseFlag;
1768 if (ppAdvSink!=NULL)
1770 IAdviseSink_QueryInterface(this->sinkInterface,
1778 /************************************************************************
1779 * DataCache_GetExtent (IViewObject2)
1781 * This method retrieves the "natural" size of this cached object.
1783 * See Windows documentation for more details on IViewObject2 methods.
1785 static HRESULT WINAPI DataCache_GetExtent(
1786 IViewObject2* iface,
1789 DVTARGETDEVICE* ptd,
1792 PresentationDataHeader presData;
1793 HRESULT hres = E_FAIL;
1795 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1797 TRACE("(%p, %lx, %ld, %p, %p)\n",
1798 iface, dwDrawAspect, lindex, ptd, lpsizel);
1807 * Initialize the out parameter.
1813 * This flag should be set to -1.
1816 FIXME("Unimplemented flag lindex = %ld\n", lindex);
1819 * Right now, we suport only the callback from
1820 * the default handler.
1823 FIXME("Unimplemented ptd = %p\n", ptd);
1826 * Get the presentation information from the
1829 hres = DataCache_ReadPresentationData(this,
1833 if (SUCCEEDED(hres))
1835 lpsizel->cx = presData.dwObjectExtentX;
1836 lpsizel->cy = presData.dwObjectExtentY;
1840 * This method returns OLE_E_BLANK when it fails.
1849 /*********************************************************
1850 * Method implementation for the IOleCache2
1851 * part of the DataCache class.
1854 /************************************************************************
1855 * DataCache_IOleCache2_QueryInterface (IUnknown)
1857 * See Windows documentation for more details on IUnknown methods.
1859 static HRESULT WINAPI DataCache_IOleCache2_QueryInterface(
1864 _ICOM_THIS_From_IOleCache2(DataCache, iface);
1866 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1869 /************************************************************************
1870 * DataCache_IOleCache2_AddRef (IUnknown)
1872 * See Windows documentation for more details on IUnknown methods.
1874 static ULONG WINAPI DataCache_IOleCache2_AddRef(
1877 _ICOM_THIS_From_IOleCache2(DataCache, iface);
1879 return IUnknown_AddRef(this->outerUnknown);
1882 /************************************************************************
1883 * DataCache_IOleCache2_Release (IUnknown)
1885 * See Windows documentation for more details on IUnknown methods.
1887 static ULONG WINAPI DataCache_IOleCache2_Release(
1890 _ICOM_THIS_From_IOleCache2(DataCache, iface);
1892 return IUnknown_Release(this->outerUnknown);
1895 static HRESULT WINAPI DataCache_Cache(
1897 FORMATETC* pformatetc,
1899 DWORD* pdwConnection)
1905 static HRESULT WINAPI DataCache_Uncache(
1913 static HRESULT WINAPI DataCache_EnumCache(
1915 IEnumSTATDATA** ppenumSTATDATA)
1921 static HRESULT WINAPI DataCache_InitCache(
1923 IDataObject* pDataObject)
1929 static HRESULT WINAPI DataCache_IOleCache2_SetData(
1931 FORMATETC* pformatetc,
1939 static HRESULT WINAPI DataCache_UpdateCache(
1941 LPDATAOBJECT pDataObject,
1949 static HRESULT WINAPI DataCache_DiscardCache(
1951 DWORD dwDiscardOptions)
1958 /*********************************************************
1959 * Method implementation for the IOleCacheControl
1960 * part of the DataCache class.
1963 /************************************************************************
1964 * DataCache_IOleCacheControl_QueryInterface (IUnknown)
1966 * See Windows documentation for more details on IUnknown methods.
1968 static HRESULT WINAPI DataCache_IOleCacheControl_QueryInterface(
1969 IOleCacheControl* iface,
1973 _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
1975 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1978 /************************************************************************
1979 * DataCache_IOleCacheControl_AddRef (IUnknown)
1981 * See Windows documentation for more details on IUnknown methods.
1983 static ULONG WINAPI DataCache_IOleCacheControl_AddRef(
1984 IOleCacheControl* iface)
1986 _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
1988 return IUnknown_AddRef(this->outerUnknown);
1991 /************************************************************************
1992 * DataCache_IOleCacheControl_Release (IUnknown)
1994 * See Windows documentation for more details on IUnknown methods.
1996 static ULONG WINAPI DataCache_IOleCacheControl_Release(
1997 IOleCacheControl* iface)
1999 _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
2001 return IUnknown_Release(this->outerUnknown);
2004 static HRESULT WINAPI DataCache_OnRun(
2005 IOleCacheControl* iface,
2006 LPDATAOBJECT pDataObject)
2012 static HRESULT WINAPI DataCache_OnStop(
2013 IOleCacheControl* iface)