4 * Copyright 1999 Francis Beaudet
7 * The OLE2 data cache supports a whole whack of
8 * interfaces including:
9 * IDataObject, IPersistStorage, IViewObject2,
10 * IOleCache2 and IOleCacheControl.
12 * Most of the implementation details are taken from: Inside OLE
13 * second edition by Kraig Brockschmidt,
16 * - This implementation of the datacache will let your application
17 * load documents that have embedded OLE objects in them and it will
18 * also retrieve the metafile representation of those objects.
19 * - This implementation of the datacache will also allow your
20 * application to save new documents with OLE objects in them.
21 * - The main thing that it doesn't do is allow you to activate
22 * or modify the OLE objects in any way.
23 * - I haven't found any good documentation on the real usage of
24 * the streams created by the data cache. In particular, How to
25 * determine what the XXX stands for in the stream name
26 * "\002OlePresXXX". It appears to just be a counter.
27 * - Also, I don't know the real content of the presentation stream
28 * header. I was able to figure-out where the extent of the object
29 * was stored and the aspect, but that's about it.
37 #include "wine/obj_oleview.h"
38 #include "wine/obj_cache.h"
39 #include "debugtools.h"
41 DEFAULT_DEBUG_CHANNEL(ole
);
43 /****************************************************************************
44 * PresentationDataHeader
46 * This structure represents the header of the \002OlePresXXX stream in
47 * the OLE object strorage.
49 * Most fields are still unknown.
51 typedef struct PresentationDataHeader
53 DWORD unknown1
; /* -1 */
54 DWORD unknown2
; /* 3, possibly CF_METAFILEPICT */
55 DWORD unknown3
; /* 4, possibly TYMED_ISTREAM */
57 DWORD unknown5
; /* -1 */
60 DWORD unknown7
; /* 0 */
64 } PresentationDataHeader
;
66 /****************************************************************************
72 * List all interface VTables here
74 ICOM_VTABLE(IDataObject
)* lpvtbl1
;
75 ICOM_VTABLE(IUnknown
)* lpvtbl2
;
76 ICOM_VTABLE(IPersistStorage
)* lpvtbl3
;
77 ICOM_VTABLE(IViewObject2
)* lpvtbl4
;
78 ICOM_VTABLE(IOleCache2
)* lpvtbl5
;
79 ICOM_VTABLE(IOleCacheControl
)* lpvtbl6
;
82 * Reference count of this object
87 * IUnknown implementation of the outer object.
89 IUnknown
* outerUnknown
;
92 * This storage pointer is set through a call to
93 * IPersistStorage_Load. This is where the visual
94 * representation of the object is stored.
96 IStorage
* presentationStorage
;
99 * The user of this object can setup ONE advise sink
100 * connection with the object. These parameters describe
104 DWORD sinkAdviseFlag
;
105 IAdviseSink
* sinkInterface
;
109 typedef struct DataCache DataCache
;
112 * Here, I define utility macros to help with the casting of the
114 * There is a version to accomodate all of the VTables implemented
117 #define _ICOM_THIS_From_IDataObject(class,name) class* this = (class*)name;
118 #define _ICOM_THIS_From_NDIUnknown(class, name) class* this = (class*)(((char*)name)-sizeof(void*));
119 #define _ICOM_THIS_From_IPersistStorage(class, name) class* this = (class*)(((char*)name)-2*sizeof(void*));
120 #define _ICOM_THIS_From_IViewObject2(class, name) class* this = (class*)(((char*)name)-3*sizeof(void*));
121 #define _ICOM_THIS_From_IOleCache2(class, name) class* this = (class*)(((char*)name)-4*sizeof(void*));
122 #define _ICOM_THIS_From_IOleCacheControl(class, name) class* this = (class*)(((char*)name)-5*sizeof(void*));
125 * Prototypes for the methods of the DataCache class.
127 static DataCache
* DataCache_Construct(REFCLSID clsid
,
128 LPUNKNOWN pUnkOuter
);
129 static void DataCache_Destroy(DataCache
* ptrToDestroy
);
130 static HRESULT
DataCache_ReadPresentationData(DataCache
* this,
132 PresentationDataHeader
* header
);
133 static HRESULT
DataCache_OpenPresStream(DataCache
*this,
136 static HMETAFILE
DataCache_ReadPresMetafile(DataCache
* this,
138 static void DataCache_FireOnViewChange(DataCache
* this,
143 * Prototypes for the methods of the DataCache class
144 * that implement non delegating IUnknown methods.
146 static HRESULT WINAPI
DataCache_NDIUnknown_QueryInterface(
150 static ULONG WINAPI
DataCache_NDIUnknown_AddRef(
152 static ULONG WINAPI
DataCache_NDIUnknown_Release(
156 * Prototypes for the methods of the DataCache class
157 * that implement IDataObject methods.
159 static HRESULT WINAPI
DataCache_IDataObject_QueryInterface(
163 static ULONG WINAPI
DataCache_IDataObject_AddRef(
165 static ULONG WINAPI
DataCache_IDataObject_Release(
167 static HRESULT WINAPI
DataCache_GetData(
169 LPFORMATETC pformatetcIn
,
171 static HRESULT WINAPI
DataCache_GetDataHere(
173 LPFORMATETC pformatetc
,
175 static HRESULT WINAPI
DataCache_QueryGetData(
177 LPFORMATETC pformatetc
);
178 static HRESULT WINAPI
DataCache_GetCanonicalFormatEtc(
180 LPFORMATETC pformatectIn
,
181 LPFORMATETC pformatetcOut
);
182 static HRESULT WINAPI
DataCache_IDataObject_SetData(
184 LPFORMATETC pformatetc
,
187 static HRESULT WINAPI
DataCache_EnumFormatEtc(
190 IEnumFORMATETC
** ppenumFormatEtc
);
191 static HRESULT WINAPI
DataCache_DAdvise(
193 FORMATETC
* pformatetc
,
195 IAdviseSink
* pAdvSink
,
196 DWORD
* pdwConnection
);
197 static HRESULT WINAPI
DataCache_DUnadvise(
200 static HRESULT WINAPI
DataCache_EnumDAdvise(
202 IEnumSTATDATA
** ppenumAdvise
);
205 * Prototypes for the methods of the DataCache class
206 * that implement IPersistStorage methods.
208 static HRESULT WINAPI
DataCache_IPersistStorage_QueryInterface(
209 IPersistStorage
* iface
,
212 static ULONG WINAPI
DataCache_IPersistStorage_AddRef(
213 IPersistStorage
* iface
);
214 static ULONG WINAPI
DataCache_IPersistStorage_Release(
215 IPersistStorage
* iface
);
216 static HRESULT WINAPI
DataCache_GetClassID(
217 IPersistStorage
* iface
,
219 static HRESULT WINAPI
DataCache_IsDirty(
220 IPersistStorage
* iface
);
221 static HRESULT WINAPI
DataCache_InitNew(
222 IPersistStorage
* iface
,
224 static HRESULT WINAPI
DataCache_Load(
225 IPersistStorage
* iface
,
227 static HRESULT WINAPI
DataCache_Save(
228 IPersistStorage
* iface
,
231 static HRESULT WINAPI
DataCache_SaveCompleted(
232 IPersistStorage
* iface
,
234 static HRESULT WINAPI
DataCache_HandsOffStorage(
235 IPersistStorage
* iface
);
238 * Prototypes for the methods of the DataCache class
239 * that implement IViewObject2 methods.
241 static HRESULT WINAPI
DataCache_IViewObject2_QueryInterface(
245 static ULONG WINAPI
DataCache_IViewObject2_AddRef(
246 IViewObject2
* iface
);
247 static ULONG WINAPI
DataCache_IViewObject2_Release(
248 IViewObject2
* iface
);
249 static HRESULT WINAPI
DataCache_Draw(
258 LPCRECTL lprcWBounds
,
259 IVO_ContCallback pfnContinue
,
261 static HRESULT WINAPI
DataCache_GetColorSet(
268 LOGPALETTE
** ppColorSet
);
269 static HRESULT WINAPI
DataCache_Freeze(
275 static HRESULT WINAPI
DataCache_Unfreeze(
278 static HRESULT WINAPI
DataCache_SetAdvise(
282 IAdviseSink
* pAdvSink
);
283 static HRESULT WINAPI
DataCache_GetAdvise(
287 IAdviseSink
** ppAdvSink
);
288 static HRESULT WINAPI
DataCache_GetExtent(
296 * Prototypes for the methods of the DataCache class
297 * that implement IOleCache2 methods.
299 static HRESULT WINAPI
DataCache_IOleCache2_QueryInterface(
303 static ULONG WINAPI
DataCache_IOleCache2_AddRef(
305 static ULONG WINAPI
DataCache_IOleCache2_Release(
307 static HRESULT WINAPI
DataCache_Cache(
309 FORMATETC
* pformatetc
,
311 DWORD
* pdwConnection
);
312 static HRESULT WINAPI
DataCache_Uncache(
315 static HRESULT WINAPI
DataCache_EnumCache(
317 IEnumSTATDATA
** ppenumSTATDATA
);
318 static HRESULT WINAPI
DataCache_InitCache(
320 IDataObject
* pDataObject
);
321 static HRESULT WINAPI
DataCache_IOleCache2_SetData(
323 FORMATETC
* pformatetc
,
326 static HRESULT WINAPI
DataCache_UpdateCache(
328 LPDATAOBJECT pDataObject
,
331 static HRESULT WINAPI
DataCache_DiscardCache(
333 DWORD dwDiscardOptions
);
336 * Prototypes for the methods of the DataCache class
337 * that implement IOleCacheControl methods.
339 static HRESULT WINAPI
DataCache_IOleCacheControl_QueryInterface(
340 IOleCacheControl
* iface
,
343 static ULONG WINAPI
DataCache_IOleCacheControl_AddRef(
344 IOleCacheControl
* iface
);
345 static ULONG WINAPI
DataCache_IOleCacheControl_Release(
346 IOleCacheControl
* iface
);
347 static HRESULT WINAPI
DataCache_OnRun(
348 IOleCacheControl
* iface
,
349 LPDATAOBJECT pDataObject
);
350 static HRESULT WINAPI
DataCache_OnStop(
351 IOleCacheControl
* iface
);
354 * Virtual function tables for the DataCache class.
356 static ICOM_VTABLE(IUnknown
) DataCache_NDIUnknown_VTable
=
358 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
359 DataCache_NDIUnknown_QueryInterface
,
360 DataCache_NDIUnknown_AddRef
,
361 DataCache_NDIUnknown_Release
364 static ICOM_VTABLE(IDataObject
) DataCache_IDataObject_VTable
=
366 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
367 DataCache_IDataObject_QueryInterface
,
368 DataCache_IDataObject_AddRef
,
369 DataCache_IDataObject_Release
,
371 DataCache_GetDataHere
,
372 DataCache_QueryGetData
,
373 DataCache_GetCanonicalFormatEtc
,
374 DataCache_IDataObject_SetData
,
375 DataCache_EnumFormatEtc
,
378 DataCache_EnumDAdvise
381 static ICOM_VTABLE(IPersistStorage
) DataCache_IPersistStorage_VTable
=
383 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
384 DataCache_IPersistStorage_QueryInterface
,
385 DataCache_IPersistStorage_AddRef
,
386 DataCache_IPersistStorage_Release
,
387 DataCache_GetClassID
,
392 DataCache_SaveCompleted
,
393 DataCache_HandsOffStorage
396 static ICOM_VTABLE(IViewObject2
) DataCache_IViewObject2_VTable
=
398 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
399 DataCache_IViewObject2_QueryInterface
,
400 DataCache_IViewObject2_AddRef
,
401 DataCache_IViewObject2_Release
,
403 DataCache_GetColorSet
,
411 static ICOM_VTABLE(IOleCache2
) DataCache_IOleCache2_VTable
=
413 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
414 DataCache_IOleCache2_QueryInterface
,
415 DataCache_IOleCache2_AddRef
,
416 DataCache_IOleCache2_Release
,
421 DataCache_IOleCache2_SetData
,
422 DataCache_UpdateCache
,
423 DataCache_DiscardCache
426 static ICOM_VTABLE(IOleCacheControl
) DataCache_IOleCacheControl_VTable
=
428 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
429 DataCache_IOleCacheControl_QueryInterface
,
430 DataCache_IOleCacheControl_AddRef
,
431 DataCache_IOleCacheControl_Release
,
436 /******************************************************************************
437 * CreateDataCache [OLE32.54]
439 HRESULT WINAPI
CreateDataCache(
445 DataCache
* newCache
= NULL
;
448 TRACE("(%s, %p, %s, %p)\n", debugstr_guid(rclsid
), pUnkOuter
, debugstr_guid(riid
), ppvObj
);
459 * If this cache is constructed for aggregation, make sure
460 * the caller is requesting the IUnknown interface.
461 * This is necessary because it's the only time the non-delegating
462 * IUnknown pointer can be returned to the outside.
464 if ( (pUnkOuter
!=NULL
) &&
465 (memcmp(&IID_IUnknown
, riid
, sizeof(IID_IUnknown
)) != 0) )
466 return CLASS_E_NOAGGREGATION
;
469 * Try to construct a new instance of the class.
471 newCache
= DataCache_Construct(rclsid
,
475 return E_OUTOFMEMORY
;
478 * Make sure it supports the interface required by the caller.
480 hr
= IUnknown_QueryInterface((IUnknown
*)&(newCache
->lpvtbl2
), riid
, ppvObj
);
483 * Release the reference obtained in the constructor. If
484 * the QueryInterface was unsuccessful, it will free the class.
486 IUnknown_Release((IUnknown
*)&(newCache
->lpvtbl2
));
491 /*********************************************************
492 * Method implementation for DataCache class.
494 static DataCache
* DataCache_Construct(
498 DataCache
* newObject
= 0;
501 * Allocate space for the object.
503 newObject
= HeapAlloc(GetProcessHeap(), 0, sizeof(DataCache
));
509 * Initialize the virtual function table.
511 newObject
->lpvtbl1
= &DataCache_IDataObject_VTable
;
512 newObject
->lpvtbl2
= &DataCache_NDIUnknown_VTable
;
513 newObject
->lpvtbl3
= &DataCache_IPersistStorage_VTable
;
514 newObject
->lpvtbl4
= &DataCache_IViewObject2_VTable
;
515 newObject
->lpvtbl5
= &DataCache_IOleCache2_VTable
;
516 newObject
->lpvtbl6
= &DataCache_IOleCacheControl_VTable
;
519 * Start with one reference count. The caller of this function
520 * must release the interface pointer when it is done.
525 * Initialize the outer unknown
526 * We don't keep a reference on the outer unknown since, the way
527 * aggregation works, our lifetime is at least as large as it's
531 pUnkOuter
= (IUnknown
*)&(newObject
->lpvtbl2
);
533 newObject
->outerUnknown
= pUnkOuter
;
536 * Initialize the other members of the structure.
538 newObject
->presentationStorage
= NULL
;
539 newObject
->sinkAspects
= 0;
540 newObject
->sinkAdviseFlag
= 0;
541 newObject
->sinkInterface
= 0;
546 static void DataCache_Destroy(
547 DataCache
* ptrToDestroy
)
551 if (ptrToDestroy
->sinkInterface
!= NULL
)
553 IAdviseSink_Release(ptrToDestroy
->sinkInterface
);
554 ptrToDestroy
->sinkInterface
= NULL
;
557 if (ptrToDestroy
->presentationStorage
!= NULL
)
559 IStorage_Release(ptrToDestroy
->presentationStorage
);
560 ptrToDestroy
->presentationStorage
= NULL
;
564 * Free the datacache pointer.
566 HeapFree(GetProcessHeap(), 0, ptrToDestroy
);
569 /************************************************************************
570 * DataCache_ReadPresentationData
572 * This method will read information for the requested presentation
573 * into the given structure.
576 * this - Pointer to the DataCache object
577 * drawAspect - The aspect of the object that we wish to draw.
578 * header - The structure containing information about this
579 * aspect of the object.
581 static HRESULT
DataCache_ReadPresentationData(
584 PresentationDataHeader
* header
)
586 IStream
* presStream
= NULL
;
590 * Open the presentation stream.
592 hres
= DataCache_OpenPresStream(
607 sizeof(PresentationDataHeader
),
613 IStream_Release(presStream
);
616 * We don't want to propagate any other error
617 * code than a failure.
625 /************************************************************************
626 * DataCache_FireOnViewChange
628 * This method will fire an OnViewChange notification to the advise
629 * sink registered with the datacache.
631 * See IAdviseSink::OnViewChange for more details.
633 static void DataCache_FireOnViewChange(
638 TRACE("(%p, %lx, %ld)\n", this, aspect
, lindex
);
641 * The sink supplies a filter when it registers
642 * we make sure we only send the notifications when that
645 if ((this->sinkAspects
& aspect
) != 0)
647 if (this->sinkInterface
!= NULL
)
649 IAdviseSink_OnViewChange(this->sinkInterface
,
654 * Some sinks want to be unregistered automatically when
655 * the first notification goes out.
657 if ( (this->sinkAdviseFlag
& ADVF_ONLYONCE
) != 0)
659 IAdviseSink_Release(this->sinkInterface
);
661 this->sinkInterface
= NULL
;
662 this->sinkAspects
= 0;
663 this->sinkAdviseFlag
= 0;
669 /* Helper for DataCache_OpenPresStream */
670 static BOOL
DataCache_IsPresentationStream(const STATSTG
*elem
)
672 /* The presentation streams have names of the form "\002OlePresXXX",
673 * where XXX goes from 000 to 999. */
674 static const WCHAR OlePres
[] = { 2,'O','l','e','P','r','e','s' };
676 LPCWSTR name
= elem
->pwcsName
;
678 return (elem
->type
== STGTY_STREAM
)
679 && (elem
->cbSize
.s
.LowPart
>= sizeof(PresentationDataHeader
))
680 && (CRTDLL_wcslen(name
) == 11)
681 && (CRTDLL_wcsncmp(name
, OlePres
, 8) == 0)
682 && CRTDLL_iswdigit(name
[8])
683 && CRTDLL_iswdigit(name
[9])
684 && CRTDLL_iswdigit(name
[10]);
687 /************************************************************************
688 * DataCache_OpenPresStream
690 * This method will find the stream for the given presentation. It makes
691 * no attempt at fallback.
694 * this - Pointer to the DataCache object
695 * drawAspect - The aspect of the object that we wish to draw.
696 * pStm - A returned stream. It points to the beginning of the
697 * - presentation data, including the header.
700 * S_OK The requested stream has been opened.
701 * OLE_E_BLANK The requested stream could not be found.
702 * Quite a few others I'm too lazy to map correctly.
705 * Algorithm: Scan the elements of the presentation storage, looking
706 * for presentation streams. For each presentation stream,
707 * load the header and check to see if the aspect maches.
709 * If a fallback is desired, just opening the first presentation stream
712 static HRESULT
DataCache_OpenPresStream(
721 if (!ppStm
) return E_POINTER
;
723 hr
= IStorage_EnumElements(this->presentationStorage
, 0, NULL
, 0, &pEnum
);
724 if (FAILED(hr
)) return hr
;
726 while ((hr
= IEnumSTATSTG_Next(pEnum
, 1, &elem
, NULL
)) == S_OK
)
728 if (DataCache_IsPresentationStream(&elem
))
732 hr
= IStorage_OpenStream(this->presentationStorage
, elem
.pwcsName
,
733 NULL
, STGM_READ
| STGM_SHARE_EXCLUSIVE
, 0,
737 PresentationDataHeader header
;
740 hr
= IStream_Read(pStm
, &header
, sizeof(header
), &actual_read
);
742 /* can't use SUCCEEDED(hr): S_FALSE counts as an error */
743 if (hr
== S_OK
&& actual_read
== sizeof(header
)
744 && header
.dvAspect
== drawAspect
)
746 /* Rewind the stream before returning it. */
747 LARGE_INTEGER offset
;
748 offset
.s
.LowPart
= 0;
749 offset
.s
.HighPart
= 0;
750 IStream_Seek(pStm
, offset
, STREAM_SEEK_SET
, NULL
);
754 CoTaskMemFree(elem
.pwcsName
);
755 IEnumSTATSTG_Release(pEnum
);
760 IStream_Release(pStm
);
764 CoTaskMemFree(elem
.pwcsName
);
767 IEnumSTATSTG_Release(pEnum
);
769 return (hr
== S_FALSE
? OLE_E_BLANK
: hr
);
772 /************************************************************************
773 * DataCache_ReadPresentationData
775 * This method will read information for the requested presentation
776 * into the given structure.
779 * this - Pointer to the DataCache object
780 * drawAspect - The aspect of the object that we wish to draw.
783 * This method returns a metafile handle if it is successful.
784 * it will return 0 if not.
786 static HMETAFILE
DataCache_ReadPresMetafile(
790 LARGE_INTEGER offset
;
791 IStream
* presStream
= NULL
;
795 HMETAFILE newMetafile
= 0;
798 * Open the presentation stream.
800 hres
= DataCache_OpenPresStream(
809 * Get the size of the stream.
811 hres
= IStream_Stat(presStream
,
818 offset
.s
.HighPart
= 0;
819 offset
.s
.LowPart
= sizeof(PresentationDataHeader
);
827 streamInfo
.cbSize
.s
.LowPart
-= offset
.s
.LowPart
;
830 * Allocate a buffer for the metafile bits.
832 metafileBits
= HeapAlloc(GetProcessHeap(),
834 streamInfo
.cbSize
.s
.LowPart
);
837 * Read the metafile bits.
842 streamInfo
.cbSize
.s
.LowPart
,
846 * Create a metafile with those bits.
850 newMetafile
= SetMetaFileBitsEx(streamInfo
.cbSize
.s
.LowPart
, metafileBits
);
856 HeapFree(GetProcessHeap(), 0, metafileBits
);
857 IStream_Release(presStream
);
865 /*********************************************************
866 * Method implementation for the non delegating IUnknown
867 * part of the DataCache class.
870 /************************************************************************
871 * DataCache_NDIUnknown_QueryInterface (IUnknown)
873 * See Windows documentation for more details on IUnknown methods.
875 * This version of QueryInterface will not delegate it's implementation
876 * to the outer unknown.
878 static HRESULT WINAPI
DataCache_NDIUnknown_QueryInterface(
883 _ICOM_THIS_From_NDIUnknown(DataCache
, iface
);
886 * Perform a sanity check on the parameters.
888 if ( (this==0) || (ppvObject
==0) )
892 * Initialize the return parameter.
897 * Compare the riid with the interface IDs implemented by this object.
899 if (memcmp(&IID_IUnknown
, riid
, sizeof(IID_IUnknown
)) == 0)
903 else if (memcmp(&IID_IDataObject
, riid
, sizeof(IID_IDataObject
)) == 0)
905 *ppvObject
= (IDataObject
*)&(this->lpvtbl1
);
907 else if ( (memcmp(&IID_IPersistStorage
, riid
, sizeof(IID_IPersistStorage
)) == 0) ||
908 (memcmp(&IID_IPersist
, riid
, sizeof(IID_IPersist
)) == 0) )
910 *ppvObject
= (IPersistStorage
*)&(this->lpvtbl3
);
912 else if ( (memcmp(&IID_IViewObject
, riid
, sizeof(IID_IViewObject
)) == 0) ||
913 (memcmp(&IID_IViewObject2
, riid
, sizeof(IID_IViewObject2
)) == 0) )
915 *ppvObject
= (IViewObject2
*)&(this->lpvtbl4
);
917 else if ( (memcmp(&IID_IOleCache
, riid
, sizeof(IID_IOleCache
)) == 0) ||
918 (memcmp(&IID_IOleCache2
, riid
, sizeof(IID_IOleCache2
)) == 0) )
920 *ppvObject
= (IOleCache2
*)&(this->lpvtbl5
);
922 else if (memcmp(&IID_IOleCacheControl
, riid
, sizeof(IID_IOleCacheControl
)) == 0)
924 *ppvObject
= (IOleCacheControl
*)&(this->lpvtbl6
);
928 * Check that we obtained an interface.
932 WARN( "() : asking for un supported interface %s\n", debugstr_guid(riid
));
933 return E_NOINTERFACE
;
937 * Query Interface always increases the reference count by one when it is
940 IUnknown_AddRef((IUnknown
*)*ppvObject
);
945 /************************************************************************
946 * DataCache_NDIUnknown_AddRef (IUnknown)
948 * See Windows documentation for more details on IUnknown methods.
950 * This version of QueryInterface will not delegate it's implementation
951 * to the outer unknown.
953 static ULONG WINAPI
DataCache_NDIUnknown_AddRef(
956 _ICOM_THIS_From_NDIUnknown(DataCache
, iface
);
963 /************************************************************************
964 * DataCache_NDIUnknown_Release (IUnknown)
966 * See Windows documentation for more details on IUnknown methods.
968 * This version of QueryInterface will not delegate it's implementation
969 * to the outer unknown.
971 static ULONG WINAPI
DataCache_NDIUnknown_Release(
974 _ICOM_THIS_From_NDIUnknown(DataCache
, iface
);
977 * Decrease the reference count on this object.
982 * If the reference count goes down to 0, perform suicide.
986 DataCache_Destroy(this);
994 /*********************************************************
995 * Method implementation for the IDataObject
996 * part of the DataCache class.
999 /************************************************************************
1000 * DataCache_IDataObject_QueryInterface (IUnknown)
1002 * See Windows documentation for more details on IUnknown methods.
1004 static HRESULT WINAPI
DataCache_IDataObject_QueryInterface(
1009 _ICOM_THIS_From_IDataObject(DataCache
, iface
);
1011 return IUnknown_QueryInterface(this->outerUnknown
, riid
, ppvObject
);
1014 /************************************************************************
1015 * DataCache_IDataObject_AddRef (IUnknown)
1017 * See Windows documentation for more details on IUnknown methods.
1019 static ULONG WINAPI
DataCache_IDataObject_AddRef(
1022 _ICOM_THIS_From_IDataObject(DataCache
, iface
);
1024 return IUnknown_AddRef(this->outerUnknown
);
1027 /************************************************************************
1028 * DataCache_IDataObject_Release (IUnknown)
1030 * See Windows documentation for more details on IUnknown methods.
1032 static ULONG WINAPI
DataCache_IDataObject_Release(
1035 _ICOM_THIS_From_IDataObject(DataCache
, iface
);
1037 return IUnknown_Release(this->outerUnknown
);
1040 static HRESULT WINAPI
DataCache_GetData(
1042 LPFORMATETC pformatetcIn
,
1049 static HRESULT WINAPI
DataCache_GetDataHere(
1051 LPFORMATETC pformatetc
,
1058 static HRESULT WINAPI
DataCache_QueryGetData(
1060 LPFORMATETC pformatetc
)
1066 /************************************************************************
1067 * DataCache_EnumFormatEtc (IDataObject)
1069 * The data cache doesn't implement this method.
1071 * See Windows documentation for more details on IDataObject methods.
1073 static HRESULT WINAPI
DataCache_GetCanonicalFormatEtc(
1075 LPFORMATETC pformatectIn
,
1076 LPFORMATETC pformatetcOut
)
1082 /************************************************************************
1083 * DataCache_IDataObject_SetData (IDataObject)
1085 * This method is delegated to the IOleCache2 implementation.
1087 * See Windows documentation for more details on IDataObject methods.
1089 static HRESULT WINAPI
DataCache_IDataObject_SetData(
1091 LPFORMATETC pformatetc
,
1095 IOleCache2
* oleCache
= NULL
;
1098 TRACE("(%p, %p, %p, %d)\n", iface
, pformatetc
, pmedium
, fRelease
);
1100 hres
= IDataObject_QueryInterface(iface
, &IID_IOleCache2
, (void**)&oleCache
);
1103 return E_UNEXPECTED
;
1105 hres
= IOleCache2_SetData(oleCache
, pformatetc
, pmedium
, fRelease
);
1107 IOleCache2_Release(oleCache
);
1112 /************************************************************************
1113 * DataCache_EnumFormatEtc (IDataObject)
1115 * The data cache doesn't implement this method.
1117 * See Windows documentation for more details on IDataObject methods.
1119 static HRESULT WINAPI
DataCache_EnumFormatEtc(
1122 IEnumFORMATETC
** ppenumFormatEtc
)
1128 /************************************************************************
1129 * DataCache_DAdvise (IDataObject)
1131 * The data cache doesn't support connections.
1133 * See Windows documentation for more details on IDataObject methods.
1135 static HRESULT WINAPI
DataCache_DAdvise(
1137 FORMATETC
* pformatetc
,
1139 IAdviseSink
* pAdvSink
,
1140 DWORD
* pdwConnection
)
1143 return OLE_E_ADVISENOTSUPPORTED
;
1146 /************************************************************************
1147 * DataCache_DUnadvise (IDataObject)
1149 * The data cache doesn't support connections.
1151 * See Windows documentation for more details on IDataObject methods.
1153 static HRESULT WINAPI
DataCache_DUnadvise(
1158 return OLE_E_NOCONNECTION
;
1161 /************************************************************************
1162 * DataCache_EnumDAdvise (IDataObject)
1164 * The data cache doesn't support connections.
1166 * See Windows documentation for more details on IDataObject methods.
1168 static HRESULT WINAPI
DataCache_EnumDAdvise(
1170 IEnumSTATDATA
** ppenumAdvise
)
1173 return OLE_E_ADVISENOTSUPPORTED
;
1176 /*********************************************************
1177 * Method implementation for the IDataObject
1178 * part of the DataCache class.
1181 /************************************************************************
1182 * DataCache_IPersistStorage_QueryInterface (IUnknown)
1184 * See Windows documentation for more details on IUnknown methods.
1186 static HRESULT WINAPI
DataCache_IPersistStorage_QueryInterface(
1187 IPersistStorage
* iface
,
1191 _ICOM_THIS_From_IPersistStorage(DataCache
, iface
);
1193 return IUnknown_QueryInterface(this->outerUnknown
, riid
, ppvObject
);
1196 /************************************************************************
1197 * DataCache_IPersistStorage_AddRef (IUnknown)
1199 * See Windows documentation for more details on IUnknown methods.
1201 static ULONG WINAPI
DataCache_IPersistStorage_AddRef(
1202 IPersistStorage
* iface
)
1204 _ICOM_THIS_From_IPersistStorage(DataCache
, iface
);
1206 return IUnknown_AddRef(this->outerUnknown
);
1209 /************************************************************************
1210 * DataCache_IPersistStorage_Release (IUnknown)
1212 * See Windows documentation for more details on IUnknown methods.
1214 static ULONG WINAPI
DataCache_IPersistStorage_Release(
1215 IPersistStorage
* iface
)
1217 _ICOM_THIS_From_IPersistStorage(DataCache
, iface
);
1219 return IUnknown_Release(this->outerUnknown
);
1222 /************************************************************************
1223 * DataCache_GetClassID (IPersistStorage)
1225 * The data cache doesn't implement this method.
1227 * See Windows documentation for more details on IPersistStorage methods.
1229 static HRESULT WINAPI
DataCache_GetClassID(
1230 IPersistStorage
* iface
,
1233 TRACE("(%p, %p)\n", iface
, pClassID
);
1237 /************************************************************************
1238 * DataCache_IsDirty (IPersistStorage)
1240 * Until we actully connect to a running object and retrieve new
1241 * information to it, we never get dirty.
1243 * See Windows documentation for more details on IPersistStorage methods.
1245 static HRESULT WINAPI
DataCache_IsDirty(
1246 IPersistStorage
* iface
)
1248 TRACE("(%p)\n", iface
);
1253 /************************************************************************
1254 * DataCache_InitNew (IPersistStorage)
1256 * The data cache implementation of IPersistStorage_InitNew simply stores
1257 * the storage pointer.
1259 * See Windows documentation for more details on IPersistStorage methods.
1261 static HRESULT WINAPI
DataCache_InitNew(
1262 IPersistStorage
* iface
,
1265 TRACE("(%p, %p)\n", iface
, pStg
);
1267 return DataCache_Load(iface
, pStg
);
1270 /************************************************************************
1271 * DataCache_Load (IPersistStorage)
1273 * The data cache implementation of IPersistStorage_Load doesn't
1274 * actually load anything. Instead, it holds on to the storage pointer
1275 * and it will load the presentation information when the
1276 * IDataObject_GetData or IViewObject2_Draw methods are called.
1278 * See Windows documentation for more details on IPersistStorage methods.
1280 static HRESULT WINAPI
DataCache_Load(
1281 IPersistStorage
* iface
,
1284 _ICOM_THIS_From_IPersistStorage(DataCache
, iface
);
1286 TRACE("(%p, %p)\n", iface
, pStg
);
1288 if (this->presentationStorage
!= NULL
)
1290 IStorage_Release(this->presentationStorage
);
1293 this->presentationStorage
= pStg
;
1295 if (this->presentationStorage
!= NULL
)
1297 IStorage_AddRef(this->presentationStorage
);
1302 /************************************************************************
1303 * DataCache_Save (IPersistStorage)
1305 * Until we actully connect to a running object and retrieve new
1306 * information to it, we never have to save anything. However, it is
1307 * our responsability to copy the information when saving to a new
1310 * See Windows documentation for more details on IPersistStorage methods.
1312 static HRESULT WINAPI
DataCache_Save(
1313 IPersistStorage
* iface
,
1317 _ICOM_THIS_From_IPersistStorage(DataCache
, iface
);
1319 TRACE("(%p, %p, %d)\n", iface
, pStg
, fSameAsLoad
);
1321 if ( (!fSameAsLoad
) &&
1322 (this->presentationStorage
!=NULL
) )
1324 return IStorage_CopyTo(this->presentationStorage
,
1334 /************************************************************************
1335 * DataCache_SaveCompleted (IPersistStorage)
1337 * This method is called to tell the cache to release the storage
1338 * pointer it's currentlu holding.
1340 * See Windows documentation for more details on IPersistStorage methods.
1342 static HRESULT WINAPI
DataCache_SaveCompleted(
1343 IPersistStorage
* iface
,
1346 TRACE("(%p, %p)\n", iface
, pStgNew
);
1351 * First, make sure we get our hands off any storage we have.
1354 DataCache_HandsOffStorage(iface
);
1357 * Then, attach to the new storage.
1360 DataCache_Load(iface
, pStgNew
);
1366 /************************************************************************
1367 * DataCache_HandsOffStorage (IPersistStorage)
1369 * This method is called to tell the cache to release the storage
1370 * pointer it's currentlu holding.
1372 * See Windows documentation for more details on IPersistStorage methods.
1374 static HRESULT WINAPI
DataCache_HandsOffStorage(
1375 IPersistStorage
* iface
)
1377 _ICOM_THIS_From_IPersistStorage(DataCache
, iface
);
1379 TRACE("(%p)\n", iface
);
1381 if (this->presentationStorage
!= NULL
)
1383 IStorage_Release(this->presentationStorage
);
1384 this->presentationStorage
= NULL
;
1390 /*********************************************************
1391 * Method implementation for the IViewObject2
1392 * part of the DataCache class.
1395 /************************************************************************
1396 * DataCache_IViewObject2_QueryInterface (IUnknown)
1398 * See Windows documentation for more details on IUnknown methods.
1400 static HRESULT WINAPI
DataCache_IViewObject2_QueryInterface(
1401 IViewObject2
* iface
,
1405 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1407 return IUnknown_QueryInterface(this->outerUnknown
, riid
, ppvObject
);
1410 /************************************************************************
1411 * DataCache_IViewObject2_AddRef (IUnknown)
1413 * See Windows documentation for more details on IUnknown methods.
1415 static ULONG WINAPI
DataCache_IViewObject2_AddRef(
1416 IViewObject2
* iface
)
1418 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1420 return IUnknown_AddRef(this->outerUnknown
);
1423 /************************************************************************
1424 * DataCache_IViewObject2_Release (IUnknown)
1426 * See Windows documentation for more details on IUnknown methods.
1428 static ULONG WINAPI
DataCache_IViewObject2_Release(
1429 IViewObject2
* iface
)
1431 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1433 return IUnknown_Release(this->outerUnknown
);
1436 /************************************************************************
1437 * DataCache_Draw (IViewObject2)
1439 * This method will draw the cached representation of the object
1440 * to the given device context.
1442 * See Windows documentation for more details on IViewObject2 methods.
1444 static HRESULT WINAPI
DataCache_Draw(
1445 IViewObject2
* iface
,
1449 DVTARGETDEVICE
* ptd
,
1452 LPCRECTL lprcBounds
,
1453 LPCRECTL lprcWBounds
,
1454 IVO_ContCallback pfnContinue
,
1457 PresentationDataHeader presData
;
1458 HMETAFILE presMetafile
= 0;
1461 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1463 TRACE("(%p, %lx, %ld, %p, %x, %x, %p, %p, %p, %lx)\n",
1478 if (lprcBounds
==NULL
)
1479 return E_INVALIDARG
;
1482 * First, we need to retrieve the dimensions of the
1483 * image in the metafile.
1485 hres
= DataCache_ReadPresentationData(this,
1493 * Then, we can extract the metafile itself from the cached
1496 * FIXME Unless it isn't a metafile. I think it could be any CF_XXX type,
1497 * particularly CF_DIB.
1499 presMetafile
= DataCache_ReadPresMetafile(this,
1503 * If we have a metafile, just draw baby...
1504 * We have to be careful not to modify the state of the
1507 if (presMetafile
!=0)
1509 INT prevMapMode
= SetMapMode(hdcDraw
, MM_ANISOTROPIC
);
1511 SIZE oldViewportExt
;
1512 POINT oldViewportOrg
;
1514 SetWindowExtEx(hdcDraw
,
1515 presData
.objectExtentX
,
1516 presData
.objectExtentY
,
1519 SetViewportExtEx(hdcDraw
,
1520 lprcBounds
->right
- lprcBounds
->left
,
1521 lprcBounds
->bottom
- lprcBounds
->top
,
1524 SetViewportOrgEx(hdcDraw
,
1529 PlayMetaFile(hdcDraw
, presMetafile
);
1531 SetWindowExtEx(hdcDraw
,
1536 SetViewportExtEx(hdcDraw
,
1541 SetViewportOrgEx(hdcDraw
,
1546 SetMapMode(hdcDraw
, prevMapMode
);
1548 DeleteMetaFile(presMetafile
);
1554 static HRESULT WINAPI
DataCache_GetColorSet(
1555 IViewObject2
* iface
,
1559 DVTARGETDEVICE
* ptd
,
1560 HDC hicTargetDevice
,
1561 LOGPALETTE
** ppColorSet
)
1567 static HRESULT WINAPI
DataCache_Freeze(
1568 IViewObject2
* iface
,
1578 static HRESULT WINAPI
DataCache_Unfreeze(
1579 IViewObject2
* iface
,
1586 /************************************************************************
1587 * DataCache_SetAdvise (IViewObject2)
1589 * This sets-up an advisory sink with the data cache. When the object's
1590 * view changes, this sink is called.
1592 * See Windows documentation for more details on IViewObject2 methods.
1594 static HRESULT WINAPI
DataCache_SetAdvise(
1595 IViewObject2
* iface
,
1598 IAdviseSink
* pAdvSink
)
1600 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1602 TRACE("(%p, %lx, %lx, %p)\n", iface
, aspects
, advf
, pAdvSink
);
1605 * A call to this function removes the previous sink
1607 if (this->sinkInterface
!= NULL
)
1609 IAdviseSink_Release(this->sinkInterface
);
1610 this->sinkInterface
= NULL
;
1611 this->sinkAspects
= 0;
1612 this->sinkAdviseFlag
= 0;
1616 * Now, setup the new one.
1620 this->sinkInterface
= pAdvSink
;
1621 this->sinkAspects
= aspects
;
1622 this->sinkAdviseFlag
= advf
;
1624 IAdviseSink_AddRef(this->sinkInterface
);
1628 * When the ADVF_PRIMEFIRST flag is set, we have to advise the
1631 if (advf
& ADVF_PRIMEFIRST
)
1633 DataCache_FireOnViewChange(this,
1641 /************************************************************************
1642 * DataCache_GetAdvise (IViewObject2)
1644 * This method queries the current state of the advise sink
1645 * installed on the data cache.
1647 * See Windows documentation for more details on IViewObject2 methods.
1649 static HRESULT WINAPI
DataCache_GetAdvise(
1650 IViewObject2
* iface
,
1653 IAdviseSink
** ppAdvSink
)
1655 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1657 TRACE("(%p, %p, %p, %p)\n", iface
, pAspects
, pAdvf
, ppAdvSink
);
1660 * Just copy all the requested values.
1663 *pAspects
= this->sinkAspects
;
1666 *pAdvf
= this->sinkAdviseFlag
;
1668 if (ppAdvSink
!=NULL
)
1670 IAdviseSink_QueryInterface(this->sinkInterface
,
1678 /************************************************************************
1679 * DataCache_GetExtent (IViewObject2)
1681 * This method retrieves the "natural" size of this cached object.
1683 * See Windows documentation for more details on IViewObject2 methods.
1685 static HRESULT WINAPI
DataCache_GetExtent(
1686 IViewObject2
* iface
,
1689 DVTARGETDEVICE
* ptd
,
1692 PresentationDataHeader presData
;
1693 HRESULT hres
= E_FAIL
;
1695 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1697 TRACE("(%p, %lx, %ld, %p, %p)\n",
1698 iface
, dwDrawAspect
, lindex
, ptd
, lpsizel
);
1707 * Initialize the out parameter.
1713 * This flag should be set to -1.
1716 FIXME("Unimplemented flag lindex = %ld\n", lindex
);
1719 * Right now, we suport only the callback from
1720 * the default handler.
1723 FIXME("Unimplemented ptd = %p\n", ptd
);
1726 * Get the presentation information from the
1729 hres
= DataCache_ReadPresentationData(this,
1733 if (SUCCEEDED(hres
))
1735 lpsizel
->cx
= presData
.objectExtentX
;
1736 lpsizel
->cy
= presData
.objectExtentY
;
1740 * This method returns OLE_E_BLANK when it fails.
1749 /*********************************************************
1750 * Method implementation for the IOleCache2
1751 * part of the DataCache class.
1754 /************************************************************************
1755 * DataCache_IOleCache2_QueryInterface (IUnknown)
1757 * See Windows documentation for more details on IUnknown methods.
1759 static HRESULT WINAPI
DataCache_IOleCache2_QueryInterface(
1764 _ICOM_THIS_From_IOleCache2(DataCache
, iface
);
1766 return IUnknown_QueryInterface(this->outerUnknown
, riid
, ppvObject
);
1769 /************************************************************************
1770 * DataCache_IOleCache2_AddRef (IUnknown)
1772 * See Windows documentation for more details on IUnknown methods.
1774 static ULONG WINAPI
DataCache_IOleCache2_AddRef(
1777 _ICOM_THIS_From_IOleCache2(DataCache
, iface
);
1779 return IUnknown_AddRef(this->outerUnknown
);
1782 /************************************************************************
1783 * DataCache_IOleCache2_Release (IUnknown)
1785 * See Windows documentation for more details on IUnknown methods.
1787 static ULONG WINAPI
DataCache_IOleCache2_Release(
1790 _ICOM_THIS_From_IOleCache2(DataCache
, iface
);
1792 return IUnknown_Release(this->outerUnknown
);
1795 static HRESULT WINAPI
DataCache_Cache(
1797 FORMATETC
* pformatetc
,
1799 DWORD
* pdwConnection
)
1805 static HRESULT WINAPI
DataCache_Uncache(
1813 static HRESULT WINAPI
DataCache_EnumCache(
1815 IEnumSTATDATA
** ppenumSTATDATA
)
1821 static HRESULT WINAPI
DataCache_InitCache(
1823 IDataObject
* pDataObject
)
1829 static HRESULT WINAPI
DataCache_IOleCache2_SetData(
1831 FORMATETC
* pformatetc
,
1839 static HRESULT WINAPI
DataCache_UpdateCache(
1841 LPDATAOBJECT pDataObject
,
1849 static HRESULT WINAPI
DataCache_DiscardCache(
1851 DWORD dwDiscardOptions
)
1858 /*********************************************************
1859 * Method implementation for the IOleCacheControl
1860 * part of the DataCache class.
1863 /************************************************************************
1864 * DataCache_IOleCacheControl_QueryInterface (IUnknown)
1866 * See Windows documentation for more details on IUnknown methods.
1868 static HRESULT WINAPI
DataCache_IOleCacheControl_QueryInterface(
1869 IOleCacheControl
* iface
,
1873 _ICOM_THIS_From_IOleCacheControl(DataCache
, iface
);
1875 return IUnknown_QueryInterface(this->outerUnknown
, riid
, ppvObject
);
1878 /************************************************************************
1879 * DataCache_IOleCacheControl_AddRef (IUnknown)
1881 * See Windows documentation for more details on IUnknown methods.
1883 static ULONG WINAPI
DataCache_IOleCacheControl_AddRef(
1884 IOleCacheControl
* iface
)
1886 _ICOM_THIS_From_IOleCacheControl(DataCache
, iface
);
1888 return IUnknown_AddRef(this->outerUnknown
);
1891 /************************************************************************
1892 * DataCache_IOleCacheControl_Release (IUnknown)
1894 * See Windows documentation for more details on IUnknown methods.
1896 static ULONG WINAPI
DataCache_IOleCacheControl_Release(
1897 IOleCacheControl
* iface
)
1899 _ICOM_THIS_From_IOleCacheControl(DataCache
, iface
);
1901 return IUnknown_Release(this->outerUnknown
);
1904 static HRESULT WINAPI
DataCache_OnRun(
1905 IOleCacheControl
* iface
,
1906 LPDATAOBJECT pDataObject
)
1912 static HRESULT WINAPI
DataCache_OnStop(
1913 IOleCacheControl
* iface
)