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.
39 #include "wine/obj_base.h"
40 #include "wine/obj_misc.h"
41 #include "wine/obj_storage.h"
42 #include "wine/obj_moniker.h"
43 #include "wine/obj_dataobject.h"
44 #include "wine/obj_oleview.h"
45 #include "wine/obj_cache.h"
46 #include "wine/unicode.h"
48 #include "debugtools.h"
50 DEFAULT_DEBUG_CHANNEL(ole);
52 /****************************************************************************
53 * PresentationDataHeader
55 * This structure represents the header of the \002OlePresXXX stream in
56 * the OLE object strorage.
58 * Most fields are still unknown.
60 typedef struct PresentationDataHeader
62 DWORD unknown1; /* -1 */
63 DWORD unknown2; /* 3, possibly CF_METAFILEPICT */
64 DWORD unknown3; /* 4, possibly TYMED_ISTREAM */
66 DWORD unknown5; /* -1 */
69 DWORD unknown7; /* 0 */
70 DWORD dwObjectExtentX;
71 DWORD dwObjectExtentY;
73 } PresentationDataHeader;
75 /****************************************************************************
81 * List all interface VTables here
83 ICOM_VTABLE(IDataObject)* lpvtbl1;
84 ICOM_VTABLE(IUnknown)* lpvtbl2;
85 ICOM_VTABLE(IPersistStorage)* lpvtbl3;
86 ICOM_VTABLE(IViewObject2)* lpvtbl4;
87 ICOM_VTABLE(IOleCache2)* lpvtbl5;
88 ICOM_VTABLE(IOleCacheControl)* lpvtbl6;
91 * Reference count of this object
96 * IUnknown implementation of the outer object.
98 IUnknown* outerUnknown;
101 * This storage pointer is set through a call to
102 * IPersistStorage_Load. This is where the visual
103 * representation of the object is stored.
105 IStorage* presentationStorage;
108 * The user of this object can setup ONE advise sink
109 * connection with the object. These parameters describe
113 DWORD sinkAdviseFlag;
114 IAdviseSink* sinkInterface;
118 typedef struct DataCache DataCache;
121 * Here, I define utility macros to help with the casting of the
123 * There is a version to accomodate all of the VTables implemented
126 #define _ICOM_THIS_From_IDataObject(class,name) class* this = (class*)name;
127 #define _ICOM_THIS_From_NDIUnknown(class, name) class* this = (class*)(((char*)name)-sizeof(void*));
128 #define _ICOM_THIS_From_IPersistStorage(class, name) class* this = (class*)(((char*)name)-2*sizeof(void*));
129 #define _ICOM_THIS_From_IViewObject2(class, name) class* this = (class*)(((char*)name)-3*sizeof(void*));
130 #define _ICOM_THIS_From_IOleCache2(class, name) class* this = (class*)(((char*)name)-4*sizeof(void*));
131 #define _ICOM_THIS_From_IOleCacheControl(class, name) class* this = (class*)(((char*)name)-5*sizeof(void*));
134 * Prototypes for the methods of the DataCache class.
136 static DataCache* DataCache_Construct(REFCLSID clsid,
137 LPUNKNOWN pUnkOuter);
138 static void DataCache_Destroy(DataCache* ptrToDestroy);
139 static HRESULT DataCache_ReadPresentationData(DataCache* this,
141 PresentationDataHeader* header);
142 static HRESULT DataCache_OpenPresStream(DataCache *this,
145 static HMETAFILE DataCache_ReadPresMetafile(DataCache* this,
147 static void DataCache_FireOnViewChange(DataCache* this,
152 * Prototypes for the methods of the DataCache class
153 * that implement non delegating IUnknown methods.
155 static HRESULT WINAPI DataCache_NDIUnknown_QueryInterface(
159 static ULONG WINAPI DataCache_NDIUnknown_AddRef(
161 static ULONG WINAPI DataCache_NDIUnknown_Release(
165 * Prototypes for the methods of the DataCache class
166 * that implement IDataObject methods.
168 static HRESULT WINAPI DataCache_IDataObject_QueryInterface(
172 static ULONG WINAPI DataCache_IDataObject_AddRef(
174 static ULONG WINAPI DataCache_IDataObject_Release(
176 static HRESULT WINAPI DataCache_GetData(
178 LPFORMATETC pformatetcIn,
180 static HRESULT WINAPI DataCache_GetDataHere(
182 LPFORMATETC pformatetc,
184 static HRESULT WINAPI DataCache_QueryGetData(
186 LPFORMATETC pformatetc);
187 static HRESULT WINAPI DataCache_GetCanonicalFormatEtc(
189 LPFORMATETC pformatectIn,
190 LPFORMATETC pformatetcOut);
191 static HRESULT WINAPI DataCache_IDataObject_SetData(
193 LPFORMATETC pformatetc,
196 static HRESULT WINAPI DataCache_EnumFormatEtc(
199 IEnumFORMATETC** ppenumFormatEtc);
200 static HRESULT WINAPI DataCache_DAdvise(
202 FORMATETC* pformatetc,
204 IAdviseSink* pAdvSink,
205 DWORD* pdwConnection);
206 static HRESULT WINAPI DataCache_DUnadvise(
209 static HRESULT WINAPI DataCache_EnumDAdvise(
211 IEnumSTATDATA** ppenumAdvise);
214 * Prototypes for the methods of the DataCache class
215 * that implement IPersistStorage methods.
217 static HRESULT WINAPI DataCache_IPersistStorage_QueryInterface(
218 IPersistStorage* iface,
221 static ULONG WINAPI DataCache_IPersistStorage_AddRef(
222 IPersistStorage* iface);
223 static ULONG WINAPI DataCache_IPersistStorage_Release(
224 IPersistStorage* iface);
225 static HRESULT WINAPI DataCache_GetClassID(
226 IPersistStorage* iface,
228 static HRESULT WINAPI DataCache_IsDirty(
229 IPersistStorage* iface);
230 static HRESULT WINAPI DataCache_InitNew(
231 IPersistStorage* iface,
233 static HRESULT WINAPI DataCache_Load(
234 IPersistStorage* iface,
236 static HRESULT WINAPI DataCache_Save(
237 IPersistStorage* iface,
240 static HRESULT WINAPI DataCache_SaveCompleted(
241 IPersistStorage* iface,
243 static HRESULT WINAPI DataCache_HandsOffStorage(
244 IPersistStorage* iface);
247 * Prototypes for the methods of the DataCache class
248 * that implement IViewObject2 methods.
250 static HRESULT WINAPI DataCache_IViewObject2_QueryInterface(
254 static ULONG WINAPI DataCache_IViewObject2_AddRef(
255 IViewObject2* iface);
256 static ULONG WINAPI DataCache_IViewObject2_Release(
257 IViewObject2* iface);
258 static HRESULT WINAPI DataCache_Draw(
267 LPCRECTL lprcWBounds,
268 IVO_ContCallback pfnContinue,
270 static HRESULT WINAPI DataCache_GetColorSet(
277 LOGPALETTE** ppColorSet);
278 static HRESULT WINAPI DataCache_Freeze(
284 static HRESULT WINAPI DataCache_Unfreeze(
287 static HRESULT WINAPI DataCache_SetAdvise(
291 IAdviseSink* pAdvSink);
292 static HRESULT WINAPI DataCache_GetAdvise(
296 IAdviseSink** ppAdvSink);
297 static HRESULT WINAPI DataCache_GetExtent(
305 * Prototypes for the methods of the DataCache class
306 * that implement IOleCache2 methods.
308 static HRESULT WINAPI DataCache_IOleCache2_QueryInterface(
312 static ULONG WINAPI DataCache_IOleCache2_AddRef(
314 static ULONG WINAPI DataCache_IOleCache2_Release(
316 static HRESULT WINAPI DataCache_Cache(
318 FORMATETC* pformatetc,
320 DWORD* pdwConnection);
321 static HRESULT WINAPI DataCache_Uncache(
324 static HRESULT WINAPI DataCache_EnumCache(
326 IEnumSTATDATA** ppenumSTATDATA);
327 static HRESULT WINAPI DataCache_InitCache(
329 IDataObject* pDataObject);
330 static HRESULT WINAPI DataCache_IOleCache2_SetData(
332 FORMATETC* pformatetc,
335 static HRESULT WINAPI DataCache_UpdateCache(
337 LPDATAOBJECT pDataObject,
340 static HRESULT WINAPI DataCache_DiscardCache(
342 DWORD dwDiscardOptions);
345 * Prototypes for the methods of the DataCache class
346 * that implement IOleCacheControl methods.
348 static HRESULT WINAPI DataCache_IOleCacheControl_QueryInterface(
349 IOleCacheControl* iface,
352 static ULONG WINAPI DataCache_IOleCacheControl_AddRef(
353 IOleCacheControl* iface);
354 static ULONG WINAPI DataCache_IOleCacheControl_Release(
355 IOleCacheControl* iface);
356 static HRESULT WINAPI DataCache_OnRun(
357 IOleCacheControl* iface,
358 LPDATAOBJECT pDataObject);
359 static HRESULT WINAPI DataCache_OnStop(
360 IOleCacheControl* iface);
363 * Virtual function tables for the DataCache class.
365 static ICOM_VTABLE(IUnknown) DataCache_NDIUnknown_VTable =
367 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
368 DataCache_NDIUnknown_QueryInterface,
369 DataCache_NDIUnknown_AddRef,
370 DataCache_NDIUnknown_Release
373 static ICOM_VTABLE(IDataObject) DataCache_IDataObject_VTable =
375 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
376 DataCache_IDataObject_QueryInterface,
377 DataCache_IDataObject_AddRef,
378 DataCache_IDataObject_Release,
380 DataCache_GetDataHere,
381 DataCache_QueryGetData,
382 DataCache_GetCanonicalFormatEtc,
383 DataCache_IDataObject_SetData,
384 DataCache_EnumFormatEtc,
387 DataCache_EnumDAdvise
390 static ICOM_VTABLE(IPersistStorage) DataCache_IPersistStorage_VTable =
392 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
393 DataCache_IPersistStorage_QueryInterface,
394 DataCache_IPersistStorage_AddRef,
395 DataCache_IPersistStorage_Release,
396 DataCache_GetClassID,
401 DataCache_SaveCompleted,
402 DataCache_HandsOffStorage
405 static ICOM_VTABLE(IViewObject2) DataCache_IViewObject2_VTable =
407 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
408 DataCache_IViewObject2_QueryInterface,
409 DataCache_IViewObject2_AddRef,
410 DataCache_IViewObject2_Release,
412 DataCache_GetColorSet,
420 static ICOM_VTABLE(IOleCache2) DataCache_IOleCache2_VTable =
422 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
423 DataCache_IOleCache2_QueryInterface,
424 DataCache_IOleCache2_AddRef,
425 DataCache_IOleCache2_Release,
430 DataCache_IOleCache2_SetData,
431 DataCache_UpdateCache,
432 DataCache_DiscardCache
435 static ICOM_VTABLE(IOleCacheControl) DataCache_IOleCacheControl_VTable =
437 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
438 DataCache_IOleCacheControl_QueryInterface,
439 DataCache_IOleCacheControl_AddRef,
440 DataCache_IOleCacheControl_Release,
445 /******************************************************************************
446 * CreateDataCache [OLE32.54]
448 HRESULT WINAPI CreateDataCache(
454 DataCache* newCache = NULL;
457 TRACE("(%s, %p, %s, %p)\n", debugstr_guid(rclsid), pUnkOuter, debugstr_guid(riid), ppvObj);
468 * If this cache is constructed for aggregation, make sure
469 * the caller is requesting the IUnknown interface.
470 * This is necessary because it's the only time the non-delegating
471 * IUnknown pointer can be returned to the outside.
473 if ( (pUnkOuter!=NULL) &&
474 (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) != 0) )
475 return CLASS_E_NOAGGREGATION;
478 * Try to construct a new instance of the class.
480 newCache = DataCache_Construct(rclsid,
484 return E_OUTOFMEMORY;
487 * Make sure it supports the interface required by the caller.
489 hr = IUnknown_QueryInterface((IUnknown*)&(newCache->lpvtbl2), riid, ppvObj);
492 * Release the reference obtained in the constructor. If
493 * the QueryInterface was unsuccessful, it will free the class.
495 IUnknown_Release((IUnknown*)&(newCache->lpvtbl2));
500 /*********************************************************
501 * Method implementation for DataCache class.
503 static DataCache* DataCache_Construct(
507 DataCache* newObject = 0;
510 * Allocate space for the object.
512 newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(DataCache));
518 * Initialize the virtual function table.
520 newObject->lpvtbl1 = &DataCache_IDataObject_VTable;
521 newObject->lpvtbl2 = &DataCache_NDIUnknown_VTable;
522 newObject->lpvtbl3 = &DataCache_IPersistStorage_VTable;
523 newObject->lpvtbl4 = &DataCache_IViewObject2_VTable;
524 newObject->lpvtbl5 = &DataCache_IOleCache2_VTable;
525 newObject->lpvtbl6 = &DataCache_IOleCacheControl_VTable;
528 * Start with one reference count. The caller of this function
529 * must release the interface pointer when it is done.
534 * Initialize the outer unknown
535 * We don't keep a reference on the outer unknown since, the way
536 * aggregation works, our lifetime is at least as large as it's
540 pUnkOuter = (IUnknown*)&(newObject->lpvtbl2);
542 newObject->outerUnknown = pUnkOuter;
545 * Initialize the other members of the structure.
547 newObject->presentationStorage = NULL;
548 newObject->sinkAspects = 0;
549 newObject->sinkAdviseFlag = 0;
550 newObject->sinkInterface = 0;
555 static void DataCache_Destroy(
556 DataCache* ptrToDestroy)
560 if (ptrToDestroy->sinkInterface != NULL)
562 IAdviseSink_Release(ptrToDestroy->sinkInterface);
563 ptrToDestroy->sinkInterface = NULL;
566 if (ptrToDestroy->presentationStorage != NULL)
568 IStorage_Release(ptrToDestroy->presentationStorage);
569 ptrToDestroy->presentationStorage = NULL;
573 * Free the datacache pointer.
575 HeapFree(GetProcessHeap(), 0, ptrToDestroy);
578 /************************************************************************
579 * DataCache_ReadPresentationData
581 * This method will read information for the requested presentation
582 * into the given structure.
585 * this - Pointer to the DataCache object
586 * drawAspect - The aspect of the object that we wish to draw.
587 * header - The structure containing information about this
588 * aspect of the object.
590 static HRESULT DataCache_ReadPresentationData(
593 PresentationDataHeader* header)
595 IStream* presStream = NULL;
599 * Open the presentation stream.
601 hres = DataCache_OpenPresStream(
616 sizeof(PresentationDataHeader),
622 IStream_Release(presStream);
625 * We don't want to propagate any other error
626 * code than a failure.
634 /************************************************************************
635 * DataCache_FireOnViewChange
637 * This method will fire an OnViewChange notification to the advise
638 * sink registered with the datacache.
640 * See IAdviseSink::OnViewChange for more details.
642 static void DataCache_FireOnViewChange(
647 TRACE("(%p, %lx, %ld)\n", this, aspect, lindex);
650 * The sink supplies a filter when it registers
651 * we make sure we only send the notifications when that
654 if ((this->sinkAspects & aspect) != 0)
656 if (this->sinkInterface != NULL)
658 IAdviseSink_OnViewChange(this->sinkInterface,
663 * Some sinks want to be unregistered automatically when
664 * the first notification goes out.
666 if ( (this->sinkAdviseFlag & ADVF_ONLYONCE) != 0)
668 IAdviseSink_Release(this->sinkInterface);
670 this->sinkInterface = NULL;
671 this->sinkAspects = 0;
672 this->sinkAdviseFlag = 0;
678 /* Helper for DataCache_OpenPresStream */
679 static BOOL DataCache_IsPresentationStream(const STATSTG *elem)
681 /* The presentation streams have names of the form "\002OlePresXXX",
682 * where XXX goes from 000 to 999. */
683 static const WCHAR OlePres[] = { 2,'O','l','e','P','r','e','s' };
685 LPCWSTR name = elem->pwcsName;
687 return (elem->type == STGTY_STREAM)
688 && (elem->cbSize.s.LowPart >= sizeof(PresentationDataHeader))
689 && (strlenW(name) == 11)
690 && (strncmpW(name, OlePres, 8) == 0)
691 && (name[8] >= '0') && (name[8] <= '9')
692 && (name[9] >= '0') && (name[9] <= '9')
693 && (name[10] >= '0') && (name[10] <= '9');
696 /************************************************************************
697 * DataCache_OpenPresStream
699 * This method will find the stream for the given presentation. It makes
700 * no attempt at fallback.
703 * this - Pointer to the DataCache object
704 * drawAspect - The aspect of the object that we wish to draw.
705 * pStm - A returned stream. It points to the beginning of the
706 * - presentation data, including the header.
709 * S_OK The requested stream has been opened.
710 * OLE_E_BLANK The requested stream could not be found.
711 * Quite a few others I'm too lazy to map correctly.
714 * Algorithm: Scan the elements of the presentation storage, looking
715 * for presentation streams. For each presentation stream,
716 * load the header and check to see if the aspect maches.
718 * If a fallback is desired, just opening the first presentation stream
721 static HRESULT DataCache_OpenPresStream(
730 if (!ppStm) return E_POINTER;
732 hr = IStorage_EnumElements(this->presentationStorage, 0, NULL, 0, &pEnum);
733 if (FAILED(hr)) return hr;
735 while ((hr = IEnumSTATSTG_Next(pEnum, 1, &elem, NULL)) == S_OK)
737 if (DataCache_IsPresentationStream(&elem))
741 hr = IStorage_OpenStream(this->presentationStorage, elem.pwcsName,
742 NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0,
746 PresentationDataHeader header;
749 hr = IStream_Read(pStm, &header, sizeof(header), &actual_read);
751 /* can't use SUCCEEDED(hr): S_FALSE counts as an error */
752 if (hr == S_OK && actual_read == sizeof(header)
753 && header.dvAspect == drawAspect)
755 /* Rewind the stream before returning it. */
756 LARGE_INTEGER offset;
757 offset.s.LowPart = 0;
758 offset.s.HighPart = 0;
759 IStream_Seek(pStm, offset, STREAM_SEEK_SET, NULL);
763 CoTaskMemFree(elem.pwcsName);
764 IEnumSTATSTG_Release(pEnum);
769 IStream_Release(pStm);
773 CoTaskMemFree(elem.pwcsName);
776 IEnumSTATSTG_Release(pEnum);
778 return (hr == S_FALSE ? OLE_E_BLANK : hr);
781 /************************************************************************
782 * DataCache_ReadPresentationData
784 * This method will read information for the requested presentation
785 * into the given structure.
788 * this - Pointer to the DataCache object
789 * drawAspect - The aspect of the object that we wish to draw.
792 * This method returns a metafile handle if it is successful.
793 * it will return 0 if not.
795 static HMETAFILE DataCache_ReadPresMetafile(
799 LARGE_INTEGER offset;
800 IStream* presStream = NULL;
804 HMETAFILE newMetafile = 0;
807 * Open the presentation stream.
809 hres = DataCache_OpenPresStream(
818 * Get the size of the stream.
820 hres = IStream_Stat(presStream,
827 offset.s.HighPart = 0;
828 offset.s.LowPart = sizeof(PresentationDataHeader);
836 streamInfo.cbSize.s.LowPart -= offset.s.LowPart;
839 * Allocate a buffer for the metafile bits.
841 metafileBits = HeapAlloc(GetProcessHeap(),
843 streamInfo.cbSize.s.LowPart);
846 * Read the metafile bits.
851 streamInfo.cbSize.s.LowPart,
855 * Create a metafile with those bits.
859 newMetafile = SetMetaFileBitsEx(streamInfo.cbSize.s.LowPart, metafileBits);
865 HeapFree(GetProcessHeap(), 0, metafileBits);
866 IStream_Release(presStream);
874 /*********************************************************
875 * Method implementation for the non delegating IUnknown
876 * part of the DataCache class.
879 /************************************************************************
880 * DataCache_NDIUnknown_QueryInterface (IUnknown)
882 * See Windows documentation for more details on IUnknown methods.
884 * This version of QueryInterface will not delegate it's implementation
885 * to the outer unknown.
887 static HRESULT WINAPI DataCache_NDIUnknown_QueryInterface(
892 _ICOM_THIS_From_NDIUnknown(DataCache, iface);
895 * Perform a sanity check on the parameters.
897 if ( (this==0) || (ppvObject==0) )
901 * Initialize the return parameter.
906 * Compare the riid with the interface IDs implemented by this object.
908 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
912 else if (memcmp(&IID_IDataObject, riid, sizeof(IID_IDataObject)) == 0)
914 *ppvObject = (IDataObject*)&(this->lpvtbl1);
916 else if ( (memcmp(&IID_IPersistStorage, riid, sizeof(IID_IPersistStorage)) == 0) ||
917 (memcmp(&IID_IPersist, riid, sizeof(IID_IPersist)) == 0) )
919 *ppvObject = (IPersistStorage*)&(this->lpvtbl3);
921 else if ( (memcmp(&IID_IViewObject, riid, sizeof(IID_IViewObject)) == 0) ||
922 (memcmp(&IID_IViewObject2, riid, sizeof(IID_IViewObject2)) == 0) )
924 *ppvObject = (IViewObject2*)&(this->lpvtbl4);
926 else if ( (memcmp(&IID_IOleCache, riid, sizeof(IID_IOleCache)) == 0) ||
927 (memcmp(&IID_IOleCache2, riid, sizeof(IID_IOleCache2)) == 0) )
929 *ppvObject = (IOleCache2*)&(this->lpvtbl5);
931 else if (memcmp(&IID_IOleCacheControl, riid, sizeof(IID_IOleCacheControl)) == 0)
933 *ppvObject = (IOleCacheControl*)&(this->lpvtbl6);
937 * Check that we obtained an interface.
941 WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid));
942 return E_NOINTERFACE;
946 * Query Interface always increases the reference count by one when it is
949 IUnknown_AddRef((IUnknown*)*ppvObject);
954 /************************************************************************
955 * DataCache_NDIUnknown_AddRef (IUnknown)
957 * See Windows documentation for more details on IUnknown methods.
959 * This version of QueryInterface will not delegate it's implementation
960 * to the outer unknown.
962 static ULONG WINAPI DataCache_NDIUnknown_AddRef(
965 _ICOM_THIS_From_NDIUnknown(DataCache, iface);
972 /************************************************************************
973 * DataCache_NDIUnknown_Release (IUnknown)
975 * See Windows documentation for more details on IUnknown methods.
977 * This version of QueryInterface will not delegate it's implementation
978 * to the outer unknown.
980 static ULONG WINAPI DataCache_NDIUnknown_Release(
983 _ICOM_THIS_From_NDIUnknown(DataCache, iface);
986 * Decrease the reference count on this object.
991 * If the reference count goes down to 0, perform suicide.
995 DataCache_Destroy(this);
1003 /*********************************************************
1004 * Method implementation for the IDataObject
1005 * part of the DataCache class.
1008 /************************************************************************
1009 * DataCache_IDataObject_QueryInterface (IUnknown)
1011 * See Windows documentation for more details on IUnknown methods.
1013 static HRESULT WINAPI DataCache_IDataObject_QueryInterface(
1018 _ICOM_THIS_From_IDataObject(DataCache, iface);
1020 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1023 /************************************************************************
1024 * DataCache_IDataObject_AddRef (IUnknown)
1026 * See Windows documentation for more details on IUnknown methods.
1028 static ULONG WINAPI DataCache_IDataObject_AddRef(
1031 _ICOM_THIS_From_IDataObject(DataCache, iface);
1033 return IUnknown_AddRef(this->outerUnknown);
1036 /************************************************************************
1037 * DataCache_IDataObject_Release (IUnknown)
1039 * See Windows documentation for more details on IUnknown methods.
1041 static ULONG WINAPI DataCache_IDataObject_Release(
1044 _ICOM_THIS_From_IDataObject(DataCache, iface);
1046 return IUnknown_Release(this->outerUnknown);
1049 /************************************************************************
1052 * Get Data from a source dataobject using format pformatetcIn->cfFormat
1053 * See Windows documentation for more details on GetData.
1054 * TODO: Currently only CF_METAFILEPICT is implemented
1056 static HRESULT WINAPI DataCache_GetData(
1058 LPFORMATETC pformatetcIn,
1062 HRESULT hrRet = E_UNEXPECTED;
1063 IPersistStorage *pPersistStorage = 0;
1064 IStorage *pStorage = 0;
1065 IStream *pStream = 0;
1066 OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
1067 HGLOBAL hGlobalMF = 0;
1069 PresentationDataHeader pdh;
1070 METAFILEPICT *mfPict;
1071 HMETAFILE hMetaFile = 0;
1073 if (pformatetcIn->cfFormat == CF_METAFILEPICT)
1075 /* Get the Persist Storage */
1077 hr = IDataObject_QueryInterface(iface, &IID_IPersistStorage, (void**)&pPersistStorage);
1082 /* Create a doc file to copy the doc to a storage */
1084 hr = StgCreateDocfile(NULL, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &pStorage);
1089 /* Save it to storage */
1091 hr = OleSave(pPersistStorage, pStorage, FALSE);
1096 /* Open the Presentation data srteam */
1098 hr = IStorage_OpenStream(pStorage, name, 0, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &pStream);
1103 /* Read the presentation header */
1105 hr = IStream_Read(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
1110 mfBits = HeapAlloc(GetProcessHeap(), 0, pdh.dwSize);
1112 /* Read the Metafile bits */
1114 hr = IStream_Read(pStream, mfBits, pdh.dwSize, NULL);
1119 /* Create the metafile and place it in the STGMEDIUM structure */
1121 hMetaFile = SetMetaFileBitsEx(pdh.dwSize, mfBits);
1123 hGlobalMF = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, sizeof(METAFILEPICT));
1124 mfPict = (METAFILEPICT *)GlobalLock(hGlobalMF);
1125 mfPict->hMF = hMetaFile;
1127 GlobalUnlock(hGlobalMF);
1129 pmedium->u.hGlobal = hGlobalMF;
1130 pmedium->tymed = TYMED_MFPICT;
1136 HeapFree(GetProcessHeap(), 0, mfBits);
1139 IStream_Release(pStream);
1142 IStorage_Release(pStorage);
1144 if (pPersistStorage)
1145 IPersistStorage_Release(pPersistStorage);
1150 /* TODO: Other formats are not implemented */
1155 static HRESULT WINAPI DataCache_GetDataHere(
1157 LPFORMATETC pformatetc,
1164 static HRESULT WINAPI DataCache_QueryGetData(
1166 LPFORMATETC pformatetc)
1172 /************************************************************************
1173 * DataCache_EnumFormatEtc (IDataObject)
1175 * The data cache doesn't implement this method.
1177 * See Windows documentation for more details on IDataObject methods.
1179 static HRESULT WINAPI DataCache_GetCanonicalFormatEtc(
1181 LPFORMATETC pformatectIn,
1182 LPFORMATETC pformatetcOut)
1188 /************************************************************************
1189 * DataCache_IDataObject_SetData (IDataObject)
1191 * This method is delegated to the IOleCache2 implementation.
1193 * See Windows documentation for more details on IDataObject methods.
1195 static HRESULT WINAPI DataCache_IDataObject_SetData(
1197 LPFORMATETC pformatetc,
1201 IOleCache2* oleCache = NULL;
1204 TRACE("(%p, %p, %p, %d)\n", iface, pformatetc, pmedium, fRelease);
1206 hres = IDataObject_QueryInterface(iface, &IID_IOleCache2, (void**)&oleCache);
1209 return E_UNEXPECTED;
1211 hres = IOleCache2_SetData(oleCache, pformatetc, pmedium, fRelease);
1213 IOleCache2_Release(oleCache);
1218 /************************************************************************
1219 * DataCache_EnumFormatEtc (IDataObject)
1221 * The data cache doesn't implement this method.
1223 * See Windows documentation for more details on IDataObject methods.
1225 static HRESULT WINAPI DataCache_EnumFormatEtc(
1228 IEnumFORMATETC** ppenumFormatEtc)
1234 /************************************************************************
1235 * DataCache_DAdvise (IDataObject)
1237 * The data cache doesn't support connections.
1239 * See Windows documentation for more details on IDataObject methods.
1241 static HRESULT WINAPI DataCache_DAdvise(
1243 FORMATETC* pformatetc,
1245 IAdviseSink* pAdvSink,
1246 DWORD* pdwConnection)
1249 return OLE_E_ADVISENOTSUPPORTED;
1252 /************************************************************************
1253 * DataCache_DUnadvise (IDataObject)
1255 * The data cache doesn't support connections.
1257 * See Windows documentation for more details on IDataObject methods.
1259 static HRESULT WINAPI DataCache_DUnadvise(
1264 return OLE_E_NOCONNECTION;
1267 /************************************************************************
1268 * DataCache_EnumDAdvise (IDataObject)
1270 * The data cache doesn't support connections.
1272 * See Windows documentation for more details on IDataObject methods.
1274 static HRESULT WINAPI DataCache_EnumDAdvise(
1276 IEnumSTATDATA** ppenumAdvise)
1279 return OLE_E_ADVISENOTSUPPORTED;
1282 /*********************************************************
1283 * Method implementation for the IDataObject
1284 * part of the DataCache class.
1287 /************************************************************************
1288 * DataCache_IPersistStorage_QueryInterface (IUnknown)
1290 * See Windows documentation for more details on IUnknown methods.
1292 static HRESULT WINAPI DataCache_IPersistStorage_QueryInterface(
1293 IPersistStorage* iface,
1297 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1299 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1302 /************************************************************************
1303 * DataCache_IPersistStorage_AddRef (IUnknown)
1305 * See Windows documentation for more details on IUnknown methods.
1307 static ULONG WINAPI DataCache_IPersistStorage_AddRef(
1308 IPersistStorage* iface)
1310 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1312 return IUnknown_AddRef(this->outerUnknown);
1315 /************************************************************************
1316 * DataCache_IPersistStorage_Release (IUnknown)
1318 * See Windows documentation for more details on IUnknown methods.
1320 static ULONG WINAPI DataCache_IPersistStorage_Release(
1321 IPersistStorage* iface)
1323 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1325 return IUnknown_Release(this->outerUnknown);
1328 /************************************************************************
1329 * DataCache_GetClassID (IPersistStorage)
1331 * The data cache doesn't implement this method.
1333 * See Windows documentation for more details on IPersistStorage methods.
1335 static HRESULT WINAPI DataCache_GetClassID(
1336 IPersistStorage* iface,
1339 TRACE("(%p, %p)\n", iface, pClassID);
1343 /************************************************************************
1344 * DataCache_IsDirty (IPersistStorage)
1346 * Until we actully connect to a running object and retrieve new
1347 * information to it, we never get dirty.
1349 * See Windows documentation for more details on IPersistStorage methods.
1351 static HRESULT WINAPI DataCache_IsDirty(
1352 IPersistStorage* iface)
1354 TRACE("(%p)\n", iface);
1359 /************************************************************************
1360 * DataCache_InitNew (IPersistStorage)
1362 * The data cache implementation of IPersistStorage_InitNew simply stores
1363 * the storage pointer.
1365 * See Windows documentation for more details on IPersistStorage methods.
1367 static HRESULT WINAPI DataCache_InitNew(
1368 IPersistStorage* iface,
1371 TRACE("(%p, %p)\n", iface, pStg);
1373 return DataCache_Load(iface, pStg);
1376 /************************************************************************
1377 * DataCache_Load (IPersistStorage)
1379 * The data cache implementation of IPersistStorage_Load doesn't
1380 * actually load anything. Instead, it holds on to the storage pointer
1381 * and it will load the presentation information when the
1382 * IDataObject_GetData or IViewObject2_Draw methods are called.
1384 * See Windows documentation for more details on IPersistStorage methods.
1386 static HRESULT WINAPI DataCache_Load(
1387 IPersistStorage* iface,
1390 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1392 TRACE("(%p, %p)\n", iface, pStg);
1394 if (this->presentationStorage != NULL)
1396 IStorage_Release(this->presentationStorage);
1399 this->presentationStorage = pStg;
1401 if (this->presentationStorage != NULL)
1403 IStorage_AddRef(this->presentationStorage);
1408 /************************************************************************
1409 * DataCache_Save (IPersistStorage)
1411 * Until we actully connect to a running object and retrieve new
1412 * information to it, we never have to save anything. However, it is
1413 * our responsability to copy the information when saving to a new
1416 * See Windows documentation for more details on IPersistStorage methods.
1418 static HRESULT WINAPI DataCache_Save(
1419 IPersistStorage* iface,
1423 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1425 TRACE("(%p, %p, %d)\n", iface, pStg, fSameAsLoad);
1427 if ( (!fSameAsLoad) &&
1428 (this->presentationStorage!=NULL) )
1430 return IStorage_CopyTo(this->presentationStorage,
1440 /************************************************************************
1441 * DataCache_SaveCompleted (IPersistStorage)
1443 * This method is called to tell the cache to release the storage
1444 * pointer it's currentlu holding.
1446 * See Windows documentation for more details on IPersistStorage methods.
1448 static HRESULT WINAPI DataCache_SaveCompleted(
1449 IPersistStorage* iface,
1452 TRACE("(%p, %p)\n", iface, pStgNew);
1457 * First, make sure we get our hands off any storage we have.
1460 DataCache_HandsOffStorage(iface);
1463 * Then, attach to the new storage.
1466 DataCache_Load(iface, pStgNew);
1472 /************************************************************************
1473 * DataCache_HandsOffStorage (IPersistStorage)
1475 * This method is called to tell the cache to release the storage
1476 * pointer it's currentlu holding.
1478 * See Windows documentation for more details on IPersistStorage methods.
1480 static HRESULT WINAPI DataCache_HandsOffStorage(
1481 IPersistStorage* iface)
1483 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1485 TRACE("(%p)\n", iface);
1487 if (this->presentationStorage != NULL)
1489 IStorage_Release(this->presentationStorage);
1490 this->presentationStorage = NULL;
1496 /*********************************************************
1497 * Method implementation for the IViewObject2
1498 * part of the DataCache class.
1501 /************************************************************************
1502 * DataCache_IViewObject2_QueryInterface (IUnknown)
1504 * See Windows documentation for more details on IUnknown methods.
1506 static HRESULT WINAPI DataCache_IViewObject2_QueryInterface(
1507 IViewObject2* iface,
1511 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1513 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1516 /************************************************************************
1517 * DataCache_IViewObject2_AddRef (IUnknown)
1519 * See Windows documentation for more details on IUnknown methods.
1521 static ULONG WINAPI DataCache_IViewObject2_AddRef(
1522 IViewObject2* iface)
1524 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1526 return IUnknown_AddRef(this->outerUnknown);
1529 /************************************************************************
1530 * DataCache_IViewObject2_Release (IUnknown)
1532 * See Windows documentation for more details on IUnknown methods.
1534 static ULONG WINAPI DataCache_IViewObject2_Release(
1535 IViewObject2* iface)
1537 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1539 return IUnknown_Release(this->outerUnknown);
1542 /************************************************************************
1543 * DataCache_Draw (IViewObject2)
1545 * This method will draw the cached representation of the object
1546 * to the given device context.
1548 * See Windows documentation for more details on IViewObject2 methods.
1550 static HRESULT WINAPI DataCache_Draw(
1551 IViewObject2* iface,
1555 DVTARGETDEVICE* ptd,
1558 LPCRECTL lprcBounds,
1559 LPCRECTL lprcWBounds,
1560 IVO_ContCallback pfnContinue,
1563 PresentationDataHeader presData;
1564 HMETAFILE presMetafile = 0;
1567 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1569 TRACE("(%p, %lx, %ld, %p, %x, %x, %p, %p, %p, %lx)\n",
1584 if (lprcBounds==NULL)
1585 return E_INVALIDARG;
1588 * First, we need to retrieve the dimensions of the
1589 * image in the metafile.
1591 hres = DataCache_ReadPresentationData(this,
1599 * Then, we can extract the metafile itself from the cached
1602 * FIXME Unless it isn't a metafile. I think it could be any CF_XXX type,
1603 * particularly CF_DIB.
1605 presMetafile = DataCache_ReadPresMetafile(this,
1609 * If we have a metafile, just draw baby...
1610 * We have to be careful not to modify the state of the
1613 if (presMetafile!=0)
1615 INT prevMapMode = SetMapMode(hdcDraw, MM_ANISOTROPIC);
1617 SIZE oldViewportExt;
1618 POINT oldViewportOrg;
1620 SetWindowExtEx(hdcDraw,
1621 presData.dwObjectExtentX,
1622 presData.dwObjectExtentY,
1625 SetViewportExtEx(hdcDraw,
1626 lprcBounds->right - lprcBounds->left,
1627 lprcBounds->bottom - lprcBounds->top,
1630 SetViewportOrgEx(hdcDraw,
1635 PlayMetaFile(hdcDraw, presMetafile);
1637 SetWindowExtEx(hdcDraw,
1642 SetViewportExtEx(hdcDraw,
1647 SetViewportOrgEx(hdcDraw,
1652 SetMapMode(hdcDraw, prevMapMode);
1654 DeleteMetaFile(presMetafile);
1660 static HRESULT WINAPI DataCache_GetColorSet(
1661 IViewObject2* iface,
1665 DVTARGETDEVICE* ptd,
1666 HDC hicTargetDevice,
1667 LOGPALETTE** ppColorSet)
1673 static HRESULT WINAPI DataCache_Freeze(
1674 IViewObject2* iface,
1684 static HRESULT WINAPI DataCache_Unfreeze(
1685 IViewObject2* iface,
1692 /************************************************************************
1693 * DataCache_SetAdvise (IViewObject2)
1695 * This sets-up an advisory sink with the data cache. When the object's
1696 * view changes, this sink is called.
1698 * See Windows documentation for more details on IViewObject2 methods.
1700 static HRESULT WINAPI DataCache_SetAdvise(
1701 IViewObject2* iface,
1704 IAdviseSink* pAdvSink)
1706 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1708 TRACE("(%p, %lx, %lx, %p)\n", iface, aspects, advf, pAdvSink);
1711 * A call to this function removes the previous sink
1713 if (this->sinkInterface != NULL)
1715 IAdviseSink_Release(this->sinkInterface);
1716 this->sinkInterface = NULL;
1717 this->sinkAspects = 0;
1718 this->sinkAdviseFlag = 0;
1722 * Now, setup the new one.
1726 this->sinkInterface = pAdvSink;
1727 this->sinkAspects = aspects;
1728 this->sinkAdviseFlag = advf;
1730 IAdviseSink_AddRef(this->sinkInterface);
1734 * When the ADVF_PRIMEFIRST flag is set, we have to advise the
1737 if (advf & ADVF_PRIMEFIRST)
1739 DataCache_FireOnViewChange(this,
1747 /************************************************************************
1748 * DataCache_GetAdvise (IViewObject2)
1750 * This method queries the current state of the advise sink
1751 * installed on the data cache.
1753 * See Windows documentation for more details on IViewObject2 methods.
1755 static HRESULT WINAPI DataCache_GetAdvise(
1756 IViewObject2* iface,
1759 IAdviseSink** ppAdvSink)
1761 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1763 TRACE("(%p, %p, %p, %p)\n", iface, pAspects, pAdvf, ppAdvSink);
1766 * Just copy all the requested values.
1769 *pAspects = this->sinkAspects;
1772 *pAdvf = this->sinkAdviseFlag;
1774 if (ppAdvSink!=NULL)
1776 IAdviseSink_QueryInterface(this->sinkInterface,
1784 /************************************************************************
1785 * DataCache_GetExtent (IViewObject2)
1787 * This method retrieves the "natural" size of this cached object.
1789 * See Windows documentation for more details on IViewObject2 methods.
1791 static HRESULT WINAPI DataCache_GetExtent(
1792 IViewObject2* iface,
1795 DVTARGETDEVICE* ptd,
1798 PresentationDataHeader presData;
1799 HRESULT hres = E_FAIL;
1801 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1803 TRACE("(%p, %lx, %ld, %p, %p)\n",
1804 iface, dwDrawAspect, lindex, ptd, lpsizel);
1813 * Initialize the out parameter.
1819 * This flag should be set to -1.
1822 FIXME("Unimplemented flag lindex = %ld\n", lindex);
1825 * Right now, we suport only the callback from
1826 * the default handler.
1829 FIXME("Unimplemented ptd = %p\n", ptd);
1832 * Get the presentation information from the
1835 hres = DataCache_ReadPresentationData(this,
1839 if (SUCCEEDED(hres))
1841 lpsizel->cx = presData.dwObjectExtentX;
1842 lpsizel->cy = presData.dwObjectExtentY;
1846 * This method returns OLE_E_BLANK when it fails.
1855 /*********************************************************
1856 * Method implementation for the IOleCache2
1857 * part of the DataCache class.
1860 /************************************************************************
1861 * DataCache_IOleCache2_QueryInterface (IUnknown)
1863 * See Windows documentation for more details on IUnknown methods.
1865 static HRESULT WINAPI DataCache_IOleCache2_QueryInterface(
1870 _ICOM_THIS_From_IOleCache2(DataCache, iface);
1872 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1875 /************************************************************************
1876 * DataCache_IOleCache2_AddRef (IUnknown)
1878 * See Windows documentation for more details on IUnknown methods.
1880 static ULONG WINAPI DataCache_IOleCache2_AddRef(
1883 _ICOM_THIS_From_IOleCache2(DataCache, iface);
1885 return IUnknown_AddRef(this->outerUnknown);
1888 /************************************************************************
1889 * DataCache_IOleCache2_Release (IUnknown)
1891 * See Windows documentation for more details on IUnknown methods.
1893 static ULONG WINAPI DataCache_IOleCache2_Release(
1896 _ICOM_THIS_From_IOleCache2(DataCache, iface);
1898 return IUnknown_Release(this->outerUnknown);
1901 static HRESULT WINAPI DataCache_Cache(
1903 FORMATETC* pformatetc,
1905 DWORD* pdwConnection)
1911 static HRESULT WINAPI DataCache_Uncache(
1919 static HRESULT WINAPI DataCache_EnumCache(
1921 IEnumSTATDATA** ppenumSTATDATA)
1927 static HRESULT WINAPI DataCache_InitCache(
1929 IDataObject* pDataObject)
1935 static HRESULT WINAPI DataCache_IOleCache2_SetData(
1937 FORMATETC* pformatetc,
1945 static HRESULT WINAPI DataCache_UpdateCache(
1947 LPDATAOBJECT pDataObject,
1955 static HRESULT WINAPI DataCache_DiscardCache(
1957 DWORD dwDiscardOptions)
1964 /*********************************************************
1965 * Method implementation for the IOleCacheControl
1966 * part of the DataCache class.
1969 /************************************************************************
1970 * DataCache_IOleCacheControl_QueryInterface (IUnknown)
1972 * See Windows documentation for more details on IUnknown methods.
1974 static HRESULT WINAPI DataCache_IOleCacheControl_QueryInterface(
1975 IOleCacheControl* iface,
1979 _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
1981 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1984 /************************************************************************
1985 * DataCache_IOleCacheControl_AddRef (IUnknown)
1987 * See Windows documentation for more details on IUnknown methods.
1989 static ULONG WINAPI DataCache_IOleCacheControl_AddRef(
1990 IOleCacheControl* iface)
1992 _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
1994 return IUnknown_AddRef(this->outerUnknown);
1997 /************************************************************************
1998 * DataCache_IOleCacheControl_Release (IUnknown)
2000 * See Windows documentation for more details on IUnknown methods.
2002 static ULONG WINAPI DataCache_IOleCacheControl_Release(
2003 IOleCacheControl* iface)
2005 _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
2007 return IUnknown_Release(this->outerUnknown);
2010 static HRESULT WINAPI DataCache_OnRun(
2011 IOleCacheControl* iface,
2012 LPDATAOBJECT pDataObject)
2018 static HRESULT WINAPI DataCache_OnStop(
2019 IOleCacheControl* iface)