4 * Copyright 1999 Francis Beaudet
5 * Copyright 2000 Abey George
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * The OLE2 data cache supports a whole whack of
23 * interfaces including:
24 * IDataObject, IPersistStorage, IViewObject2,
25 * IOleCache2 and IOleCacheControl.
27 * Most of the implementation details are taken from: Inside OLE
28 * second edition by Kraig Brockschmidt,
31 * - This implementation of the datacache will let your application
32 * load documents that have embedded OLE objects in them and it will
33 * also retrieve the metafile representation of those objects.
34 * - This implementation of the datacache will also allow your
35 * application to save new documents with OLE objects in them.
36 * - The main thing that it doesn't do is allow you to activate
37 * or modify the OLE objects in any way.
38 * - I haven't found any good documentation on the real usage of
39 * the streams created by the data cache. In particular, How to
40 * determine what the XXX stands for in the stream name
41 * "\002OlePresXXX". It appears to just be a counter.
42 * - Also, I don't know the real content of the presentation stream
43 * header. I was able to figure-out where the extent of the object
44 * was stored and the aspect, but that's about it.
51 #define NONAMELESSUNION
52 #define NONAMELESSSTRUCT
59 #include "wine/unicode.h"
61 #include "wine/debug.h"
63 WINE_DEFAULT_DEBUG_CHANNEL(ole);
65 /****************************************************************************
66 * PresentationDataHeader
68 * This structure represents the header of the \002OlePresXXX stream in
69 * the OLE object strorage.
71 * Most fields are still unknown.
73 typedef struct PresentationDataHeader
75 DWORD unknown1; /* -1 */
76 DWORD unknown2; /* 3, possibly CF_METAFILEPICT */
77 DWORD unknown3; /* 4, possibly TYMED_ISTREAM */
79 DWORD unknown5; /* -1 */
82 DWORD unknown7; /* 0 */
83 DWORD dwObjectExtentX;
84 DWORD dwObjectExtentY;
86 } PresentationDataHeader;
88 /****************************************************************************
94 * List all interface VTables here
96 IDataObjectVtbl* lpvtbl1;
97 IUnknownVtbl* lpvtbl2;
98 IPersistStorageVtbl* lpvtbl3;
99 IViewObject2Vtbl* lpvtbl4;
100 IOleCache2Vtbl* lpvtbl5;
101 IOleCacheControlVtbl* lpvtbl6;
104 * Reference count of this object
109 * IUnknown implementation of the outer object.
111 IUnknown* outerUnknown;
114 * This storage pointer is set through a call to
115 * IPersistStorage_Load. This is where the visual
116 * representation of the object is stored.
118 IStorage* presentationStorage;
121 * The user of this object can setup ONE advise sink
122 * connection with the object. These parameters describe
126 DWORD sinkAdviseFlag;
127 IAdviseSink* sinkInterface;
131 typedef struct DataCache DataCache;
134 * Here, I define utility macros to help with the casting of the
136 * There is a version to accommodate all of the VTables implemented
139 #define _ICOM_THIS_From_IDataObject(class,name) class* this = (class*)name
140 #define _ICOM_THIS_From_NDIUnknown(class, name) class* this = (class*)(((char*)name)-sizeof(void*))
141 #define _ICOM_THIS_From_IPersistStorage(class, name) class* this = (class*)(((char*)name)-2*sizeof(void*))
142 #define _ICOM_THIS_From_IViewObject2(class, name) class* this = (class*)(((char*)name)-3*sizeof(void*))
143 #define _ICOM_THIS_From_IOleCache2(class, name) class* this = (class*)(((char*)name)-4*sizeof(void*))
144 #define _ICOM_THIS_From_IOleCacheControl(class, name) class* this = (class*)(((char*)name)-5*sizeof(void*))
147 * Prototypes for the methods of the DataCache class.
149 static DataCache* DataCache_Construct(REFCLSID clsid,
150 LPUNKNOWN pUnkOuter);
151 static void DataCache_Destroy(DataCache* ptrToDestroy);
152 static HRESULT DataCache_ReadPresentationData(DataCache* this,
154 PresentationDataHeader* header);
155 static HRESULT DataCache_OpenPresStream(DataCache *this,
158 static HMETAFILE DataCache_ReadPresMetafile(DataCache* this,
160 static void DataCache_FireOnViewChange(DataCache* this,
165 * Prototypes for the methods of the DataCache class
166 * that implement non delegating IUnknown methods.
168 static HRESULT WINAPI DataCache_NDIUnknown_QueryInterface(
172 static ULONG WINAPI DataCache_NDIUnknown_AddRef(
174 static ULONG WINAPI DataCache_NDIUnknown_Release(
178 * Prototypes for the methods of the DataCache class
179 * that implement IDataObject methods.
181 static HRESULT WINAPI DataCache_IDataObject_QueryInterface(
185 static ULONG WINAPI DataCache_IDataObject_AddRef(
187 static ULONG WINAPI DataCache_IDataObject_Release(
189 static HRESULT WINAPI DataCache_GetData(
191 LPFORMATETC pformatetcIn,
193 static HRESULT WINAPI DataCache_GetDataHere(
195 LPFORMATETC pformatetc,
197 static HRESULT WINAPI DataCache_QueryGetData(
199 LPFORMATETC pformatetc);
200 static HRESULT WINAPI DataCache_GetCanonicalFormatEtc(
202 LPFORMATETC pformatectIn,
203 LPFORMATETC pformatetcOut);
204 static HRESULT WINAPI DataCache_IDataObject_SetData(
206 LPFORMATETC pformatetc,
209 static HRESULT WINAPI DataCache_EnumFormatEtc(
212 IEnumFORMATETC** ppenumFormatEtc);
213 static HRESULT WINAPI DataCache_DAdvise(
215 FORMATETC* pformatetc,
217 IAdviseSink* pAdvSink,
218 DWORD* pdwConnection);
219 static HRESULT WINAPI DataCache_DUnadvise(
222 static HRESULT WINAPI DataCache_EnumDAdvise(
224 IEnumSTATDATA** ppenumAdvise);
227 * Prototypes for the methods of the DataCache class
228 * that implement IPersistStorage methods.
230 static HRESULT WINAPI DataCache_IPersistStorage_QueryInterface(
231 IPersistStorage* iface,
234 static ULONG WINAPI DataCache_IPersistStorage_AddRef(
235 IPersistStorage* iface);
236 static ULONG WINAPI DataCache_IPersistStorage_Release(
237 IPersistStorage* iface);
238 static HRESULT WINAPI DataCache_GetClassID(
239 IPersistStorage* iface,
241 static HRESULT WINAPI DataCache_IsDirty(
242 IPersistStorage* iface);
243 static HRESULT WINAPI DataCache_InitNew(
244 IPersistStorage* iface,
246 static HRESULT WINAPI DataCache_Load(
247 IPersistStorage* iface,
249 static HRESULT WINAPI DataCache_Save(
250 IPersistStorage* iface,
253 static HRESULT WINAPI DataCache_SaveCompleted(
254 IPersistStorage* iface,
256 static HRESULT WINAPI DataCache_HandsOffStorage(
257 IPersistStorage* iface);
260 * Prototypes for the methods of the DataCache class
261 * that implement IViewObject2 methods.
263 static HRESULT WINAPI DataCache_IViewObject2_QueryInterface(
267 static ULONG WINAPI DataCache_IViewObject2_AddRef(
268 IViewObject2* iface);
269 static ULONG WINAPI DataCache_IViewObject2_Release(
270 IViewObject2* iface);
271 static HRESULT WINAPI DataCache_Draw(
280 LPCRECTL lprcWBounds,
281 BOOL (CALLBACK *pfnContinue)(ULONG_PTR dwContinue),
282 ULONG_PTR dwContinue);
283 static HRESULT WINAPI DataCache_GetColorSet(
290 LOGPALETTE** ppColorSet);
291 static HRESULT WINAPI DataCache_Freeze(
297 static HRESULT WINAPI DataCache_Unfreeze(
300 static HRESULT WINAPI DataCache_SetAdvise(
304 IAdviseSink* pAdvSink);
305 static HRESULT WINAPI DataCache_GetAdvise(
309 IAdviseSink** ppAdvSink);
310 static HRESULT WINAPI DataCache_GetExtent(
318 * Prototypes for the methods of the DataCache class
319 * that implement IOleCache2 methods.
321 static HRESULT WINAPI DataCache_IOleCache2_QueryInterface(
325 static ULONG WINAPI DataCache_IOleCache2_AddRef(
327 static ULONG WINAPI DataCache_IOleCache2_Release(
329 static HRESULT WINAPI DataCache_Cache(
331 FORMATETC* pformatetc,
333 DWORD* pdwConnection);
334 static HRESULT WINAPI DataCache_Uncache(
337 static HRESULT WINAPI DataCache_EnumCache(
339 IEnumSTATDATA** ppenumSTATDATA);
340 static HRESULT WINAPI DataCache_InitCache(
342 IDataObject* pDataObject);
343 static HRESULT WINAPI DataCache_IOleCache2_SetData(
345 FORMATETC* pformatetc,
348 static HRESULT WINAPI DataCache_UpdateCache(
350 LPDATAOBJECT pDataObject,
353 static HRESULT WINAPI DataCache_DiscardCache(
355 DWORD dwDiscardOptions);
358 * Prototypes for the methods of the DataCache class
359 * that implement IOleCacheControl methods.
361 static HRESULT WINAPI DataCache_IOleCacheControl_QueryInterface(
362 IOleCacheControl* iface,
365 static ULONG WINAPI DataCache_IOleCacheControl_AddRef(
366 IOleCacheControl* iface);
367 static ULONG WINAPI DataCache_IOleCacheControl_Release(
368 IOleCacheControl* iface);
369 static HRESULT WINAPI DataCache_OnRun(
370 IOleCacheControl* iface,
371 LPDATAOBJECT pDataObject);
372 static HRESULT WINAPI DataCache_OnStop(
373 IOleCacheControl* iface);
376 * Virtual function tables for the DataCache class.
378 static IUnknownVtbl DataCache_NDIUnknown_VTable =
380 DataCache_NDIUnknown_QueryInterface,
381 DataCache_NDIUnknown_AddRef,
382 DataCache_NDIUnknown_Release
385 static IDataObjectVtbl DataCache_IDataObject_VTable =
387 DataCache_IDataObject_QueryInterface,
388 DataCache_IDataObject_AddRef,
389 DataCache_IDataObject_Release,
391 DataCache_GetDataHere,
392 DataCache_QueryGetData,
393 DataCache_GetCanonicalFormatEtc,
394 DataCache_IDataObject_SetData,
395 DataCache_EnumFormatEtc,
398 DataCache_EnumDAdvise
401 static IPersistStorageVtbl DataCache_IPersistStorage_VTable =
403 DataCache_IPersistStorage_QueryInterface,
404 DataCache_IPersistStorage_AddRef,
405 DataCache_IPersistStorage_Release,
406 DataCache_GetClassID,
411 DataCache_SaveCompleted,
412 DataCache_HandsOffStorage
415 static IViewObject2Vtbl DataCache_IViewObject2_VTable =
417 DataCache_IViewObject2_QueryInterface,
418 DataCache_IViewObject2_AddRef,
419 DataCache_IViewObject2_Release,
421 DataCache_GetColorSet,
429 static IOleCache2Vtbl DataCache_IOleCache2_VTable =
431 DataCache_IOleCache2_QueryInterface,
432 DataCache_IOleCache2_AddRef,
433 DataCache_IOleCache2_Release,
438 DataCache_IOleCache2_SetData,
439 DataCache_UpdateCache,
440 DataCache_DiscardCache
443 static IOleCacheControlVtbl DataCache_IOleCacheControl_VTable =
445 DataCache_IOleCacheControl_QueryInterface,
446 DataCache_IOleCacheControl_AddRef,
447 DataCache_IOleCacheControl_Release,
452 /******************************************************************************
453 * CreateDataCache [OLE32.@]
455 HRESULT WINAPI CreateDataCache(
461 DataCache* newCache = NULL;
464 TRACE("(%s, %p, %s, %p)\n", debugstr_guid(rclsid), pUnkOuter, debugstr_guid(riid), ppvObj);
475 * If this cache is constructed for aggregation, make sure
476 * the caller is requesting the IUnknown interface.
477 * This is necessary because it's the only time the non-delegating
478 * IUnknown pointer can be returned to the outside.
480 if ( (pUnkOuter!=NULL) &&
481 (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) != 0) )
482 return CLASS_E_NOAGGREGATION;
485 * Try to construct a new instance of the class.
487 newCache = DataCache_Construct(rclsid,
491 return E_OUTOFMEMORY;
494 * Make sure it supports the interface required by the caller.
496 hr = IUnknown_QueryInterface((IUnknown*)&(newCache->lpvtbl2), riid, ppvObj);
499 * Release the reference obtained in the constructor. If
500 * the QueryInterface was unsuccessful, it will free the class.
502 IUnknown_Release((IUnknown*)&(newCache->lpvtbl2));
507 /*********************************************************
508 * Method implementation for DataCache class.
510 static DataCache* DataCache_Construct(
514 DataCache* newObject = 0;
517 * Allocate space for the object.
519 newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(DataCache));
525 * Initialize the virtual function table.
527 newObject->lpvtbl1 = &DataCache_IDataObject_VTable;
528 newObject->lpvtbl2 = &DataCache_NDIUnknown_VTable;
529 newObject->lpvtbl3 = &DataCache_IPersistStorage_VTable;
530 newObject->lpvtbl4 = &DataCache_IViewObject2_VTable;
531 newObject->lpvtbl5 = &DataCache_IOleCache2_VTable;
532 newObject->lpvtbl6 = &DataCache_IOleCacheControl_VTable;
535 * Start with one reference count. The caller of this function
536 * must release the interface pointer when it is done.
541 * Initialize the outer unknown
542 * We don't keep a reference on the outer unknown since, the way
543 * aggregation works, our lifetime is at least as large as it's
547 pUnkOuter = (IUnknown*)&(newObject->lpvtbl2);
549 newObject->outerUnknown = pUnkOuter;
552 * Initialize the other members of the structure.
554 newObject->presentationStorage = NULL;
555 newObject->sinkAspects = 0;
556 newObject->sinkAdviseFlag = 0;
557 newObject->sinkInterface = 0;
562 static void DataCache_Destroy(
563 DataCache* ptrToDestroy)
567 if (ptrToDestroy->sinkInterface != NULL)
569 IAdviseSink_Release(ptrToDestroy->sinkInterface);
570 ptrToDestroy->sinkInterface = NULL;
573 if (ptrToDestroy->presentationStorage != NULL)
575 IStorage_Release(ptrToDestroy->presentationStorage);
576 ptrToDestroy->presentationStorage = NULL;
580 * Free the datacache pointer.
582 HeapFree(GetProcessHeap(), 0, ptrToDestroy);
585 /************************************************************************
586 * DataCache_ReadPresentationData
588 * This method will read information for the requested presentation
589 * into the given structure.
592 * this - Pointer to the DataCache object
593 * drawAspect - The aspect of the object that we wish to draw.
594 * header - The structure containing information about this
595 * aspect of the object.
597 static HRESULT DataCache_ReadPresentationData(
600 PresentationDataHeader* header)
602 IStream* presStream = NULL;
606 * Open the presentation stream.
608 hres = DataCache_OpenPresStream(
623 sizeof(PresentationDataHeader),
629 IStream_Release(presStream);
632 * We don't want to propagate any other error
633 * code than a failure.
641 /************************************************************************
642 * DataCache_FireOnViewChange
644 * This method will fire an OnViewChange notification to the advise
645 * sink registered with the datacache.
647 * See IAdviseSink::OnViewChange for more details.
649 static void DataCache_FireOnViewChange(
654 TRACE("(%p, %lx, %ld)\n", this, aspect, lindex);
657 * The sink supplies a filter when it registers
658 * we make sure we only send the notifications when that
661 if ((this->sinkAspects & aspect) != 0)
663 if (this->sinkInterface != NULL)
665 IAdviseSink_OnViewChange(this->sinkInterface,
670 * Some sinks want to be unregistered automatically when
671 * the first notification goes out.
673 if ( (this->sinkAdviseFlag & ADVF_ONLYONCE) != 0)
675 IAdviseSink_Release(this->sinkInterface);
677 this->sinkInterface = NULL;
678 this->sinkAspects = 0;
679 this->sinkAdviseFlag = 0;
685 /* Helper for DataCache_OpenPresStream */
686 static BOOL DataCache_IsPresentationStream(const STATSTG *elem)
688 /* The presentation streams have names of the form "\002OlePresXXX",
689 * where XXX goes from 000 to 999. */
690 static const WCHAR OlePres[] = { 2,'O','l','e','P','r','e','s' };
692 LPCWSTR name = elem->pwcsName;
694 return (elem->type == STGTY_STREAM)
695 && (elem->cbSize.u.LowPart >= sizeof(PresentationDataHeader))
696 && (strlenW(name) == 11)
697 && (strncmpW(name, OlePres, 8) == 0)
698 && (name[8] >= '0') && (name[8] <= '9')
699 && (name[9] >= '0') && (name[9] <= '9')
700 && (name[10] >= '0') && (name[10] <= '9');
703 /************************************************************************
704 * DataCache_OpenPresStream
706 * This method will find the stream for the given presentation. It makes
707 * no attempt at fallback.
710 * this - Pointer to the DataCache object
711 * drawAspect - The aspect of the object that we wish to draw.
712 * pStm - A returned stream. It points to the beginning of the
713 * - presentation data, including the header.
716 * S_OK The requested stream has been opened.
717 * OLE_E_BLANK The requested stream could not be found.
718 * Quite a few others I'm too lazy to map correctly.
721 * Algorithm: Scan the elements of the presentation storage, looking
722 * for presentation streams. For each presentation stream,
723 * load the header and check to see if the aspect maches.
725 * If a fallback is desired, just opening the first presentation stream
728 static HRESULT DataCache_OpenPresStream(
737 if (!ppStm) return E_POINTER;
739 hr = IStorage_EnumElements(this->presentationStorage, 0, NULL, 0, &pEnum);
740 if (FAILED(hr)) return hr;
742 while ((hr = IEnumSTATSTG_Next(pEnum, 1, &elem, NULL)) == S_OK)
744 if (DataCache_IsPresentationStream(&elem))
748 hr = IStorage_OpenStream(this->presentationStorage, elem.pwcsName,
749 NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0,
753 PresentationDataHeader header;
756 hr = IStream_Read(pStm, &header, sizeof(header), &actual_read);
758 /* can't use SUCCEEDED(hr): S_FALSE counts as an error */
759 if (hr == S_OK && actual_read == sizeof(header)
760 && header.dvAspect == drawAspect)
762 /* Rewind the stream before returning it. */
763 LARGE_INTEGER offset;
764 offset.u.LowPart = 0;
765 offset.u.HighPart = 0;
766 IStream_Seek(pStm, offset, STREAM_SEEK_SET, NULL);
770 CoTaskMemFree(elem.pwcsName);
771 IEnumSTATSTG_Release(pEnum);
776 IStream_Release(pStm);
780 CoTaskMemFree(elem.pwcsName);
783 IEnumSTATSTG_Release(pEnum);
785 return (hr == S_FALSE ? OLE_E_BLANK : hr);
788 /************************************************************************
789 * DataCache_ReadPresentationData
791 * This method will read information for the requested presentation
792 * into the given structure.
795 * this - Pointer to the DataCache object
796 * drawAspect - The aspect of the object that we wish to draw.
799 * This method returns a metafile handle if it is successful.
800 * it will return 0 if not.
802 static HMETAFILE DataCache_ReadPresMetafile(
806 LARGE_INTEGER offset;
807 IStream* presStream = NULL;
811 HMETAFILE newMetafile = 0;
814 * Open the presentation stream.
816 hres = DataCache_OpenPresStream(
822 return (HMETAFILE)hres;
825 * Get the size of the stream.
827 hres = IStream_Stat(presStream,
834 offset.u.HighPart = 0;
835 offset.u.LowPart = sizeof(PresentationDataHeader);
843 streamInfo.cbSize.u.LowPart -= offset.u.LowPart;
846 * Allocate a buffer for the metafile bits.
848 metafileBits = HeapAlloc(GetProcessHeap(),
850 streamInfo.cbSize.u.LowPart);
853 * Read the metafile bits.
858 streamInfo.cbSize.u.LowPart,
862 * Create a metafile with those bits.
866 newMetafile = SetMetaFileBitsEx(streamInfo.cbSize.u.LowPart, metafileBits);
872 HeapFree(GetProcessHeap(), 0, metafileBits);
873 IStream_Release(presStream);
881 /*********************************************************
882 * Method implementation for the non delegating IUnknown
883 * part of the DataCache class.
886 /************************************************************************
887 * DataCache_NDIUnknown_QueryInterface (IUnknown)
889 * See Windows documentation for more details on IUnknown methods.
891 * This version of QueryInterface will not delegate it's implementation
892 * to the outer unknown.
894 static HRESULT WINAPI DataCache_NDIUnknown_QueryInterface(
899 _ICOM_THIS_From_NDIUnknown(DataCache, iface);
902 * Perform a sanity check on the parameters.
904 if ( (this==0) || (ppvObject==0) )
908 * Initialize the return parameter.
913 * Compare the riid with the interface IDs implemented by this object.
915 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
919 else if (memcmp(&IID_IDataObject, riid, sizeof(IID_IDataObject)) == 0)
921 *ppvObject = (IDataObject*)&(this->lpvtbl1);
923 else if ( (memcmp(&IID_IPersistStorage, riid, sizeof(IID_IPersistStorage)) == 0) ||
924 (memcmp(&IID_IPersist, riid, sizeof(IID_IPersist)) == 0) )
926 *ppvObject = (IPersistStorage*)&(this->lpvtbl3);
928 else if ( (memcmp(&IID_IViewObject, riid, sizeof(IID_IViewObject)) == 0) ||
929 (memcmp(&IID_IViewObject2, riid, sizeof(IID_IViewObject2)) == 0) )
931 *ppvObject = (IViewObject2*)&(this->lpvtbl4);
933 else if ( (memcmp(&IID_IOleCache, riid, sizeof(IID_IOleCache)) == 0) ||
934 (memcmp(&IID_IOleCache2, riid, sizeof(IID_IOleCache2)) == 0) )
936 *ppvObject = (IOleCache2*)&(this->lpvtbl5);
938 else if (memcmp(&IID_IOleCacheControl, riid, sizeof(IID_IOleCacheControl)) == 0)
940 *ppvObject = (IOleCacheControl*)&(this->lpvtbl6);
944 * Check that we obtained an interface.
948 WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid));
949 return E_NOINTERFACE;
953 * Query Interface always increases the reference count by one when it is
956 IUnknown_AddRef((IUnknown*)*ppvObject);
961 /************************************************************************
962 * DataCache_NDIUnknown_AddRef (IUnknown)
964 * See Windows documentation for more details on IUnknown methods.
966 * This version of QueryInterface will not delegate it's implementation
967 * to the outer unknown.
969 static ULONG WINAPI DataCache_NDIUnknown_AddRef(
972 _ICOM_THIS_From_NDIUnknown(DataCache, iface);
973 return InterlockedIncrement(&this->ref);
976 /************************************************************************
977 * DataCache_NDIUnknown_Release (IUnknown)
979 * See Windows documentation for more details on IUnknown methods.
981 * This version of QueryInterface will not delegate it's implementation
982 * to the outer unknown.
984 static ULONG WINAPI DataCache_NDIUnknown_Release(
987 _ICOM_THIS_From_NDIUnknown(DataCache, iface);
991 * Decrease the reference count on this object.
993 ref = InterlockedDecrement(&this->ref);
996 * If the reference count goes down to 0, perform suicide.
998 if (ref == 0) 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;
1135 HeapFree(GetProcessHeap(), 0, mfBits);
1138 IStream_Release(pStream);
1141 IStorage_Release(pStorage);
1143 if (pPersistStorage)
1144 IPersistStorage_Release(pPersistStorage);
1149 /* TODO: Other formats are not implemented */
1154 static HRESULT WINAPI DataCache_GetDataHere(
1156 LPFORMATETC pformatetc,
1163 static HRESULT WINAPI DataCache_QueryGetData(
1165 LPFORMATETC pformatetc)
1171 /************************************************************************
1172 * DataCache_EnumFormatEtc (IDataObject)
1174 * The data cache doesn't implement this method.
1176 * See Windows documentation for more details on IDataObject methods.
1178 static HRESULT WINAPI DataCache_GetCanonicalFormatEtc(
1180 LPFORMATETC pformatectIn,
1181 LPFORMATETC pformatetcOut)
1187 /************************************************************************
1188 * DataCache_IDataObject_SetData (IDataObject)
1190 * This method is delegated to the IOleCache2 implementation.
1192 * See Windows documentation for more details on IDataObject methods.
1194 static HRESULT WINAPI DataCache_IDataObject_SetData(
1196 LPFORMATETC pformatetc,
1200 IOleCache2* oleCache = NULL;
1203 TRACE("(%p, %p, %p, %d)\n", iface, pformatetc, pmedium, fRelease);
1205 hres = IDataObject_QueryInterface(iface, &IID_IOleCache2, (void**)&oleCache);
1208 return E_UNEXPECTED;
1210 hres = IOleCache2_SetData(oleCache, pformatetc, pmedium, fRelease);
1212 IOleCache2_Release(oleCache);
1217 /************************************************************************
1218 * DataCache_EnumFormatEtc (IDataObject)
1220 * The data cache doesn't implement this method.
1222 * See Windows documentation for more details on IDataObject methods.
1224 static HRESULT WINAPI DataCache_EnumFormatEtc(
1227 IEnumFORMATETC** ppenumFormatEtc)
1233 /************************************************************************
1234 * DataCache_DAdvise (IDataObject)
1236 * The data cache doesn't support connections.
1238 * See Windows documentation for more details on IDataObject methods.
1240 static HRESULT WINAPI DataCache_DAdvise(
1242 FORMATETC* pformatetc,
1244 IAdviseSink* pAdvSink,
1245 DWORD* pdwConnection)
1248 return OLE_E_ADVISENOTSUPPORTED;
1251 /************************************************************************
1252 * DataCache_DUnadvise (IDataObject)
1254 * The data cache doesn't support connections.
1256 * See Windows documentation for more details on IDataObject methods.
1258 static HRESULT WINAPI DataCache_DUnadvise(
1263 return OLE_E_NOCONNECTION;
1266 /************************************************************************
1267 * DataCache_EnumDAdvise (IDataObject)
1269 * The data cache doesn't support connections.
1271 * See Windows documentation for more details on IDataObject methods.
1273 static HRESULT WINAPI DataCache_EnumDAdvise(
1275 IEnumSTATDATA** ppenumAdvise)
1278 return OLE_E_ADVISENOTSUPPORTED;
1281 /*********************************************************
1282 * Method implementation for the IDataObject
1283 * part of the DataCache class.
1286 /************************************************************************
1287 * DataCache_IPersistStorage_QueryInterface (IUnknown)
1289 * See Windows documentation for more details on IUnknown methods.
1291 static HRESULT WINAPI DataCache_IPersistStorage_QueryInterface(
1292 IPersistStorage* iface,
1296 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1298 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1301 /************************************************************************
1302 * DataCache_IPersistStorage_AddRef (IUnknown)
1304 * See Windows documentation for more details on IUnknown methods.
1306 static ULONG WINAPI DataCache_IPersistStorage_AddRef(
1307 IPersistStorage* iface)
1309 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1311 return IUnknown_AddRef(this->outerUnknown);
1314 /************************************************************************
1315 * DataCache_IPersistStorage_Release (IUnknown)
1317 * See Windows documentation for more details on IUnknown methods.
1319 static ULONG WINAPI DataCache_IPersistStorage_Release(
1320 IPersistStorage* iface)
1322 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1324 return IUnknown_Release(this->outerUnknown);
1327 /************************************************************************
1328 * DataCache_GetClassID (IPersistStorage)
1330 * The data cache doesn't implement this method.
1332 * See Windows documentation for more details on IPersistStorage methods.
1334 static HRESULT WINAPI DataCache_GetClassID(
1335 IPersistStorage* iface,
1338 TRACE("(%p, %p)\n", iface, pClassID);
1342 /************************************************************************
1343 * DataCache_IsDirty (IPersistStorage)
1345 * Until we actully connect to a running object and retrieve new
1346 * information to it, we never get dirty.
1348 * See Windows documentation for more details on IPersistStorage methods.
1350 static HRESULT WINAPI DataCache_IsDirty(
1351 IPersistStorage* iface)
1353 TRACE("(%p)\n", iface);
1358 /************************************************************************
1359 * DataCache_InitNew (IPersistStorage)
1361 * The data cache implementation of IPersistStorage_InitNew simply stores
1362 * the storage pointer.
1364 * See Windows documentation for more details on IPersistStorage methods.
1366 static HRESULT WINAPI DataCache_InitNew(
1367 IPersistStorage* iface,
1370 TRACE("(%p, %p)\n", iface, pStg);
1372 return DataCache_Load(iface, pStg);
1375 /************************************************************************
1376 * DataCache_Load (IPersistStorage)
1378 * The data cache implementation of IPersistStorage_Load doesn't
1379 * actually load anything. Instead, it holds on to the storage pointer
1380 * and it will load the presentation information when the
1381 * IDataObject_GetData or IViewObject2_Draw methods are called.
1383 * See Windows documentation for more details on IPersistStorage methods.
1385 static HRESULT WINAPI DataCache_Load(
1386 IPersistStorage* iface,
1389 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1391 TRACE("(%p, %p)\n", iface, pStg);
1393 if (this->presentationStorage != NULL)
1395 IStorage_Release(this->presentationStorage);
1398 this->presentationStorage = pStg;
1400 if (this->presentationStorage != NULL)
1402 IStorage_AddRef(this->presentationStorage);
1407 /************************************************************************
1408 * DataCache_Save (IPersistStorage)
1410 * Until we actully connect to a running object and retrieve new
1411 * information to it, we never have to save anything. However, it is
1412 * our responsability to copy the information when saving to a new
1415 * See Windows documentation for more details on IPersistStorage methods.
1417 static HRESULT WINAPI DataCache_Save(
1418 IPersistStorage* iface,
1422 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1424 TRACE("(%p, %p, %d)\n", iface, pStg, fSameAsLoad);
1426 if ( (!fSameAsLoad) &&
1427 (this->presentationStorage!=NULL) )
1429 return IStorage_CopyTo(this->presentationStorage,
1439 /************************************************************************
1440 * DataCache_SaveCompleted (IPersistStorage)
1442 * This method is called to tell the cache to release the storage
1443 * pointer it's currentlu holding.
1445 * See Windows documentation for more details on IPersistStorage methods.
1447 static HRESULT WINAPI DataCache_SaveCompleted(
1448 IPersistStorage* iface,
1451 TRACE("(%p, %p)\n", iface, pStgNew);
1456 * First, make sure we get our hands off any storage we have.
1459 DataCache_HandsOffStorage(iface);
1462 * Then, attach to the new storage.
1465 DataCache_Load(iface, pStgNew);
1471 /************************************************************************
1472 * DataCache_HandsOffStorage (IPersistStorage)
1474 * This method is called to tell the cache to release the storage
1475 * pointer it's currentlu holding.
1477 * See Windows documentation for more details on IPersistStorage methods.
1479 static HRESULT WINAPI DataCache_HandsOffStorage(
1480 IPersistStorage* iface)
1482 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1484 TRACE("(%p)\n", iface);
1486 if (this->presentationStorage != NULL)
1488 IStorage_Release(this->presentationStorage);
1489 this->presentationStorage = NULL;
1495 /*********************************************************
1496 * Method implementation for the IViewObject2
1497 * part of the DataCache class.
1500 /************************************************************************
1501 * DataCache_IViewObject2_QueryInterface (IUnknown)
1503 * See Windows documentation for more details on IUnknown methods.
1505 static HRESULT WINAPI DataCache_IViewObject2_QueryInterface(
1506 IViewObject2* iface,
1510 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1512 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1515 /************************************************************************
1516 * DataCache_IViewObject2_AddRef (IUnknown)
1518 * See Windows documentation for more details on IUnknown methods.
1520 static ULONG WINAPI DataCache_IViewObject2_AddRef(
1521 IViewObject2* iface)
1523 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1525 return IUnknown_AddRef(this->outerUnknown);
1528 /************************************************************************
1529 * DataCache_IViewObject2_Release (IUnknown)
1531 * See Windows documentation for more details on IUnknown methods.
1533 static ULONG WINAPI DataCache_IViewObject2_Release(
1534 IViewObject2* iface)
1536 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1538 return IUnknown_Release(this->outerUnknown);
1541 /************************************************************************
1542 * DataCache_Draw (IViewObject2)
1544 * This method will draw the cached representation of the object
1545 * to the given device context.
1547 * See Windows documentation for more details on IViewObject2 methods.
1549 static HRESULT WINAPI DataCache_Draw(
1550 IViewObject2* iface,
1554 DVTARGETDEVICE* ptd,
1557 LPCRECTL lprcBounds,
1558 LPCRECTL lprcWBounds,
1559 BOOL (CALLBACK *pfnContinue)(ULONG_PTR dwContinue),
1560 ULONG_PTR dwContinue)
1562 PresentationDataHeader presData;
1563 HMETAFILE presMetafile = 0;
1566 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1568 TRACE("(%p, %lx, %ld, %p, %p, %p, %p, %p, %p, %lx)\n",
1583 if (lprcBounds==NULL)
1584 return E_INVALIDARG;
1587 * First, we need to retrieve the dimensions of the
1588 * image in the metafile.
1590 hres = DataCache_ReadPresentationData(this,
1598 * Then, we can extract the metafile itself from the cached
1601 * FIXME Unless it isn't a metafile. I think it could be any CF_XXX type,
1602 * particularly CF_DIB.
1604 presMetafile = DataCache_ReadPresMetafile(this,
1608 * If we have a metafile, just draw baby...
1609 * We have to be careful not to modify the state of the
1612 if (presMetafile!=0)
1614 INT prevMapMode = SetMapMode(hdcDraw, MM_ANISOTROPIC);
1616 SIZE oldViewportExt;
1617 POINT oldViewportOrg;
1619 SetWindowExtEx(hdcDraw,
1620 presData.dwObjectExtentX,
1621 presData.dwObjectExtentY,
1624 SetViewportExtEx(hdcDraw,
1625 lprcBounds->right - lprcBounds->left,
1626 lprcBounds->bottom - lprcBounds->top,
1629 SetViewportOrgEx(hdcDraw,
1634 PlayMetaFile(hdcDraw, presMetafile);
1636 SetWindowExtEx(hdcDraw,
1641 SetViewportExtEx(hdcDraw,
1646 SetViewportOrgEx(hdcDraw,
1651 SetMapMode(hdcDraw, prevMapMode);
1653 DeleteMetaFile(presMetafile);
1659 static HRESULT WINAPI DataCache_GetColorSet(
1660 IViewObject2* iface,
1664 DVTARGETDEVICE* ptd,
1665 HDC hicTargetDevice,
1666 LOGPALETTE** ppColorSet)
1672 static HRESULT WINAPI DataCache_Freeze(
1673 IViewObject2* iface,
1683 static HRESULT WINAPI DataCache_Unfreeze(
1684 IViewObject2* iface,
1691 /************************************************************************
1692 * DataCache_SetAdvise (IViewObject2)
1694 * This sets-up an advisory sink with the data cache. When the object's
1695 * view changes, this sink is called.
1697 * See Windows documentation for more details on IViewObject2 methods.
1699 static HRESULT WINAPI DataCache_SetAdvise(
1700 IViewObject2* iface,
1703 IAdviseSink* pAdvSink)
1705 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1707 TRACE("(%p, %lx, %lx, %p)\n", iface, aspects, advf, pAdvSink);
1710 * A call to this function removes the previous sink
1712 if (this->sinkInterface != NULL)
1714 IAdviseSink_Release(this->sinkInterface);
1715 this->sinkInterface = NULL;
1716 this->sinkAspects = 0;
1717 this->sinkAdviseFlag = 0;
1721 * Now, setup the new one.
1725 this->sinkInterface = pAdvSink;
1726 this->sinkAspects = aspects;
1727 this->sinkAdviseFlag = advf;
1729 IAdviseSink_AddRef(this->sinkInterface);
1733 * When the ADVF_PRIMEFIRST flag is set, we have to advise the
1736 if (advf & ADVF_PRIMEFIRST)
1738 DataCache_FireOnViewChange(this,
1746 /************************************************************************
1747 * DataCache_GetAdvise (IViewObject2)
1749 * This method queries the current state of the advise sink
1750 * installed on the data cache.
1752 * See Windows documentation for more details on IViewObject2 methods.
1754 static HRESULT WINAPI DataCache_GetAdvise(
1755 IViewObject2* iface,
1758 IAdviseSink** ppAdvSink)
1760 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1762 TRACE("(%p, %p, %p, %p)\n", iface, pAspects, pAdvf, ppAdvSink);
1765 * Just copy all the requested values.
1768 *pAspects = this->sinkAspects;
1771 *pAdvf = this->sinkAdviseFlag;
1773 if (ppAdvSink!=NULL)
1775 IAdviseSink_QueryInterface(this->sinkInterface,
1783 /************************************************************************
1784 * DataCache_GetExtent (IViewObject2)
1786 * This method retrieves the "natural" size of this cached object.
1788 * See Windows documentation for more details on IViewObject2 methods.
1790 static HRESULT WINAPI DataCache_GetExtent(
1791 IViewObject2* iface,
1794 DVTARGETDEVICE* ptd,
1797 PresentationDataHeader presData;
1798 HRESULT hres = E_FAIL;
1800 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1802 TRACE("(%p, %lx, %ld, %p, %p)\n",
1803 iface, dwDrawAspect, lindex, ptd, lpsizel);
1812 * Initialize the out parameter.
1818 * This flag should be set to -1.
1821 FIXME("Unimplemented flag lindex = %ld\n", lindex);
1824 * Right now, we support only the callback from
1825 * the default handler.
1828 FIXME("Unimplemented ptd = %p\n", ptd);
1831 * Get the presentation information from the
1834 hres = DataCache_ReadPresentationData(this,
1838 if (SUCCEEDED(hres))
1840 lpsizel->cx = presData.dwObjectExtentX;
1841 lpsizel->cy = presData.dwObjectExtentY;
1845 * This method returns OLE_E_BLANK when it fails.
1854 /*********************************************************
1855 * Method implementation for the IOleCache2
1856 * part of the DataCache class.
1859 /************************************************************************
1860 * DataCache_IOleCache2_QueryInterface (IUnknown)
1862 * See Windows documentation for more details on IUnknown methods.
1864 static HRESULT WINAPI DataCache_IOleCache2_QueryInterface(
1869 _ICOM_THIS_From_IOleCache2(DataCache, iface);
1871 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1874 /************************************************************************
1875 * DataCache_IOleCache2_AddRef (IUnknown)
1877 * See Windows documentation for more details on IUnknown methods.
1879 static ULONG WINAPI DataCache_IOleCache2_AddRef(
1882 _ICOM_THIS_From_IOleCache2(DataCache, iface);
1884 return IUnknown_AddRef(this->outerUnknown);
1887 /************************************************************************
1888 * DataCache_IOleCache2_Release (IUnknown)
1890 * See Windows documentation for more details on IUnknown methods.
1892 static ULONG WINAPI DataCache_IOleCache2_Release(
1895 _ICOM_THIS_From_IOleCache2(DataCache, iface);
1897 return IUnknown_Release(this->outerUnknown);
1900 static HRESULT WINAPI DataCache_Cache(
1902 FORMATETC* pformatetc,
1904 DWORD* pdwConnection)
1910 static HRESULT WINAPI DataCache_Uncache(
1918 static HRESULT WINAPI DataCache_EnumCache(
1920 IEnumSTATDATA** ppenumSTATDATA)
1926 static HRESULT WINAPI DataCache_InitCache(
1928 IDataObject* pDataObject)
1934 static HRESULT WINAPI DataCache_IOleCache2_SetData(
1936 FORMATETC* pformatetc,
1944 static HRESULT WINAPI DataCache_UpdateCache(
1946 LPDATAOBJECT pDataObject,
1954 static HRESULT WINAPI DataCache_DiscardCache(
1956 DWORD dwDiscardOptions)
1963 /*********************************************************
1964 * Method implementation for the IOleCacheControl
1965 * part of the DataCache class.
1968 /************************************************************************
1969 * DataCache_IOleCacheControl_QueryInterface (IUnknown)
1971 * See Windows documentation for more details on IUnknown methods.
1973 static HRESULT WINAPI DataCache_IOleCacheControl_QueryInterface(
1974 IOleCacheControl* iface,
1978 _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
1980 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1983 /************************************************************************
1984 * DataCache_IOleCacheControl_AddRef (IUnknown)
1986 * See Windows documentation for more details on IUnknown methods.
1988 static ULONG WINAPI DataCache_IOleCacheControl_AddRef(
1989 IOleCacheControl* iface)
1991 _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
1993 return IUnknown_AddRef(this->outerUnknown);
1996 /************************************************************************
1997 * DataCache_IOleCacheControl_Release (IUnknown)
1999 * See Windows documentation for more details on IUnknown methods.
2001 static ULONG WINAPI DataCache_IOleCacheControl_Release(
2002 IOleCacheControl* iface)
2004 _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
2006 return IUnknown_Release(this->outerUnknown);
2009 static HRESULT WINAPI DataCache_OnRun(
2010 IOleCacheControl* iface,
2011 LPDATAOBJECT pDataObject)
2017 static HRESULT WINAPI DataCache_OnStop(
2018 IOleCacheControl* iface)