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.
53 #include "wine/unicode.h"
55 #include "wine/debug.h"
57 WINE_DEFAULT_DEBUG_CHANNEL(ole);
59 /****************************************************************************
60 * PresentationDataHeader
62 * This structure represents the header of the \002OlePresXXX stream in
63 * the OLE object strorage.
65 * Most fields are still unknown.
67 typedef struct PresentationDataHeader
69 DWORD unknown1; /* -1 */
70 DWORD unknown2; /* 3, possibly CF_METAFILEPICT */
71 DWORD unknown3; /* 4, possibly TYMED_ISTREAM */
73 DWORD unknown5; /* -1 */
76 DWORD unknown7; /* 0 */
77 DWORD dwObjectExtentX;
78 DWORD dwObjectExtentY;
80 } PresentationDataHeader;
82 /****************************************************************************
88 * List all interface VTables here
90 ICOM_VTABLE(IDataObject)* lpvtbl1;
91 ICOM_VTABLE(IUnknown)* lpvtbl2;
92 ICOM_VTABLE(IPersistStorage)* lpvtbl3;
93 ICOM_VTABLE(IViewObject2)* lpvtbl4;
94 ICOM_VTABLE(IOleCache2)* lpvtbl5;
95 ICOM_VTABLE(IOleCacheControl)* lpvtbl6;
98 * Reference count of this object
103 * IUnknown implementation of the outer object.
105 IUnknown* outerUnknown;
108 * This storage pointer is set through a call to
109 * IPersistStorage_Load. This is where the visual
110 * representation of the object is stored.
112 IStorage* presentationStorage;
115 * The user of this object can setup ONE advise sink
116 * connection with the object. These parameters describe
120 DWORD sinkAdviseFlag;
121 IAdviseSink* sinkInterface;
125 typedef struct DataCache DataCache;
128 * Here, I define utility macros to help with the casting of the
130 * There is a version to accomodate all of the VTables implemented
133 #define _ICOM_THIS_From_IDataObject(class,name) class* this = (class*)name;
134 #define _ICOM_THIS_From_NDIUnknown(class, name) class* this = (class*)(((char*)name)-sizeof(void*));
135 #define _ICOM_THIS_From_IPersistStorage(class, name) class* this = (class*)(((char*)name)-2*sizeof(void*));
136 #define _ICOM_THIS_From_IViewObject2(class, name) class* this = (class*)(((char*)name)-3*sizeof(void*));
137 #define _ICOM_THIS_From_IOleCache2(class, name) class* this = (class*)(((char*)name)-4*sizeof(void*));
138 #define _ICOM_THIS_From_IOleCacheControl(class, name) class* this = (class*)(((char*)name)-5*sizeof(void*));
141 * Prototypes for the methods of the DataCache class.
143 static DataCache* DataCache_Construct(REFCLSID clsid,
144 LPUNKNOWN pUnkOuter);
145 static void DataCache_Destroy(DataCache* ptrToDestroy);
146 static HRESULT DataCache_ReadPresentationData(DataCache* this,
148 PresentationDataHeader* header);
149 static HRESULT DataCache_OpenPresStream(DataCache *this,
152 static HMETAFILE DataCache_ReadPresMetafile(DataCache* this,
154 static void DataCache_FireOnViewChange(DataCache* this,
159 * Prototypes for the methods of the DataCache class
160 * that implement non delegating IUnknown methods.
162 static HRESULT WINAPI DataCache_NDIUnknown_QueryInterface(
166 static ULONG WINAPI DataCache_NDIUnknown_AddRef(
168 static ULONG WINAPI DataCache_NDIUnknown_Release(
172 * Prototypes for the methods of the DataCache class
173 * that implement IDataObject methods.
175 static HRESULT WINAPI DataCache_IDataObject_QueryInterface(
179 static ULONG WINAPI DataCache_IDataObject_AddRef(
181 static ULONG WINAPI DataCache_IDataObject_Release(
183 static HRESULT WINAPI DataCache_GetData(
185 LPFORMATETC pformatetcIn,
187 static HRESULT WINAPI DataCache_GetDataHere(
189 LPFORMATETC pformatetc,
191 static HRESULT WINAPI DataCache_QueryGetData(
193 LPFORMATETC pformatetc);
194 static HRESULT WINAPI DataCache_GetCanonicalFormatEtc(
196 LPFORMATETC pformatectIn,
197 LPFORMATETC pformatetcOut);
198 static HRESULT WINAPI DataCache_IDataObject_SetData(
200 LPFORMATETC pformatetc,
203 static HRESULT WINAPI DataCache_EnumFormatEtc(
206 IEnumFORMATETC** ppenumFormatEtc);
207 static HRESULT WINAPI DataCache_DAdvise(
209 FORMATETC* pformatetc,
211 IAdviseSink* pAdvSink,
212 DWORD* pdwConnection);
213 static HRESULT WINAPI DataCache_DUnadvise(
216 static HRESULT WINAPI DataCache_EnumDAdvise(
218 IEnumSTATDATA** ppenumAdvise);
221 * Prototypes for the methods of the DataCache class
222 * that implement IPersistStorage methods.
224 static HRESULT WINAPI DataCache_IPersistStorage_QueryInterface(
225 IPersistStorage* iface,
228 static ULONG WINAPI DataCache_IPersistStorage_AddRef(
229 IPersistStorage* iface);
230 static ULONG WINAPI DataCache_IPersistStorage_Release(
231 IPersistStorage* iface);
232 static HRESULT WINAPI DataCache_GetClassID(
233 IPersistStorage* iface,
235 static HRESULT WINAPI DataCache_IsDirty(
236 IPersistStorage* iface);
237 static HRESULT WINAPI DataCache_InitNew(
238 IPersistStorage* iface,
240 static HRESULT WINAPI DataCache_Load(
241 IPersistStorage* iface,
243 static HRESULT WINAPI DataCache_Save(
244 IPersistStorage* iface,
247 static HRESULT WINAPI DataCache_SaveCompleted(
248 IPersistStorage* iface,
250 static HRESULT WINAPI DataCache_HandsOffStorage(
251 IPersistStorage* iface);
254 * Prototypes for the methods of the DataCache class
255 * that implement IViewObject2 methods.
257 static HRESULT WINAPI DataCache_IViewObject2_QueryInterface(
261 static ULONG WINAPI DataCache_IViewObject2_AddRef(
262 IViewObject2* iface);
263 static ULONG WINAPI DataCache_IViewObject2_Release(
264 IViewObject2* iface);
265 static HRESULT WINAPI DataCache_Draw(
274 LPCRECTL lprcWBounds,
275 IVO_ContCallback pfnContinue,
277 static HRESULT WINAPI DataCache_GetColorSet(
284 LOGPALETTE** ppColorSet);
285 static HRESULT WINAPI DataCache_Freeze(
291 static HRESULT WINAPI DataCache_Unfreeze(
294 static HRESULT WINAPI DataCache_SetAdvise(
298 IAdviseSink* pAdvSink);
299 static HRESULT WINAPI DataCache_GetAdvise(
303 IAdviseSink** ppAdvSink);
304 static HRESULT WINAPI DataCache_GetExtent(
312 * Prototypes for the methods of the DataCache class
313 * that implement IOleCache2 methods.
315 static HRESULT WINAPI DataCache_IOleCache2_QueryInterface(
319 static ULONG WINAPI DataCache_IOleCache2_AddRef(
321 static ULONG WINAPI DataCache_IOleCache2_Release(
323 static HRESULT WINAPI DataCache_Cache(
325 FORMATETC* pformatetc,
327 DWORD* pdwConnection);
328 static HRESULT WINAPI DataCache_Uncache(
331 static HRESULT WINAPI DataCache_EnumCache(
333 IEnumSTATDATA** ppenumSTATDATA);
334 static HRESULT WINAPI DataCache_InitCache(
336 IDataObject* pDataObject);
337 static HRESULT WINAPI DataCache_IOleCache2_SetData(
339 FORMATETC* pformatetc,
342 static HRESULT WINAPI DataCache_UpdateCache(
344 LPDATAOBJECT pDataObject,
347 static HRESULT WINAPI DataCache_DiscardCache(
349 DWORD dwDiscardOptions);
352 * Prototypes for the methods of the DataCache class
353 * that implement IOleCacheControl methods.
355 static HRESULT WINAPI DataCache_IOleCacheControl_QueryInterface(
356 IOleCacheControl* iface,
359 static ULONG WINAPI DataCache_IOleCacheControl_AddRef(
360 IOleCacheControl* iface);
361 static ULONG WINAPI DataCache_IOleCacheControl_Release(
362 IOleCacheControl* iface);
363 static HRESULT WINAPI DataCache_OnRun(
364 IOleCacheControl* iface,
365 LPDATAOBJECT pDataObject);
366 static HRESULT WINAPI DataCache_OnStop(
367 IOleCacheControl* iface);
370 * Virtual function tables for the DataCache class.
372 static ICOM_VTABLE(IUnknown) DataCache_NDIUnknown_VTable =
374 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
375 DataCache_NDIUnknown_QueryInterface,
376 DataCache_NDIUnknown_AddRef,
377 DataCache_NDIUnknown_Release
380 static ICOM_VTABLE(IDataObject) DataCache_IDataObject_VTable =
382 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
383 DataCache_IDataObject_QueryInterface,
384 DataCache_IDataObject_AddRef,
385 DataCache_IDataObject_Release,
387 DataCache_GetDataHere,
388 DataCache_QueryGetData,
389 DataCache_GetCanonicalFormatEtc,
390 DataCache_IDataObject_SetData,
391 DataCache_EnumFormatEtc,
394 DataCache_EnumDAdvise
397 static ICOM_VTABLE(IPersistStorage) DataCache_IPersistStorage_VTable =
399 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
400 DataCache_IPersistStorage_QueryInterface,
401 DataCache_IPersistStorage_AddRef,
402 DataCache_IPersistStorage_Release,
403 DataCache_GetClassID,
408 DataCache_SaveCompleted,
409 DataCache_HandsOffStorage
412 static ICOM_VTABLE(IViewObject2) DataCache_IViewObject2_VTable =
414 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
415 DataCache_IViewObject2_QueryInterface,
416 DataCache_IViewObject2_AddRef,
417 DataCache_IViewObject2_Release,
419 DataCache_GetColorSet,
427 static ICOM_VTABLE(IOleCache2) DataCache_IOleCache2_VTable =
429 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
430 DataCache_IOleCache2_QueryInterface,
431 DataCache_IOleCache2_AddRef,
432 DataCache_IOleCache2_Release,
437 DataCache_IOleCache2_SetData,
438 DataCache_UpdateCache,
439 DataCache_DiscardCache
442 static ICOM_VTABLE(IOleCacheControl) DataCache_IOleCacheControl_VTable =
444 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
445 DataCache_IOleCacheControl_QueryInterface,
446 DataCache_IOleCacheControl_AddRef,
447 DataCache_IOleCacheControl_Release,
452 /******************************************************************************
453 * CreateDataCache [OLE32.54]
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.s.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.s.LowPart = 0;
765 offset.s.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.s.HighPart = 0;
835 offset.s.LowPart = sizeof(PresentationDataHeader);
843 streamInfo.cbSize.s.LowPart -= offset.s.LowPart;
846 * Allocate a buffer for the metafile bits.
848 metafileBits = HeapAlloc(GetProcessHeap(),
850 streamInfo.cbSize.s.LowPart);
853 * Read the metafile bits.
858 streamInfo.cbSize.s.LowPart,
862 * Create a metafile with those bits.
866 newMetafile = SetMetaFileBitsEx(streamInfo.cbSize.s.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);
979 /************************************************************************
980 * DataCache_NDIUnknown_Release (IUnknown)
982 * See Windows documentation for more details on IUnknown methods.
984 * This version of QueryInterface will not delegate it's implementation
985 * to the outer unknown.
987 static ULONG WINAPI DataCache_NDIUnknown_Release(
990 _ICOM_THIS_From_NDIUnknown(DataCache, iface);
993 * Decrease the reference count on this object.
998 * If the reference count goes down to 0, perform suicide.
1002 DataCache_Destroy(this);
1010 /*********************************************************
1011 * Method implementation for the IDataObject
1012 * part of the DataCache class.
1015 /************************************************************************
1016 * DataCache_IDataObject_QueryInterface (IUnknown)
1018 * See Windows documentation for more details on IUnknown methods.
1020 static HRESULT WINAPI DataCache_IDataObject_QueryInterface(
1025 _ICOM_THIS_From_IDataObject(DataCache, iface);
1027 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1030 /************************************************************************
1031 * DataCache_IDataObject_AddRef (IUnknown)
1033 * See Windows documentation for more details on IUnknown methods.
1035 static ULONG WINAPI DataCache_IDataObject_AddRef(
1038 _ICOM_THIS_From_IDataObject(DataCache, iface);
1040 return IUnknown_AddRef(this->outerUnknown);
1043 /************************************************************************
1044 * DataCache_IDataObject_Release (IUnknown)
1046 * See Windows documentation for more details on IUnknown methods.
1048 static ULONG WINAPI DataCache_IDataObject_Release(
1051 _ICOM_THIS_From_IDataObject(DataCache, iface);
1053 return IUnknown_Release(this->outerUnknown);
1056 /************************************************************************
1059 * Get Data from a source dataobject using format pformatetcIn->cfFormat
1060 * See Windows documentation for more details on GetData.
1061 * TODO: Currently only CF_METAFILEPICT is implemented
1063 static HRESULT WINAPI DataCache_GetData(
1065 LPFORMATETC pformatetcIn,
1069 HRESULT hrRet = E_UNEXPECTED;
1070 IPersistStorage *pPersistStorage = 0;
1071 IStorage *pStorage = 0;
1072 IStream *pStream = 0;
1073 OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
1074 HGLOBAL hGlobalMF = 0;
1076 PresentationDataHeader pdh;
1077 METAFILEPICT *mfPict;
1078 HMETAFILE hMetaFile = 0;
1080 if (pformatetcIn->cfFormat == CF_METAFILEPICT)
1082 /* Get the Persist Storage */
1084 hr = IDataObject_QueryInterface(iface, &IID_IPersistStorage, (void**)&pPersistStorage);
1089 /* Create a doc file to copy the doc to a storage */
1091 hr = StgCreateDocfile(NULL, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &pStorage);
1096 /* Save it to storage */
1098 hr = OleSave(pPersistStorage, pStorage, FALSE);
1103 /* Open the Presentation data srteam */
1105 hr = IStorage_OpenStream(pStorage, name, 0, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &pStream);
1110 /* Read the presentation header */
1112 hr = IStream_Read(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
1117 mfBits = HeapAlloc(GetProcessHeap(), 0, pdh.dwSize);
1119 /* Read the Metafile bits */
1121 hr = IStream_Read(pStream, mfBits, pdh.dwSize, NULL);
1126 /* Create the metafile and place it in the STGMEDIUM structure */
1128 hMetaFile = SetMetaFileBitsEx(pdh.dwSize, mfBits);
1130 hGlobalMF = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, sizeof(METAFILEPICT));
1131 mfPict = (METAFILEPICT *)GlobalLock(hGlobalMF);
1132 mfPict->hMF = hMetaFile;
1134 GlobalUnlock(hGlobalMF);
1136 pmedium->u.hGlobal = hGlobalMF;
1137 pmedium->tymed = TYMED_MFPICT;
1143 HeapFree(GetProcessHeap(), 0, mfBits);
1146 IStream_Release(pStream);
1149 IStorage_Release(pStorage);
1151 if (pPersistStorage)
1152 IPersistStorage_Release(pPersistStorage);
1157 /* TODO: Other formats are not implemented */
1162 static HRESULT WINAPI DataCache_GetDataHere(
1164 LPFORMATETC pformatetc,
1171 static HRESULT WINAPI DataCache_QueryGetData(
1173 LPFORMATETC pformatetc)
1179 /************************************************************************
1180 * DataCache_EnumFormatEtc (IDataObject)
1182 * The data cache doesn't implement this method.
1184 * See Windows documentation for more details on IDataObject methods.
1186 static HRESULT WINAPI DataCache_GetCanonicalFormatEtc(
1188 LPFORMATETC pformatectIn,
1189 LPFORMATETC pformatetcOut)
1195 /************************************************************************
1196 * DataCache_IDataObject_SetData (IDataObject)
1198 * This method is delegated to the IOleCache2 implementation.
1200 * See Windows documentation for more details on IDataObject methods.
1202 static HRESULT WINAPI DataCache_IDataObject_SetData(
1204 LPFORMATETC pformatetc,
1208 IOleCache2* oleCache = NULL;
1211 TRACE("(%p, %p, %p, %d)\n", iface, pformatetc, pmedium, fRelease);
1213 hres = IDataObject_QueryInterface(iface, &IID_IOleCache2, (void**)&oleCache);
1216 return E_UNEXPECTED;
1218 hres = IOleCache2_SetData(oleCache, pformatetc, pmedium, fRelease);
1220 IOleCache2_Release(oleCache);
1225 /************************************************************************
1226 * DataCache_EnumFormatEtc (IDataObject)
1228 * The data cache doesn't implement this method.
1230 * See Windows documentation for more details on IDataObject methods.
1232 static HRESULT WINAPI DataCache_EnumFormatEtc(
1235 IEnumFORMATETC** ppenumFormatEtc)
1241 /************************************************************************
1242 * DataCache_DAdvise (IDataObject)
1244 * The data cache doesn't support connections.
1246 * See Windows documentation for more details on IDataObject methods.
1248 static HRESULT WINAPI DataCache_DAdvise(
1250 FORMATETC* pformatetc,
1252 IAdviseSink* pAdvSink,
1253 DWORD* pdwConnection)
1256 return OLE_E_ADVISENOTSUPPORTED;
1259 /************************************************************************
1260 * DataCache_DUnadvise (IDataObject)
1262 * The data cache doesn't support connections.
1264 * See Windows documentation for more details on IDataObject methods.
1266 static HRESULT WINAPI DataCache_DUnadvise(
1271 return OLE_E_NOCONNECTION;
1274 /************************************************************************
1275 * DataCache_EnumDAdvise (IDataObject)
1277 * The data cache doesn't support connections.
1279 * See Windows documentation for more details on IDataObject methods.
1281 static HRESULT WINAPI DataCache_EnumDAdvise(
1283 IEnumSTATDATA** ppenumAdvise)
1286 return OLE_E_ADVISENOTSUPPORTED;
1289 /*********************************************************
1290 * Method implementation for the IDataObject
1291 * part of the DataCache class.
1294 /************************************************************************
1295 * DataCache_IPersistStorage_QueryInterface (IUnknown)
1297 * See Windows documentation for more details on IUnknown methods.
1299 static HRESULT WINAPI DataCache_IPersistStorage_QueryInterface(
1300 IPersistStorage* iface,
1304 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1306 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1309 /************************************************************************
1310 * DataCache_IPersistStorage_AddRef (IUnknown)
1312 * See Windows documentation for more details on IUnknown methods.
1314 static ULONG WINAPI DataCache_IPersistStorage_AddRef(
1315 IPersistStorage* iface)
1317 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1319 return IUnknown_AddRef(this->outerUnknown);
1322 /************************************************************************
1323 * DataCache_IPersistStorage_Release (IUnknown)
1325 * See Windows documentation for more details on IUnknown methods.
1327 static ULONG WINAPI DataCache_IPersistStorage_Release(
1328 IPersistStorage* iface)
1330 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1332 return IUnknown_Release(this->outerUnknown);
1335 /************************************************************************
1336 * DataCache_GetClassID (IPersistStorage)
1338 * The data cache doesn't implement this method.
1340 * See Windows documentation for more details on IPersistStorage methods.
1342 static HRESULT WINAPI DataCache_GetClassID(
1343 IPersistStorage* iface,
1346 TRACE("(%p, %p)\n", iface, pClassID);
1350 /************************************************************************
1351 * DataCache_IsDirty (IPersistStorage)
1353 * Until we actully connect to a running object and retrieve new
1354 * information to it, we never get dirty.
1356 * See Windows documentation for more details on IPersistStorage methods.
1358 static HRESULT WINAPI DataCache_IsDirty(
1359 IPersistStorage* iface)
1361 TRACE("(%p)\n", iface);
1366 /************************************************************************
1367 * DataCache_InitNew (IPersistStorage)
1369 * The data cache implementation of IPersistStorage_InitNew simply stores
1370 * the storage pointer.
1372 * See Windows documentation for more details on IPersistStorage methods.
1374 static HRESULT WINAPI DataCache_InitNew(
1375 IPersistStorage* iface,
1378 TRACE("(%p, %p)\n", iface, pStg);
1380 return DataCache_Load(iface, pStg);
1383 /************************************************************************
1384 * DataCache_Load (IPersistStorage)
1386 * The data cache implementation of IPersistStorage_Load doesn't
1387 * actually load anything. Instead, it holds on to the storage pointer
1388 * and it will load the presentation information when the
1389 * IDataObject_GetData or IViewObject2_Draw methods are called.
1391 * See Windows documentation for more details on IPersistStorage methods.
1393 static HRESULT WINAPI DataCache_Load(
1394 IPersistStorage* iface,
1397 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1399 TRACE("(%p, %p)\n", iface, pStg);
1401 if (this->presentationStorage != NULL)
1403 IStorage_Release(this->presentationStorage);
1406 this->presentationStorage = pStg;
1408 if (this->presentationStorage != NULL)
1410 IStorage_AddRef(this->presentationStorage);
1415 /************************************************************************
1416 * DataCache_Save (IPersistStorage)
1418 * Until we actully connect to a running object and retrieve new
1419 * information to it, we never have to save anything. However, it is
1420 * our responsability to copy the information when saving to a new
1423 * See Windows documentation for more details on IPersistStorage methods.
1425 static HRESULT WINAPI DataCache_Save(
1426 IPersistStorage* iface,
1430 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1432 TRACE("(%p, %p, %d)\n", iface, pStg, fSameAsLoad);
1434 if ( (!fSameAsLoad) &&
1435 (this->presentationStorage!=NULL) )
1437 return IStorage_CopyTo(this->presentationStorage,
1447 /************************************************************************
1448 * DataCache_SaveCompleted (IPersistStorage)
1450 * This method is called to tell the cache to release the storage
1451 * pointer it's currentlu holding.
1453 * See Windows documentation for more details on IPersistStorage methods.
1455 static HRESULT WINAPI DataCache_SaveCompleted(
1456 IPersistStorage* iface,
1459 TRACE("(%p, %p)\n", iface, pStgNew);
1464 * First, make sure we get our hands off any storage we have.
1467 DataCache_HandsOffStorage(iface);
1470 * Then, attach to the new storage.
1473 DataCache_Load(iface, pStgNew);
1479 /************************************************************************
1480 * DataCache_HandsOffStorage (IPersistStorage)
1482 * This method is called to tell the cache to release the storage
1483 * pointer it's currentlu holding.
1485 * See Windows documentation for more details on IPersistStorage methods.
1487 static HRESULT WINAPI DataCache_HandsOffStorage(
1488 IPersistStorage* iface)
1490 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1492 TRACE("(%p)\n", iface);
1494 if (this->presentationStorage != NULL)
1496 IStorage_Release(this->presentationStorage);
1497 this->presentationStorage = NULL;
1503 /*********************************************************
1504 * Method implementation for the IViewObject2
1505 * part of the DataCache class.
1508 /************************************************************************
1509 * DataCache_IViewObject2_QueryInterface (IUnknown)
1511 * See Windows documentation for more details on IUnknown methods.
1513 static HRESULT WINAPI DataCache_IViewObject2_QueryInterface(
1514 IViewObject2* iface,
1518 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1520 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1523 /************************************************************************
1524 * DataCache_IViewObject2_AddRef (IUnknown)
1526 * See Windows documentation for more details on IUnknown methods.
1528 static ULONG WINAPI DataCache_IViewObject2_AddRef(
1529 IViewObject2* iface)
1531 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1533 return IUnknown_AddRef(this->outerUnknown);
1536 /************************************************************************
1537 * DataCache_IViewObject2_Release (IUnknown)
1539 * See Windows documentation for more details on IUnknown methods.
1541 static ULONG WINAPI DataCache_IViewObject2_Release(
1542 IViewObject2* iface)
1544 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1546 return IUnknown_Release(this->outerUnknown);
1549 /************************************************************************
1550 * DataCache_Draw (IViewObject2)
1552 * This method will draw the cached representation of the object
1553 * to the given device context.
1555 * See Windows documentation for more details on IViewObject2 methods.
1557 static HRESULT WINAPI DataCache_Draw(
1558 IViewObject2* iface,
1562 DVTARGETDEVICE* ptd,
1565 LPCRECTL lprcBounds,
1566 LPCRECTL lprcWBounds,
1567 IVO_ContCallback pfnContinue,
1570 PresentationDataHeader presData;
1571 HMETAFILE presMetafile = 0;
1574 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1576 TRACE("(%p, %lx, %ld, %p, %p, %p, %p, %p, %p, %lx)\n",
1591 if (lprcBounds==NULL)
1592 return E_INVALIDARG;
1595 * First, we need to retrieve the dimensions of the
1596 * image in the metafile.
1598 hres = DataCache_ReadPresentationData(this,
1606 * Then, we can extract the metafile itself from the cached
1609 * FIXME Unless it isn't a metafile. I think it could be any CF_XXX type,
1610 * particularly CF_DIB.
1612 presMetafile = DataCache_ReadPresMetafile(this,
1616 * If we have a metafile, just draw baby...
1617 * We have to be careful not to modify the state of the
1620 if (presMetafile!=0)
1622 INT prevMapMode = SetMapMode(hdcDraw, MM_ANISOTROPIC);
1624 SIZE oldViewportExt;
1625 POINT oldViewportOrg;
1627 SetWindowExtEx(hdcDraw,
1628 presData.dwObjectExtentX,
1629 presData.dwObjectExtentY,
1632 SetViewportExtEx(hdcDraw,
1633 lprcBounds->right - lprcBounds->left,
1634 lprcBounds->bottom - lprcBounds->top,
1637 SetViewportOrgEx(hdcDraw,
1642 PlayMetaFile(hdcDraw, presMetafile);
1644 SetWindowExtEx(hdcDraw,
1649 SetViewportExtEx(hdcDraw,
1654 SetViewportOrgEx(hdcDraw,
1659 SetMapMode(hdcDraw, prevMapMode);
1661 DeleteMetaFile(presMetafile);
1667 static HRESULT WINAPI DataCache_GetColorSet(
1668 IViewObject2* iface,
1672 DVTARGETDEVICE* ptd,
1673 HDC hicTargetDevice,
1674 LOGPALETTE** ppColorSet)
1680 static HRESULT WINAPI DataCache_Freeze(
1681 IViewObject2* iface,
1691 static HRESULT WINAPI DataCache_Unfreeze(
1692 IViewObject2* iface,
1699 /************************************************************************
1700 * DataCache_SetAdvise (IViewObject2)
1702 * This sets-up an advisory sink with the data cache. When the object's
1703 * view changes, this sink is called.
1705 * See Windows documentation for more details on IViewObject2 methods.
1707 static HRESULT WINAPI DataCache_SetAdvise(
1708 IViewObject2* iface,
1711 IAdviseSink* pAdvSink)
1713 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1715 TRACE("(%p, %lx, %lx, %p)\n", iface, aspects, advf, pAdvSink);
1718 * A call to this function removes the previous sink
1720 if (this->sinkInterface != NULL)
1722 IAdviseSink_Release(this->sinkInterface);
1723 this->sinkInterface = NULL;
1724 this->sinkAspects = 0;
1725 this->sinkAdviseFlag = 0;
1729 * Now, setup the new one.
1733 this->sinkInterface = pAdvSink;
1734 this->sinkAspects = aspects;
1735 this->sinkAdviseFlag = advf;
1737 IAdviseSink_AddRef(this->sinkInterface);
1741 * When the ADVF_PRIMEFIRST flag is set, we have to advise the
1744 if (advf & ADVF_PRIMEFIRST)
1746 DataCache_FireOnViewChange(this,
1754 /************************************************************************
1755 * DataCache_GetAdvise (IViewObject2)
1757 * This method queries the current state of the advise sink
1758 * installed on the data cache.
1760 * See Windows documentation for more details on IViewObject2 methods.
1762 static HRESULT WINAPI DataCache_GetAdvise(
1763 IViewObject2* iface,
1766 IAdviseSink** ppAdvSink)
1768 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1770 TRACE("(%p, %p, %p, %p)\n", iface, pAspects, pAdvf, ppAdvSink);
1773 * Just copy all the requested values.
1776 *pAspects = this->sinkAspects;
1779 *pAdvf = this->sinkAdviseFlag;
1781 if (ppAdvSink!=NULL)
1783 IAdviseSink_QueryInterface(this->sinkInterface,
1791 /************************************************************************
1792 * DataCache_GetExtent (IViewObject2)
1794 * This method retrieves the "natural" size of this cached object.
1796 * See Windows documentation for more details on IViewObject2 methods.
1798 static HRESULT WINAPI DataCache_GetExtent(
1799 IViewObject2* iface,
1802 DVTARGETDEVICE* ptd,
1805 PresentationDataHeader presData;
1806 HRESULT hres = E_FAIL;
1808 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1810 TRACE("(%p, %lx, %ld, %p, %p)\n",
1811 iface, dwDrawAspect, lindex, ptd, lpsizel);
1820 * Initialize the out parameter.
1826 * This flag should be set to -1.
1829 FIXME("Unimplemented flag lindex = %ld\n", lindex);
1832 * Right now, we suport only the callback from
1833 * the default handler.
1836 FIXME("Unimplemented ptd = %p\n", ptd);
1839 * Get the presentation information from the
1842 hres = DataCache_ReadPresentationData(this,
1846 if (SUCCEEDED(hres))
1848 lpsizel->cx = presData.dwObjectExtentX;
1849 lpsizel->cy = presData.dwObjectExtentY;
1853 * This method returns OLE_E_BLANK when it fails.
1862 /*********************************************************
1863 * Method implementation for the IOleCache2
1864 * part of the DataCache class.
1867 /************************************************************************
1868 * DataCache_IOleCache2_QueryInterface (IUnknown)
1870 * See Windows documentation for more details on IUnknown methods.
1872 static HRESULT WINAPI DataCache_IOleCache2_QueryInterface(
1877 _ICOM_THIS_From_IOleCache2(DataCache, iface);
1879 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1882 /************************************************************************
1883 * DataCache_IOleCache2_AddRef (IUnknown)
1885 * See Windows documentation for more details on IUnknown methods.
1887 static ULONG WINAPI DataCache_IOleCache2_AddRef(
1890 _ICOM_THIS_From_IOleCache2(DataCache, iface);
1892 return IUnknown_AddRef(this->outerUnknown);
1895 /************************************************************************
1896 * DataCache_IOleCache2_Release (IUnknown)
1898 * See Windows documentation for more details on IUnknown methods.
1900 static ULONG WINAPI DataCache_IOleCache2_Release(
1903 _ICOM_THIS_From_IOleCache2(DataCache, iface);
1905 return IUnknown_Release(this->outerUnknown);
1908 static HRESULT WINAPI DataCache_Cache(
1910 FORMATETC* pformatetc,
1912 DWORD* pdwConnection)
1918 static HRESULT WINAPI DataCache_Uncache(
1926 static HRESULT WINAPI DataCache_EnumCache(
1928 IEnumSTATDATA** ppenumSTATDATA)
1934 static HRESULT WINAPI DataCache_InitCache(
1936 IDataObject* pDataObject)
1942 static HRESULT WINAPI DataCache_IOleCache2_SetData(
1944 FORMATETC* pformatetc,
1952 static HRESULT WINAPI DataCache_UpdateCache(
1954 LPDATAOBJECT pDataObject,
1962 static HRESULT WINAPI DataCache_DiscardCache(
1964 DWORD dwDiscardOptions)
1971 /*********************************************************
1972 * Method implementation for the IOleCacheControl
1973 * part of the DataCache class.
1976 /************************************************************************
1977 * DataCache_IOleCacheControl_QueryInterface (IUnknown)
1979 * See Windows documentation for more details on IUnknown methods.
1981 static HRESULT WINAPI DataCache_IOleCacheControl_QueryInterface(
1982 IOleCacheControl* iface,
1986 _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
1988 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1991 /************************************************************************
1992 * DataCache_IOleCacheControl_AddRef (IUnknown)
1994 * See Windows documentation for more details on IUnknown methods.
1996 static ULONG WINAPI DataCache_IOleCacheControl_AddRef(
1997 IOleCacheControl* iface)
1999 _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
2001 return IUnknown_AddRef(this->outerUnknown);
2004 /************************************************************************
2005 * DataCache_IOleCacheControl_Release (IUnknown)
2007 * See Windows documentation for more details on IUnknown methods.
2009 static ULONG WINAPI DataCache_IOleCacheControl_Release(
2010 IOleCacheControl* iface)
2012 _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
2014 return IUnknown_Release(this->outerUnknown);
2017 static HRESULT WINAPI DataCache_OnRun(
2018 IOleCacheControl* iface,
2019 LPDATAOBJECT pDataObject)
2025 static HRESULT WINAPI DataCache_OnStop(
2026 IOleCacheControl* iface)