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 <ole32/ole32.h>
40 #include <storage32.h>
45 /****************************************************************************
46 * PresentationDataHeader
48 * This structure represents the header of the \002OlePresXXX stream in
49 * the OLE object strorage.
51 * Most fields are still unknown.
53 typedef struct PresentationDataHeader
55 DWORD unknown1; /* -1 */
56 DWORD unknown2; /* 3, possibly CF_METAFILEPICT */
57 DWORD unknown3; /* 4, possibly TYMED_ISTREAM */
59 DWORD unknown5; /* -1 */
62 DWORD unknown7; /* 0 */
63 DWORD dwObjectExtentX;
64 DWORD dwObjectExtentY;
66 } PresentationDataHeader;
68 /****************************************************************************
74 * List all interface VTables here
76 ICOM_VTABLE(IDataObject)* lpvtbl1;
77 ICOM_VTABLE(IUnknown)* lpvtbl2;
78 ICOM_VTABLE(IPersistStorage)* lpvtbl3;
79 ICOM_VTABLE(IViewObject2)* lpvtbl4;
80 ICOM_VTABLE(IOleCache2)* lpvtbl5;
81 ICOM_VTABLE(IOleCacheControl)* lpvtbl6;
84 * Reference count of this object
89 * IUnknown implementation of the outer object.
91 IUnknown* outerUnknown;
94 * This storage pointer is set through a call to
95 * IPersistStorage_Load. This is where the visual
96 * representation of the object is stored.
98 IStorage* presentationStorage;
101 * The user of this object can setup ONE advise sink
102 * connection with the object. These parameters describe
106 DWORD sinkAdviseFlag;
107 IAdviseSink* sinkInterface;
111 typedef struct DataCache DataCache;
114 * Here, I define utility macros to help with the casting of the
116 * There is a version to accomodate all of the VTables implemented
119 #define _ICOM_THIS_From_IDataObject(class,name) class* this = (class*)name;
120 #define _ICOM_THIS_From_NDIUnknown(class, name) class* this = (class*)(((char*)name)-sizeof(void*));
121 #define _ICOM_THIS_From_IPersistStorage(class, name) class* this = (class*)(((char*)name)-2*sizeof(void*));
122 #define _ICOM_THIS_From_IViewObject2(class, name) class* this = (class*)(((char*)name)-3*sizeof(void*));
123 #define _ICOM_THIS_From_IOleCache2(class, name) class* this = (class*)(((char*)name)-4*sizeof(void*));
124 #define _ICOM_THIS_From_IOleCacheControl(class, name) class* this = (class*)(((char*)name)-5*sizeof(void*));
127 * Prototypes for the methods of the DataCache class.
129 static DataCache* DataCache_Construct(REFCLSID clsid,
130 LPUNKNOWN pUnkOuter);
131 static void DataCache_Destroy(DataCache* ptrToDestroy);
132 static HRESULT DataCache_ReadPresentationData(DataCache* this,
134 PresentationDataHeader* header);
135 static HRESULT DataCache_OpenPresStream(DataCache *this,
138 static HMETAFILE DataCache_ReadPresMetafile(DataCache* this,
140 static void DataCache_FireOnViewChange(DataCache* this,
145 * Prototypes for the methods of the DataCache class
146 * that implement non delegating IUnknown methods.
148 static HRESULT WINAPI DataCache_NDIUnknown_QueryInterface(
152 static ULONG WINAPI DataCache_NDIUnknown_AddRef(
154 static ULONG WINAPI DataCache_NDIUnknown_Release(
158 * Prototypes for the methods of the DataCache class
159 * that implement IDataObject methods.
161 static HRESULT WINAPI DataCache_IDataObject_QueryInterface(
165 static ULONG WINAPI DataCache_IDataObject_AddRef(
167 static ULONG WINAPI DataCache_IDataObject_Release(
169 static HRESULT WINAPI DataCache_GetData(
171 LPFORMATETC pformatetcIn,
173 static HRESULT WINAPI DataCache_GetDataHere(
175 LPFORMATETC pformatetc,
177 static HRESULT WINAPI DataCache_QueryGetData(
179 LPFORMATETC pformatetc);
180 static HRESULT WINAPI DataCache_GetCanonicalFormatEtc(
182 LPFORMATETC pformatectIn,
183 LPFORMATETC pformatetcOut);
184 static HRESULT WINAPI DataCache_IDataObject_SetData(
186 LPFORMATETC pformatetc,
189 static HRESULT WINAPI DataCache_EnumFormatEtc(
192 IEnumFORMATETC** ppenumFormatEtc);
193 static HRESULT WINAPI DataCache_DAdvise(
195 FORMATETC* pformatetc,
197 IAdviseSink* pAdvSink,
198 DWORD* pdwConnection);
199 static HRESULT WINAPI DataCache_DUnadvise(
202 static HRESULT WINAPI DataCache_EnumDAdvise(
204 IEnumSTATDATA** ppenumAdvise);
207 * Prototypes for the methods of the DataCache class
208 * that implement IPersistStorage methods.
210 static HRESULT WINAPI DataCache_IPersistStorage_QueryInterface(
211 IPersistStorage* iface,
214 static ULONG WINAPI DataCache_IPersistStorage_AddRef(
215 IPersistStorage* iface);
216 static ULONG WINAPI DataCache_IPersistStorage_Release(
217 IPersistStorage* iface);
218 static HRESULT WINAPI DataCache_GetClassID(
219 IPersistStorage* iface,
221 static HRESULT WINAPI DataCache_IsDirty(
222 IPersistStorage* iface);
223 static HRESULT WINAPI DataCache_InitNew(
224 IPersistStorage* iface,
226 static HRESULT WINAPI DataCache_Load(
227 IPersistStorage* iface,
229 static HRESULT WINAPI DataCache_Save(
230 IPersistStorage* iface,
233 static HRESULT WINAPI DataCache_SaveCompleted(
234 IPersistStorage* iface,
236 static HRESULT WINAPI DataCache_HandsOffStorage(
237 IPersistStorage* iface);
240 * Prototypes for the methods of the DataCache class
241 * that implement IViewObject2 methods.
243 static HRESULT WINAPI DataCache_IViewObject2_QueryInterface(
247 static ULONG WINAPI DataCache_IViewObject2_AddRef(
248 IViewObject2* iface);
249 static ULONG WINAPI DataCache_IViewObject2_Release(
250 IViewObject2* iface);
251 static HRESULT WINAPI DataCache_Draw(
260 LPCRECTL lprcWBounds,
261 IVO_ContCallback pfnContinue,
263 static HRESULT WINAPI DataCache_GetColorSet(
270 LOGPALETTE** ppColorSet);
271 static HRESULT WINAPI DataCache_Freeze(
277 static HRESULT WINAPI DataCache_Unfreeze(
280 static HRESULT WINAPI DataCache_SetAdvise(
284 IAdviseSink* pAdvSink);
285 static HRESULT WINAPI DataCache_GetAdvise(
289 IAdviseSink** ppAdvSink);
290 static HRESULT WINAPI DataCache_GetExtent(
298 * Prototypes for the methods of the DataCache class
299 * that implement IOleCache2 methods.
301 static HRESULT WINAPI DataCache_IOleCache2_QueryInterface(
305 static ULONG WINAPI DataCache_IOleCache2_AddRef(
307 static ULONG WINAPI DataCache_IOleCache2_Release(
309 static HRESULT WINAPI DataCache_Cache(
311 FORMATETC* pformatetc,
313 DWORD* pdwConnection);
314 static HRESULT WINAPI DataCache_Uncache(
317 static HRESULT WINAPI DataCache_EnumCache(
319 IEnumSTATDATA** ppenumSTATDATA);
320 static HRESULT WINAPI DataCache_InitCache(
322 IDataObject* pDataObject);
323 static HRESULT WINAPI DataCache_IOleCache2_SetData(
325 FORMATETC* pformatetc,
328 static HRESULT WINAPI DataCache_UpdateCache(
330 LPDATAOBJECT pDataObject,
333 static HRESULT WINAPI DataCache_DiscardCache(
335 DWORD dwDiscardOptions);
338 * Prototypes for the methods of the DataCache class
339 * that implement IOleCacheControl methods.
341 static HRESULT WINAPI DataCache_IOleCacheControl_QueryInterface(
342 IOleCacheControl* iface,
345 static ULONG WINAPI DataCache_IOleCacheControl_AddRef(
346 IOleCacheControl* iface);
347 static ULONG WINAPI DataCache_IOleCacheControl_Release(
348 IOleCacheControl* iface);
349 static HRESULT WINAPI DataCache_OnRun(
350 IOleCacheControl* iface,
351 LPDATAOBJECT pDataObject);
352 static HRESULT WINAPI DataCache_OnStop(
353 IOleCacheControl* iface);
356 * Virtual function tables for the DataCache class.
358 static ICOM_VTABLE(IUnknown) DataCache_NDIUnknown_VTable =
360 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
361 DataCache_NDIUnknown_QueryInterface,
362 DataCache_NDIUnknown_AddRef,
363 DataCache_NDIUnknown_Release
366 static ICOM_VTABLE(IDataObject) DataCache_IDataObject_VTable =
368 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
369 DataCache_IDataObject_QueryInterface,
370 DataCache_IDataObject_AddRef,
371 DataCache_IDataObject_Release,
373 DataCache_GetDataHere,
374 DataCache_QueryGetData,
375 DataCache_GetCanonicalFormatEtc,
376 DataCache_IDataObject_SetData,
377 DataCache_EnumFormatEtc,
380 DataCache_EnumDAdvise
383 static ICOM_VTABLE(IPersistStorage) DataCache_IPersistStorage_VTable =
385 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
386 DataCache_IPersistStorage_QueryInterface,
387 DataCache_IPersistStorage_AddRef,
388 DataCache_IPersistStorage_Release,
389 DataCache_GetClassID,
394 DataCache_SaveCompleted,
395 DataCache_HandsOffStorage
398 static ICOM_VTABLE(IViewObject2) DataCache_IViewObject2_VTable =
400 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
401 DataCache_IViewObject2_QueryInterface,
402 DataCache_IViewObject2_AddRef,
403 DataCache_IViewObject2_Release,
405 DataCache_GetColorSet,
413 static ICOM_VTABLE(IOleCache2) DataCache_IOleCache2_VTable =
415 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
416 DataCache_IOleCache2_QueryInterface,
417 DataCache_IOleCache2_AddRef,
418 DataCache_IOleCache2_Release,
423 DataCache_IOleCache2_SetData,
424 DataCache_UpdateCache,
425 DataCache_DiscardCache
428 static ICOM_VTABLE(IOleCacheControl) DataCache_IOleCacheControl_VTable =
430 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
431 DataCache_IOleCacheControl_QueryInterface,
432 DataCache_IOleCacheControl_AddRef,
433 DataCache_IOleCacheControl_Release,
438 /******************************************************************************
439 * CreateDataCache [OLE32.54]
441 HRESULT WINAPI CreateDataCache(
447 DataCache* newCache = NULL;
450 Print(MAX_TRACE, ("(%s, %p, %s, %p)\n", debugstr_guid(rclsid), pUnkOuter, debugstr_guid(riid), ppvObj));
461 * If this cache is constructed for aggregation, make sure
462 * the caller is requesting the IUnknown interface.
463 * This is necessary because it's the only time the non-delegating
464 * IUnknown pointer can be returned to the outside.
466 if ( (pUnkOuter!=NULL) &&
467 (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) != 0) )
468 return CLASS_E_NOAGGREGATION;
471 * Try to construct a new instance of the class.
473 newCache = DataCache_Construct(rclsid,
477 return E_OUTOFMEMORY;
480 * Make sure it supports the interface required by the caller.
482 hr = IUnknown_QueryInterface((IUnknown*)&(newCache->lpvtbl2), riid, ppvObj);
485 * Release the reference obtained in the constructor. If
486 * the QueryInterface was unsuccessful, it will free the class.
488 IUnknown_Release((IUnknown*)&(newCache->lpvtbl2));
493 /*********************************************************
494 * Method implementation for DataCache class.
496 static DataCache* DataCache_Construct(
500 DataCache* newObject = 0;
503 * Allocate space for the object.
505 newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(DataCache));
511 * Initialize the virtual function table.
513 newObject->lpvtbl1 = &DataCache_IDataObject_VTable;
514 newObject->lpvtbl2 = &DataCache_NDIUnknown_VTable;
515 newObject->lpvtbl3 = &DataCache_IPersistStorage_VTable;
516 newObject->lpvtbl4 = &DataCache_IViewObject2_VTable;
517 newObject->lpvtbl5 = &DataCache_IOleCache2_VTable;
518 newObject->lpvtbl6 = &DataCache_IOleCacheControl_VTable;
521 * Start with one reference count. The caller of this function
522 * must release the interface pointer when it is done.
527 * Initialize the outer unknown
528 * We don't keep a reference on the outer unknown since, the way
529 * aggregation works, our lifetime is at least as large as it's
533 pUnkOuter = (IUnknown*)&(newObject->lpvtbl2);
535 newObject->outerUnknown = pUnkOuter;
538 * Initialize the other members of the structure.
540 newObject->presentationStorage = NULL;
541 newObject->sinkAspects = 0;
542 newObject->sinkAdviseFlag = 0;
543 newObject->sinkInterface = 0;
548 static void DataCache_Destroy(
549 DataCache* ptrToDestroy)
551 Print(MAX_TRACE, ("()\n"));
553 if (ptrToDestroy->sinkInterface != NULL)
555 IAdviseSink_Release(ptrToDestroy->sinkInterface);
556 ptrToDestroy->sinkInterface = NULL;
559 if (ptrToDestroy->presentationStorage != NULL)
561 IStorage_Release(ptrToDestroy->presentationStorage);
562 ptrToDestroy->presentationStorage = NULL;
566 * Free the datacache pointer.
568 HeapFree(GetProcessHeap(), 0, ptrToDestroy);
571 /************************************************************************
572 * DataCache_ReadPresentationData
574 * This method will read information for the requested presentation
575 * into the given structure.
578 * this - Pointer to the DataCache object
579 * drawAspect - The aspect of the object that we wish to draw.
580 * header - The structure containing information about this
581 * aspect of the object.
583 static HRESULT DataCache_ReadPresentationData(
586 PresentationDataHeader* header)
588 IStream* presStream = NULL;
592 * Open the presentation stream.
594 hres = DataCache_OpenPresStream(
609 sizeof(PresentationDataHeader),
615 IStream_Release(presStream);
618 * We don't want to propagate any other error
619 * code than a failure.
627 /************************************************************************
628 * DataCache_FireOnViewChange
630 * This method will fire an OnViewChange notification to the advise
631 * sink registered with the datacache.
633 * See IAdviseSink::OnViewChange for more details.
635 static void DataCache_FireOnViewChange(
640 Print(MAX_TRACE, ("(%p, %lx, %ld)\n", this, aspect, lindex));
643 * The sink supplies a filter when it registers
644 * we make sure we only send the notifications when that
647 if ((this->sinkAspects & aspect) != 0)
649 if (this->sinkInterface != NULL)
651 IAdviseSink_OnViewChange(this->sinkInterface,
656 * Some sinks want to be unregistered automatically when
657 * the first notification goes out.
659 if ( (this->sinkAdviseFlag & ADVF_ONLYONCE) != 0)
661 IAdviseSink_Release(this->sinkInterface);
663 this->sinkInterface = NULL;
664 this->sinkAspects = 0;
665 this->sinkAdviseFlag = 0;
671 /* Helper for DataCache_OpenPresStream */
672 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.u.LowPart >= sizeof(PresentationDataHeader))
683 && (lstrlenW(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');
694 /************************************************************************
695 * DataCache_OpenPresStream
697 * This method will find the stream for the given presentation. It makes
698 * no attempt at fallback.
701 * this - Pointer to the DataCache object
702 * drawAspect - The aspect of the object that we wish to draw.
703 * pStm - A returned stream. It points to the beginning of the
704 * - presentation data, including the header.
707 * S_OK The requested stream has been opened.
708 * OLE_E_BLANK The requested stream could not be found.
709 * Quite a few others I'm too lazy to map correctly.
712 * Algorithm: Scan the elements of the presentation storage, looking
713 * for presentation streams. For each presentation stream,
714 * load the header and check to see if the aspect maches.
716 * If a fallback is desired, just opening the first presentation stream
719 static HRESULT DataCache_OpenPresStream(
728 if (!ppStm) return E_POINTER;
730 hr = IStorage_EnumElements(this->presentationStorage, 0, NULL, 0, &pEnum);
731 if (FAILED(hr)) return hr;
733 while ((hr = IEnumSTATSTG_Next(pEnum, 1, &elem, NULL)) == S_OK)
735 if (DataCache_IsPresentationStream(&elem))
739 hr = IStorage_OpenStream(this->presentationStorage, elem.pwcsName,
740 NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0,
744 PresentationDataHeader header;
747 hr = IStream_Read(pStm, &header, sizeof(header), &actual_read);
749 /* can't use SUCCEEDED(hr): S_FALSE counts as an error */
750 if (hr == S_OK && actual_read == sizeof(header)
751 && header.dvAspect == drawAspect)
753 /* Rewind the stream before returning it. */
754 LARGE_INTEGER offset;
755 offset.u.LowPart = 0;
756 offset.u.HighPart = 0;
757 IStream_Seek(pStm, offset, STREAM_SEEK_SET, NULL);
761 CoTaskMemFree(elem.pwcsName);
762 IEnumSTATSTG_Release(pEnum);
767 IStream_Release(pStm);
771 CoTaskMemFree(elem.pwcsName);
774 IEnumSTATSTG_Release(pEnum);
776 return (hr == S_FALSE ? OLE_E_BLANK : hr);
779 /************************************************************************
780 * DataCache_ReadPresentationData
782 * This method will read information for the requested presentation
783 * into the given structure.
786 * this - Pointer to the DataCache object
787 * drawAspect - The aspect of the object that we wish to draw.
790 * This method returns a metafile handle if it is successful.
791 * it will return 0 if not.
793 static HMETAFILE DataCache_ReadPresMetafile(
797 LARGE_INTEGER offset;
798 IStream* presStream = NULL;
802 HMETAFILE newMetafile = 0;
805 * Open the presentation stream.
807 hres = DataCache_OpenPresStream(
816 * Get the size of the stream.
818 hres = IStream_Stat(presStream,
825 offset.u.HighPart = 0;
826 offset.u.LowPart = sizeof(PresentationDataHeader);
834 streamInfo.cbSize.u.LowPart -= offset.u.LowPart;
837 * Allocate a buffer for the metafile bits.
839 metafileBits = HeapAlloc(GetProcessHeap(),
841 streamInfo.cbSize.u.LowPart);
844 * Read the metafile bits.
849 streamInfo.cbSize.u.LowPart,
853 * Create a metafile with those bits.
857 newMetafile = SetMetaFileBitsEx(streamInfo.cbSize.u.LowPart, metafileBits);
863 HeapFree(GetProcessHeap(), 0, metafileBits);
864 IStream_Release(presStream);
872 /*********************************************************
873 * Method implementation for the non delegating IUnknown
874 * part of the DataCache class.
877 /************************************************************************
878 * DataCache_NDIUnknown_QueryInterface (IUnknown)
880 * See Windows documentation for more details on IUnknown methods.
882 * This version of QueryInterface will not delegate it's implementation
883 * to the outer unknown.
885 static HRESULT WINAPI DataCache_NDIUnknown_QueryInterface(
890 _ICOM_THIS_From_NDIUnknown(DataCache, iface);
893 * Perform a sanity check on the parameters.
895 if ( (this==0) || (ppvObject==0) )
899 * Initialize the return parameter.
904 * Compare the riid with the interface IDs implemented by this object.
906 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
910 else if (memcmp(&IID_IDataObject, riid, sizeof(IID_IDataObject)) == 0)
912 *ppvObject = (IDataObject*)&(this->lpvtbl1);
914 else if ( (memcmp(&IID_IPersistStorage, riid, sizeof(IID_IPersistStorage)) == 0) ||
915 (memcmp(&IID_IPersist, riid, sizeof(IID_IPersist)) == 0) )
917 *ppvObject = (IPersistStorage*)&(this->lpvtbl3);
919 else if ( (memcmp(&IID_IViewObject, riid, sizeof(IID_IViewObject)) == 0) ||
920 (memcmp(&IID_IViewObject2, riid, sizeof(IID_IViewObject2)) == 0) )
922 *ppvObject = (IViewObject2*)&(this->lpvtbl4);
924 else if ( (memcmp(&IID_IOleCache, riid, sizeof(IID_IOleCache)) == 0) ||
925 (memcmp(&IID_IOleCache2, riid, sizeof(IID_IOleCache2)) == 0) )
927 *ppvObject = (IOleCache2*)&(this->lpvtbl5);
929 else if (memcmp(&IID_IOleCacheControl, riid, sizeof(IID_IOleCacheControl)) == 0)
931 *ppvObject = (IOleCacheControl*)&(this->lpvtbl6);
935 * Check that we obtained an interface.
939 Print(MID_TRACE, ( "() : asking for unsupported interface %s\n", PRINT_GUID(riid)));
940 return E_NOINTERFACE;
944 * Query Interface always increases the reference count by one when it is
947 IUnknown_AddRef((IUnknown*)*ppvObject);
952 /************************************************************************
953 * DataCache_NDIUnknown_AddRef (IUnknown)
955 * See Windows documentation for more details on IUnknown methods.
957 * This version of QueryInterface will not delegate it's implementation
958 * to the outer unknown.
960 static ULONG WINAPI DataCache_NDIUnknown_AddRef(
963 _ICOM_THIS_From_NDIUnknown(DataCache, iface);
970 /************************************************************************
971 * DataCache_NDIUnknown_Release (IUnknown)
973 * See Windows documentation for more details on IUnknown methods.
975 * This version of QueryInterface will not delegate it's implementation
976 * to the outer unknown.
978 static ULONG WINAPI DataCache_NDIUnknown_Release(
981 _ICOM_THIS_From_NDIUnknown(DataCache, iface);
984 * Decrease the reference count on this object.
989 * If the reference count goes down to 0, perform suicide.
993 DataCache_Destroy(this);
1001 /*********************************************************
1002 * Method implementation for the IDataObject
1003 * part of the DataCache class.
1006 /************************************************************************
1007 * DataCache_IDataObject_QueryInterface (IUnknown)
1009 * See Windows documentation for more details on IUnknown methods.
1011 static HRESULT WINAPI DataCache_IDataObject_QueryInterface(
1016 _ICOM_THIS_From_IDataObject(DataCache, iface);
1018 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1021 /************************************************************************
1022 * DataCache_IDataObject_AddRef (IUnknown)
1024 * See Windows documentation for more details on IUnknown methods.
1026 static ULONG WINAPI DataCache_IDataObject_AddRef(
1029 _ICOM_THIS_From_IDataObject(DataCache, iface);
1031 return IUnknown_AddRef(this->outerUnknown);
1034 /************************************************************************
1035 * DataCache_IDataObject_Release (IUnknown)
1037 * See Windows documentation for more details on IUnknown methods.
1039 static ULONG WINAPI DataCache_IDataObject_Release(
1042 _ICOM_THIS_From_IDataObject(DataCache, iface);
1044 return IUnknown_Release(this->outerUnknown);
1047 /************************************************************************
1050 * Get Data from a source dataobject using format pformatetcIn->cfFormat
1051 * See Windows documentation for more details on GetData.
1052 * TODO: Currently only CF_METAFILEPICT is implemented
1054 static HRESULT WINAPI DataCache_GetData(
1056 LPFORMATETC pformatetcIn,
1060 HRESULT hrRet = E_UNEXPECTED;
1061 IPersistStorage *pPersistStorage = 0;
1062 IStorage *pStorage = 0;
1063 IStream *pStream = 0;
1064 OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
1065 HGLOBAL hGlobalMF = 0;
1067 PresentationDataHeader pdh;
1068 METAFILEPICT *mfPict;
1069 HMETAFILE hMetaFile = 0;
1071 if (pformatetcIn->cfFormat == CF_METAFILEPICT)
1073 /* Get the Persist Storage */
1075 hr = IDataObject_QueryInterface(iface, &IID_IPersistStorage, (void**)&pPersistStorage);
1080 /* Create a doc file to copy the doc to a storage */
1082 hr = StgCreateDocfile(NULL, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &pStorage);
1087 /* Save it to storage */
1089 hr = OleSave(pPersistStorage, pStorage, FALSE);
1091 Print(MIN_TRACE, ("OleSave() not found\n"));
1097 /* Open the Presentation data srteam */
1099 hr = IStorage_OpenStream(pStorage, name, 0, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &pStream);
1104 /* Read the presentation header */
1106 hr = IStream_Read(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
1111 mfBits = HeapAlloc(GetProcessHeap(), 0, pdh.dwSize);
1113 /* Read the Metafile bits */
1115 hr = IStream_Read(pStream, mfBits, pdh.dwSize, NULL);
1120 /* Create the metafile and place it in the STGMEDIUM structure */
1122 hMetaFile = SetMetaFileBitsEx(pdh.dwSize, mfBits);
1124 hGlobalMF = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, sizeof(METAFILEPICT));
1125 mfPict = (METAFILEPICT *)GlobalLock(hGlobalMF);
1127 mfPict->hMF = hMetaFile;
1129 Print(MIN_TRACE, ("Depending on MetaFile implementation\n"));
1132 GlobalUnlock(hGlobalMF);
1134 pmedium->u.hGlobal = hGlobalMF;
1135 pmedium->tymed = TYMED_MFPICT;
1141 HeapFree(GetProcessHeap(), 0, mfBits);
1144 IStream_Release(pStream);
1147 IStorage_Release(pStorage);
1149 if (pPersistStorage)
1150 IPersistStorage_Release(pPersistStorage);
1155 /* TODO: Other formats are not implemented */
1160 static HRESULT WINAPI DataCache_GetDataHere(
1162 LPFORMATETC pformatetc,
1169 static HRESULT WINAPI DataCache_QueryGetData(
1171 LPFORMATETC pformatetc)
1177 /************************************************************************
1178 * DataCache_EnumFormatEtc (IDataObject)
1180 * The data cache doesn't implement this method.
1182 * See Windows documentation for more details on IDataObject methods.
1184 static HRESULT WINAPI DataCache_GetCanonicalFormatEtc(
1186 LPFORMATETC pformatectIn,
1187 LPFORMATETC pformatetcOut)
1193 /************************************************************************
1194 * DataCache_IDataObject_SetData (IDataObject)
1196 * This method is delegated to the IOleCache2 implementation.
1198 * See Windows documentation for more details on IDataObject methods.
1200 static HRESULT WINAPI DataCache_IDataObject_SetData(
1202 LPFORMATETC pformatetc,
1206 IOleCache2* oleCache = NULL;
1209 Print(MAX_TRACE, ("(%p, %p, %p, %d)\n", iface, pformatetc, pmedium, fRelease));
1211 hres = IDataObject_QueryInterface(iface, &IID_IOleCache2, (void**)&oleCache);
1214 return E_UNEXPECTED;
1216 hres = IOleCache2_SetData(oleCache, pformatetc, pmedium, fRelease);
1218 IOleCache2_Release(oleCache);
1223 /************************************************************************
1224 * DataCache_EnumFormatEtc (IDataObject)
1226 * The data cache doesn't implement this method.
1228 * See Windows documentation for more details on IDataObject methods.
1230 static HRESULT WINAPI DataCache_EnumFormatEtc(
1233 IEnumFORMATETC** ppenumFormatEtc)
1239 /************************************************************************
1240 * DataCache_DAdvise (IDataObject)
1242 * The data cache doesn't support connections.
1244 * See Windows documentation for more details on IDataObject methods.
1246 static HRESULT WINAPI DataCache_DAdvise(
1248 FORMATETC* pformatetc,
1250 IAdviseSink* pAdvSink,
1251 DWORD* pdwConnection)
1254 return OLE_E_ADVISENOTSUPPORTED;
1257 /************************************************************************
1258 * DataCache_DUnadvise (IDataObject)
1260 * The data cache doesn't support connections.
1262 * See Windows documentation for more details on IDataObject methods.
1264 static HRESULT WINAPI DataCache_DUnadvise(
1269 return OLE_E_NOCONNECTION;
1272 /************************************************************************
1273 * DataCache_EnumDAdvise (IDataObject)
1275 * The data cache doesn't support connections.
1277 * See Windows documentation for more details on IDataObject methods.
1279 static HRESULT WINAPI DataCache_EnumDAdvise(
1281 IEnumSTATDATA** ppenumAdvise)
1284 return OLE_E_ADVISENOTSUPPORTED;
1287 /*********************************************************
1288 * Method implementation for the IDataObject
1289 * part of the DataCache class.
1292 /************************************************************************
1293 * DataCache_IPersistStorage_QueryInterface (IUnknown)
1295 * See Windows documentation for more details on IUnknown methods.
1297 static HRESULT WINAPI DataCache_IPersistStorage_QueryInterface(
1298 IPersistStorage* iface,
1302 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1304 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1307 /************************************************************************
1308 * DataCache_IPersistStorage_AddRef (IUnknown)
1310 * See Windows documentation for more details on IUnknown methods.
1312 static ULONG WINAPI DataCache_IPersistStorage_AddRef(
1313 IPersistStorage* iface)
1315 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1317 return IUnknown_AddRef(this->outerUnknown);
1320 /************************************************************************
1321 * DataCache_IPersistStorage_Release (IUnknown)
1323 * See Windows documentation for more details on IUnknown methods.
1325 static ULONG WINAPI DataCache_IPersistStorage_Release(
1326 IPersistStorage* iface)
1328 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1330 return IUnknown_Release(this->outerUnknown);
1333 /************************************************************************
1334 * DataCache_GetClassID (IPersistStorage)
1336 * The data cache doesn't implement this method.
1338 * See Windows documentation for more details on IPersistStorage methods.
1340 static HRESULT WINAPI DataCache_GetClassID(
1341 IPersistStorage* iface,
1344 Print(MAX_TRACE, ("(%p, %p)\n", iface, pClassID));
1348 /************************************************************************
1349 * DataCache_IsDirty (IPersistStorage)
1351 * Until we actully connect to a running object and retrieve new
1352 * information to it, we never get dirty.
1354 * See Windows documentation for more details on IPersistStorage methods.
1356 static HRESULT WINAPI DataCache_IsDirty(
1357 IPersistStorage* iface)
1359 Print(MAX_TRACE, ("(%p)\n", iface));
1364 /************************************************************************
1365 * DataCache_InitNew (IPersistStorage)
1367 * The data cache implementation of IPersistStorage_InitNew simply stores
1368 * the storage pointer.
1370 * See Windows documentation for more details on IPersistStorage methods.
1372 static HRESULT WINAPI DataCache_InitNew(
1373 IPersistStorage* iface,
1376 Print(MAX_TRACE, ("(%p, %p)\n", iface, pStg));
1378 return DataCache_Load(iface, pStg);
1381 /************************************************************************
1382 * DataCache_Load (IPersistStorage)
1384 * The data cache implementation of IPersistStorage_Load doesn't
1385 * actually load anything. Instead, it holds on to the storage pointer
1386 * and it will load the presentation information when the
1387 * IDataObject_GetData or IViewObject2_Draw methods are called.
1389 * See Windows documentation for more details on IPersistStorage methods.
1391 static HRESULT WINAPI DataCache_Load(
1392 IPersistStorage* iface,
1395 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1397 Print(MAX_TRACE, ("(%p, %p)\n", iface, pStg));
1399 if (this->presentationStorage != NULL)
1401 IStorage_Release(this->presentationStorage);
1404 this->presentationStorage = pStg;
1406 if (this->presentationStorage != NULL)
1408 IStorage_AddRef(this->presentationStorage);
1413 /************************************************************************
1414 * DataCache_Save (IPersistStorage)
1416 * Until we actully connect to a running object and retrieve new
1417 * information to it, we never have to save anything. However, it is
1418 * our responsability to copy the information when saving to a new
1421 * See Windows documentation for more details on IPersistStorage methods.
1423 static HRESULT WINAPI DataCache_Save(
1424 IPersistStorage* iface,
1428 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1430 Print(MAX_TRACE, ("(%p, %p, %d)\n", iface, pStg, fSameAsLoad));
1432 if ( (!fSameAsLoad) &&
1433 (this->presentationStorage!=NULL) )
1435 return IStorage_CopyTo(this->presentationStorage,
1445 /************************************************************************
1446 * DataCache_SaveCompleted (IPersistStorage)
1448 * This method is called to tell the cache to release the storage
1449 * pointer it's currentlu holding.
1451 * See Windows documentation for more details on IPersistStorage methods.
1453 static HRESULT WINAPI DataCache_SaveCompleted(
1454 IPersistStorage* iface,
1457 Print(MAX_TRACE, ("(%p, %p)\n", iface, pStgNew));
1462 * First, make sure we get our hands off any storage we have.
1465 DataCache_HandsOffStorage(iface);
1468 * Then, attach to the new storage.
1471 DataCache_Load(iface, pStgNew);
1477 /************************************************************************
1478 * DataCache_HandsOffStorage (IPersistStorage)
1480 * This method is called to tell the cache to release the storage
1481 * pointer it's currentlu holding.
1483 * See Windows documentation for more details on IPersistStorage methods.
1485 static HRESULT WINAPI DataCache_HandsOffStorage(
1486 IPersistStorage* iface)
1488 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1490 Print(MAX_TRACE, ("(%p)\n", iface));
1492 if (this->presentationStorage != NULL)
1494 IStorage_Release(this->presentationStorage);
1495 this->presentationStorage = NULL;
1501 /*********************************************************
1502 * Method implementation for the IViewObject2
1503 * part of the DataCache class.
1506 /************************************************************************
1507 * DataCache_IViewObject2_QueryInterface (IUnknown)
1509 * See Windows documentation for more details on IUnknown methods.
1511 static HRESULT WINAPI DataCache_IViewObject2_QueryInterface(
1512 IViewObject2* iface,
1516 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1518 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1521 /************************************************************************
1522 * DataCache_IViewObject2_AddRef (IUnknown)
1524 * See Windows documentation for more details on IUnknown methods.
1526 static ULONG WINAPI DataCache_IViewObject2_AddRef(
1527 IViewObject2* iface)
1529 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1531 return IUnknown_AddRef(this->outerUnknown);
1534 /************************************************************************
1535 * DataCache_IViewObject2_Release (IUnknown)
1537 * See Windows documentation for more details on IUnknown methods.
1539 static ULONG WINAPI DataCache_IViewObject2_Release(
1540 IViewObject2* iface)
1542 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1544 return IUnknown_Release(this->outerUnknown);
1547 /************************************************************************
1548 * DataCache_Draw (IViewObject2)
1550 * This method will draw the cached representation of the object
1551 * to the given device context.
1553 * See Windows documentation for more details on IViewObject2 methods.
1555 static HRESULT WINAPI DataCache_Draw(
1556 IViewObject2* iface,
1560 DVTARGETDEVICE* ptd,
1563 LPCRECTL lprcBounds,
1564 LPCRECTL lprcWBounds,
1565 IVO_ContCallback pfnContinue,
1568 PresentationDataHeader presData;
1569 HMETAFILE presMetafile = 0;
1572 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1574 Print(MAX_TRACE, ("(%p, %lx, %ld, %p, %x, %x, %p, %p, %p, %lx)\n",
1589 if (lprcBounds==NULL)
1590 return E_INVALIDARG;
1593 * First, we need to retrieve the dimensions of the
1594 * image in the metafile.
1596 hres = DataCache_ReadPresentationData(this,
1604 * Then, we can extract the metafile itself from the cached
1607 * FIXME Unless it isn't a metafile. I think it could be any CF_XXX type,
1608 * particularly CF_DIB.
1610 presMetafile = DataCache_ReadPresMetafile(this,
1614 * If we have a metafile, just draw baby...
1615 * We have to be careful not to modify the state of the
1618 if (presMetafile!=0)
1620 INT prevMapMode = SetMapMode(hdcDraw, MM_ANISOTROPIC);
1622 SIZE oldViewportExt;
1623 POINT oldViewportOrg;
1625 SetWindowExtEx(hdcDraw,
1626 presData.dwObjectExtentX,
1627 presData.dwObjectExtentY,
1630 SetViewportExtEx(hdcDraw,
1631 lprcBounds->right - lprcBounds->left,
1632 lprcBounds->bottom - lprcBounds->top,
1635 SetViewportOrgEx(hdcDraw,
1640 PlayMetaFile(hdcDraw, presMetafile);
1642 SetWindowExtEx(hdcDraw,
1647 SetViewportExtEx(hdcDraw,
1652 SetViewportOrgEx(hdcDraw,
1657 SetMapMode(hdcDraw, prevMapMode);
1659 DeleteMetaFile(presMetafile);
1665 static HRESULT WINAPI DataCache_GetColorSet(
1666 IViewObject2* iface,
1670 DVTARGETDEVICE* ptd,
1671 HDC hicTargetDevice,
1672 LOGPALETTE** ppColorSet)
1678 static HRESULT WINAPI DataCache_Freeze(
1679 IViewObject2* iface,
1689 static HRESULT WINAPI DataCache_Unfreeze(
1690 IViewObject2* iface,
1697 /************************************************************************
1698 * DataCache_SetAdvise (IViewObject2)
1700 * This sets-up an advisory sink with the data cache. When the object's
1701 * view changes, this sink is called.
1703 * See Windows documentation for more details on IViewObject2 methods.
1705 static HRESULT WINAPI DataCache_SetAdvise(
1706 IViewObject2* iface,
1709 IAdviseSink* pAdvSink)
1711 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1713 Print(MAX_TRACE, ("(%p, %lx, %lx, %p)\n", iface, aspects, advf, pAdvSink));
1716 * A call to this function removes the previous sink
1718 if (this->sinkInterface != NULL)
1720 IAdviseSink_Release(this->sinkInterface);
1721 this->sinkInterface = NULL;
1722 this->sinkAspects = 0;
1723 this->sinkAdviseFlag = 0;
1727 * Now, setup the new one.
1731 this->sinkInterface = pAdvSink;
1732 this->sinkAspects = aspects;
1733 this->sinkAdviseFlag = advf;
1735 IAdviseSink_AddRef(this->sinkInterface);
1739 * When the ADVF_PRIMEFIRST flag is set, we have to advise the
1742 if (advf & ADVF_PRIMEFIRST)
1744 DataCache_FireOnViewChange(this,
1752 /************************************************************************
1753 * DataCache_GetAdvise (IViewObject2)
1755 * This method queries the current state of the advise sink
1756 * installed on the data cache.
1758 * See Windows documentation for more details on IViewObject2 methods.
1760 static HRESULT WINAPI DataCache_GetAdvise(
1761 IViewObject2* iface,
1764 IAdviseSink** ppAdvSink)
1766 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1768 Print(MAX_TRACE, ("(%p, %p, %p, %p)\n", iface, pAspects, pAdvf, ppAdvSink));
1771 * Just copy all the requested values.
1774 *pAspects = this->sinkAspects;
1777 *pAdvf = this->sinkAdviseFlag;
1779 if (ppAdvSink!=NULL)
1781 IAdviseSink_QueryInterface(this->sinkInterface,
1789 /************************************************************************
1790 * DataCache_GetExtent (IViewObject2)
1792 * This method retrieves the "natural" size of this cached object.
1794 * See Windows documentation for more details on IViewObject2 methods.
1796 static HRESULT WINAPI DataCache_GetExtent(
1797 IViewObject2* iface,
1800 DVTARGETDEVICE* ptd,
1803 PresentationDataHeader presData;
1804 HRESULT hres = E_FAIL;
1806 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1808 Print(MAX_TRACE, ("(%p, %lx, %ld, %p, %p)\n",
1809 iface, dwDrawAspect, lindex, ptd, lpsizel));
1818 * Initialize the out parameter.
1824 * This flag should be set to -1.
1827 Print(MIN_TRACE, ("Unimplemented flag lindex = %ld\n", lindex));
1830 * Right now, we suport only the callback from
1831 * the default handler.
1834 Print(MIN_TRACE, ("Unimplemented ptd = %p\n", ptd));
1837 * Get the presentation information from the
1840 hres = DataCache_ReadPresentationData(this,
1844 if (SUCCEEDED(hres))
1846 lpsizel->cx = presData.dwObjectExtentX;
1847 lpsizel->cy = presData.dwObjectExtentY;
1851 * This method returns OLE_E_BLANK when it fails.
1860 /*********************************************************
1861 * Method implementation for the IOleCache2
1862 * part of the DataCache class.
1865 /************************************************************************
1866 * DataCache_IOleCache2_QueryInterface (IUnknown)
1868 * See Windows documentation for more details on IUnknown methods.
1870 static HRESULT WINAPI DataCache_IOleCache2_QueryInterface(
1875 _ICOM_THIS_From_IOleCache2(DataCache, iface);
1877 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1880 /************************************************************************
1881 * DataCache_IOleCache2_AddRef (IUnknown)
1883 * See Windows documentation for more details on IUnknown methods.
1885 static ULONG WINAPI DataCache_IOleCache2_AddRef(
1888 _ICOM_THIS_From_IOleCache2(DataCache, iface);
1890 return IUnknown_AddRef(this->outerUnknown);
1893 /************************************************************************
1894 * DataCache_IOleCache2_Release (IUnknown)
1896 * See Windows documentation for more details on IUnknown methods.
1898 static ULONG WINAPI DataCache_IOleCache2_Release(
1901 _ICOM_THIS_From_IOleCache2(DataCache, iface);
1903 return IUnknown_Release(this->outerUnknown);
1906 static HRESULT WINAPI DataCache_Cache(
1908 FORMATETC* pformatetc,
1910 DWORD* pdwConnection)
1916 static HRESULT WINAPI DataCache_Uncache(
1924 static HRESULT WINAPI DataCache_EnumCache(
1926 IEnumSTATDATA** ppenumSTATDATA)
1932 static HRESULT WINAPI DataCache_InitCache(
1934 IDataObject* pDataObject)
1940 static HRESULT WINAPI DataCache_IOleCache2_SetData(
1942 FORMATETC* pformatetc,
1950 static HRESULT WINAPI DataCache_UpdateCache(
1952 LPDATAOBJECT pDataObject,
1960 static HRESULT WINAPI DataCache_DiscardCache(
1962 DWORD dwDiscardOptions)
1969 /*********************************************************
1970 * Method implementation for the IOleCacheControl
1971 * part of the DataCache class.
1974 /************************************************************************
1975 * DataCache_IOleCacheControl_QueryInterface (IUnknown)
1977 * See Windows documentation for more details on IUnknown methods.
1979 static HRESULT WINAPI DataCache_IOleCacheControl_QueryInterface(
1980 IOleCacheControl* iface,
1984 _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
1986 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1989 /************************************************************************
1990 * DataCache_IOleCacheControl_AddRef (IUnknown)
1992 * See Windows documentation for more details on IUnknown methods.
1994 static ULONG WINAPI DataCache_IOleCacheControl_AddRef(
1995 IOleCacheControl* iface)
1997 _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
1999 return IUnknown_AddRef(this->outerUnknown);
2002 /************************************************************************
2003 * DataCache_IOleCacheControl_Release (IUnknown)
2005 * See Windows documentation for more details on IUnknown methods.
2007 static ULONG WINAPI DataCache_IOleCacheControl_Release(
2008 IOleCacheControl* iface)
2010 _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
2012 return IUnknown_Release(this->outerUnknown);
2015 static HRESULT WINAPI DataCache_OnRun(
2016 IOleCacheControl* iface,
2017 LPDATAOBJECT pDataObject)
2023 static HRESULT WINAPI DataCache_OnStop(
2024 IOleCacheControl* iface)