4 * Copyright 1999 Francis Beaudet
5 * Copyright 2000 Abey George
8 * The OLE2 data cache supports a whole whack of
9 * interfaces including:
10 * IDataObject, IPersistStorage, IViewObject2,
11 * IOleCache2 and IOleCacheControl.
13 * Most of the implementation details are taken from: Inside OLE
14 * second edition by Kraig Brockschmidt,
17 * - This implementation of the datacache will let your application
18 * load documents that have embedded OLE objects in them and it will
19 * also retrieve the metafile representation of those objects.
20 * - This implementation of the datacache will also allow your
21 * application to save new documents with OLE objects in them.
22 * - The main thing that it doesn't do is allow you to activate
23 * or modify the OLE objects in any way.
24 * - I haven't found any good documentation on the real usage of
25 * the streams created by the data cache. In particular, How to
26 * determine what the XXX stands for in the stream name
27 * "\002OlePresXXX". It appears to just be a counter.
28 * - Also, I don't know the real content of the presentation stream
29 * header. I was able to figure-out where the extent of the object
30 * was stored and the aspect, but that's about it.
39 #include "wine/obj_oleview.h"
40 #include "wine/obj_cache.h"
41 #include "wine/unicode.h"
43 #include "debugtools.h"
45 DEFAULT_DEBUG_CHANNEL(ole
);
47 /****************************************************************************
48 * PresentationDataHeader
50 * This structure represents the header of the \002OlePresXXX stream in
51 * the OLE object strorage.
53 * Most fields are still unknown.
55 typedef struct PresentationDataHeader
57 DWORD unknown1
; /* -1 */
58 DWORD unknown2
; /* 3, possibly CF_METAFILEPICT */
59 DWORD unknown3
; /* 4, possibly TYMED_ISTREAM */
61 DWORD unknown5
; /* -1 */
64 DWORD unknown7
; /* 0 */
65 DWORD dwObjectExtentX
;
66 DWORD dwObjectExtentY
;
68 } PresentationDataHeader
;
70 /****************************************************************************
76 * List all interface VTables here
78 ICOM_VTABLE(IDataObject
)* lpvtbl1
;
79 ICOM_VTABLE(IUnknown
)* lpvtbl2
;
80 ICOM_VTABLE(IPersistStorage
)* lpvtbl3
;
81 ICOM_VTABLE(IViewObject2
)* lpvtbl4
;
82 ICOM_VTABLE(IOleCache2
)* lpvtbl5
;
83 ICOM_VTABLE(IOleCacheControl
)* lpvtbl6
;
86 * Reference count of this object
91 * IUnknown implementation of the outer object.
93 IUnknown
* outerUnknown
;
96 * This storage pointer is set through a call to
97 * IPersistStorage_Load. This is where the visual
98 * representation of the object is stored.
100 IStorage
* presentationStorage
;
103 * The user of this object can setup ONE advise sink
104 * connection with the object. These parameters describe
108 DWORD sinkAdviseFlag
;
109 IAdviseSink
* sinkInterface
;
113 typedef struct DataCache DataCache
;
116 * Here, I define utility macros to help with the casting of the
118 * There is a version to accomodate all of the VTables implemented
121 #define _ICOM_THIS_From_IDataObject(class,name) class* this = (class*)name;
122 #define _ICOM_THIS_From_NDIUnknown(class, name) class* this = (class*)(((char*)name)-sizeof(void*));
123 #define _ICOM_THIS_From_IPersistStorage(class, name) class* this = (class*)(((char*)name)-2*sizeof(void*));
124 #define _ICOM_THIS_From_IViewObject2(class, name) class* this = (class*)(((char*)name)-3*sizeof(void*));
125 #define _ICOM_THIS_From_IOleCache2(class, name) class* this = (class*)(((char*)name)-4*sizeof(void*));
126 #define _ICOM_THIS_From_IOleCacheControl(class, name) class* this = (class*)(((char*)name)-5*sizeof(void*));
129 * Prototypes for the methods of the DataCache class.
131 static DataCache
* DataCache_Construct(REFCLSID clsid
,
132 LPUNKNOWN pUnkOuter
);
133 static void DataCache_Destroy(DataCache
* ptrToDestroy
);
134 static HRESULT
DataCache_ReadPresentationData(DataCache
* this,
136 PresentationDataHeader
* header
);
137 static HRESULT
DataCache_OpenPresStream(DataCache
*this,
140 static HMETAFILE
DataCache_ReadPresMetafile(DataCache
* this,
142 static void DataCache_FireOnViewChange(DataCache
* this,
147 * Prototypes for the methods of the DataCache class
148 * that implement non delegating IUnknown methods.
150 static HRESULT WINAPI
DataCache_NDIUnknown_QueryInterface(
154 static ULONG WINAPI
DataCache_NDIUnknown_AddRef(
156 static ULONG WINAPI
DataCache_NDIUnknown_Release(
160 * Prototypes for the methods of the DataCache class
161 * that implement IDataObject methods.
163 static HRESULT WINAPI
DataCache_IDataObject_QueryInterface(
167 static ULONG WINAPI
DataCache_IDataObject_AddRef(
169 static ULONG WINAPI
DataCache_IDataObject_Release(
171 static HRESULT WINAPI
DataCache_GetData(
173 LPFORMATETC pformatetcIn
,
175 static HRESULT WINAPI
DataCache_GetDataHere(
177 LPFORMATETC pformatetc
,
179 static HRESULT WINAPI
DataCache_QueryGetData(
181 LPFORMATETC pformatetc
);
182 static HRESULT WINAPI
DataCache_GetCanonicalFormatEtc(
184 LPFORMATETC pformatectIn
,
185 LPFORMATETC pformatetcOut
);
186 static HRESULT WINAPI
DataCache_IDataObject_SetData(
188 LPFORMATETC pformatetc
,
191 static HRESULT WINAPI
DataCache_EnumFormatEtc(
194 IEnumFORMATETC
** ppenumFormatEtc
);
195 static HRESULT WINAPI
DataCache_DAdvise(
197 FORMATETC
* pformatetc
,
199 IAdviseSink
* pAdvSink
,
200 DWORD
* pdwConnection
);
201 static HRESULT WINAPI
DataCache_DUnadvise(
204 static HRESULT WINAPI
DataCache_EnumDAdvise(
206 IEnumSTATDATA
** ppenumAdvise
);
209 * Prototypes for the methods of the DataCache class
210 * that implement IPersistStorage methods.
212 static HRESULT WINAPI
DataCache_IPersistStorage_QueryInterface(
213 IPersistStorage
* iface
,
216 static ULONG WINAPI
DataCache_IPersistStorage_AddRef(
217 IPersistStorage
* iface
);
218 static ULONG WINAPI
DataCache_IPersistStorage_Release(
219 IPersistStorage
* iface
);
220 static HRESULT WINAPI
DataCache_GetClassID(
221 IPersistStorage
* iface
,
223 static HRESULT WINAPI
DataCache_IsDirty(
224 IPersistStorage
* iface
);
225 static HRESULT WINAPI
DataCache_InitNew(
226 IPersistStorage
* iface
,
228 static HRESULT WINAPI
DataCache_Load(
229 IPersistStorage
* iface
,
231 static HRESULT WINAPI
DataCache_Save(
232 IPersistStorage
* iface
,
235 static HRESULT WINAPI
DataCache_SaveCompleted(
236 IPersistStorage
* iface
,
238 static HRESULT WINAPI
DataCache_HandsOffStorage(
239 IPersistStorage
* iface
);
242 * Prototypes for the methods of the DataCache class
243 * that implement IViewObject2 methods.
245 static HRESULT WINAPI
DataCache_IViewObject2_QueryInterface(
249 static ULONG WINAPI
DataCache_IViewObject2_AddRef(
250 IViewObject2
* iface
);
251 static ULONG WINAPI
DataCache_IViewObject2_Release(
252 IViewObject2
* iface
);
253 static HRESULT WINAPI
DataCache_Draw(
262 LPCRECTL lprcWBounds
,
263 IVO_ContCallback pfnContinue
,
265 static HRESULT WINAPI
DataCache_GetColorSet(
272 LOGPALETTE
** ppColorSet
);
273 static HRESULT WINAPI
DataCache_Freeze(
279 static HRESULT WINAPI
DataCache_Unfreeze(
282 static HRESULT WINAPI
DataCache_SetAdvise(
286 IAdviseSink
* pAdvSink
);
287 static HRESULT WINAPI
DataCache_GetAdvise(
291 IAdviseSink
** ppAdvSink
);
292 static HRESULT WINAPI
DataCache_GetExtent(
300 * Prototypes for the methods of the DataCache class
301 * that implement IOleCache2 methods.
303 static HRESULT WINAPI
DataCache_IOleCache2_QueryInterface(
307 static ULONG WINAPI
DataCache_IOleCache2_AddRef(
309 static ULONG WINAPI
DataCache_IOleCache2_Release(
311 static HRESULT WINAPI
DataCache_Cache(
313 FORMATETC
* pformatetc
,
315 DWORD
* pdwConnection
);
316 static HRESULT WINAPI
DataCache_Uncache(
319 static HRESULT WINAPI
DataCache_EnumCache(
321 IEnumSTATDATA
** ppenumSTATDATA
);
322 static HRESULT WINAPI
DataCache_InitCache(
324 IDataObject
* pDataObject
);
325 static HRESULT WINAPI
DataCache_IOleCache2_SetData(
327 FORMATETC
* pformatetc
,
330 static HRESULT WINAPI
DataCache_UpdateCache(
332 LPDATAOBJECT pDataObject
,
335 static HRESULT WINAPI
DataCache_DiscardCache(
337 DWORD dwDiscardOptions
);
340 * Prototypes for the methods of the DataCache class
341 * that implement IOleCacheControl methods.
343 static HRESULT WINAPI
DataCache_IOleCacheControl_QueryInterface(
344 IOleCacheControl
* iface
,
347 static ULONG WINAPI
DataCache_IOleCacheControl_AddRef(
348 IOleCacheControl
* iface
);
349 static ULONG WINAPI
DataCache_IOleCacheControl_Release(
350 IOleCacheControl
* iface
);
351 static HRESULT WINAPI
DataCache_OnRun(
352 IOleCacheControl
* iface
,
353 LPDATAOBJECT pDataObject
);
354 static HRESULT WINAPI
DataCache_OnStop(
355 IOleCacheControl
* iface
);
358 * Virtual function tables for the DataCache class.
360 static ICOM_VTABLE(IUnknown
) DataCache_NDIUnknown_VTable
=
362 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
363 DataCache_NDIUnknown_QueryInterface
,
364 DataCache_NDIUnknown_AddRef
,
365 DataCache_NDIUnknown_Release
368 static ICOM_VTABLE(IDataObject
) DataCache_IDataObject_VTable
=
370 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
371 DataCache_IDataObject_QueryInterface
,
372 DataCache_IDataObject_AddRef
,
373 DataCache_IDataObject_Release
,
375 DataCache_GetDataHere
,
376 DataCache_QueryGetData
,
377 DataCache_GetCanonicalFormatEtc
,
378 DataCache_IDataObject_SetData
,
379 DataCache_EnumFormatEtc
,
382 DataCache_EnumDAdvise
385 static ICOM_VTABLE(IPersistStorage
) DataCache_IPersistStorage_VTable
=
387 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
388 DataCache_IPersistStorage_QueryInterface
,
389 DataCache_IPersistStorage_AddRef
,
390 DataCache_IPersistStorage_Release
,
391 DataCache_GetClassID
,
396 DataCache_SaveCompleted
,
397 DataCache_HandsOffStorage
400 static ICOM_VTABLE(IViewObject2
) DataCache_IViewObject2_VTable
=
402 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
403 DataCache_IViewObject2_QueryInterface
,
404 DataCache_IViewObject2_AddRef
,
405 DataCache_IViewObject2_Release
,
407 DataCache_GetColorSet
,
415 static ICOM_VTABLE(IOleCache2
) DataCache_IOleCache2_VTable
=
417 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
418 DataCache_IOleCache2_QueryInterface
,
419 DataCache_IOleCache2_AddRef
,
420 DataCache_IOleCache2_Release
,
425 DataCache_IOleCache2_SetData
,
426 DataCache_UpdateCache
,
427 DataCache_DiscardCache
430 static ICOM_VTABLE(IOleCacheControl
) DataCache_IOleCacheControl_VTable
=
432 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
433 DataCache_IOleCacheControl_QueryInterface
,
434 DataCache_IOleCacheControl_AddRef
,
435 DataCache_IOleCacheControl_Release
,
440 /******************************************************************************
441 * CreateDataCache [OLE32.54]
443 HRESULT WINAPI
CreateDataCache(
449 DataCache
* newCache
= NULL
;
452 TRACE("(%s, %p, %s, %p)\n", debugstr_guid(rclsid
), pUnkOuter
, debugstr_guid(riid
), ppvObj
);
463 * If this cache is constructed for aggregation, make sure
464 * the caller is requesting the IUnknown interface.
465 * This is necessary because it's the only time the non-delegating
466 * IUnknown pointer can be returned to the outside.
468 if ( (pUnkOuter
!=NULL
) &&
469 (memcmp(&IID_IUnknown
, riid
, sizeof(IID_IUnknown
)) != 0) )
470 return CLASS_E_NOAGGREGATION
;
473 * Try to construct a new instance of the class.
475 newCache
= DataCache_Construct(rclsid
,
479 return E_OUTOFMEMORY
;
482 * Make sure it supports the interface required by the caller.
484 hr
= IUnknown_QueryInterface((IUnknown
*)&(newCache
->lpvtbl2
), riid
, ppvObj
);
487 * Release the reference obtained in the constructor. If
488 * the QueryInterface was unsuccessful, it will free the class.
490 IUnknown_Release((IUnknown
*)&(newCache
->lpvtbl2
));
495 /*********************************************************
496 * Method implementation for DataCache class.
498 static DataCache
* DataCache_Construct(
502 DataCache
* newObject
= 0;
505 * Allocate space for the object.
507 newObject
= HeapAlloc(GetProcessHeap(), 0, sizeof(DataCache
));
513 * Initialize the virtual function table.
515 newObject
->lpvtbl1
= &DataCache_IDataObject_VTable
;
516 newObject
->lpvtbl2
= &DataCache_NDIUnknown_VTable
;
517 newObject
->lpvtbl3
= &DataCache_IPersistStorage_VTable
;
518 newObject
->lpvtbl4
= &DataCache_IViewObject2_VTable
;
519 newObject
->lpvtbl5
= &DataCache_IOleCache2_VTable
;
520 newObject
->lpvtbl6
= &DataCache_IOleCacheControl_VTable
;
523 * Start with one reference count. The caller of this function
524 * must release the interface pointer when it is done.
529 * Initialize the outer unknown
530 * We don't keep a reference on the outer unknown since, the way
531 * aggregation works, our lifetime is at least as large as it's
535 pUnkOuter
= (IUnknown
*)&(newObject
->lpvtbl2
);
537 newObject
->outerUnknown
= pUnkOuter
;
540 * Initialize the other members of the structure.
542 newObject
->presentationStorage
= NULL
;
543 newObject
->sinkAspects
= 0;
544 newObject
->sinkAdviseFlag
= 0;
545 newObject
->sinkInterface
= 0;
550 static void DataCache_Destroy(
551 DataCache
* ptrToDestroy
)
555 if (ptrToDestroy
->sinkInterface
!= NULL
)
557 IAdviseSink_Release(ptrToDestroy
->sinkInterface
);
558 ptrToDestroy
->sinkInterface
= NULL
;
561 if (ptrToDestroy
->presentationStorage
!= NULL
)
563 IStorage_Release(ptrToDestroy
->presentationStorage
);
564 ptrToDestroy
->presentationStorage
= NULL
;
568 * Free the datacache pointer.
570 HeapFree(GetProcessHeap(), 0, ptrToDestroy
);
573 /************************************************************************
574 * DataCache_ReadPresentationData
576 * This method will read information for the requested presentation
577 * into the given structure.
580 * this - Pointer to the DataCache object
581 * drawAspect - The aspect of the object that we wish to draw.
582 * header - The structure containing information about this
583 * aspect of the object.
585 static HRESULT
DataCache_ReadPresentationData(
588 PresentationDataHeader
* header
)
590 IStream
* presStream
= NULL
;
594 * Open the presentation stream.
596 hres
= DataCache_OpenPresStream(
611 sizeof(PresentationDataHeader
),
617 IStream_Release(presStream
);
620 * We don't want to propagate any other error
621 * code than a failure.
629 /************************************************************************
630 * DataCache_FireOnViewChange
632 * This method will fire an OnViewChange notification to the advise
633 * sink registered with the datacache.
635 * See IAdviseSink::OnViewChange for more details.
637 static void DataCache_FireOnViewChange(
642 TRACE("(%p, %lx, %ld)\n", this, aspect
, lindex
);
645 * The sink supplies a filter when it registers
646 * we make sure we only send the notifications when that
649 if ((this->sinkAspects
& aspect
) != 0)
651 if (this->sinkInterface
!= NULL
)
653 IAdviseSink_OnViewChange(this->sinkInterface
,
658 * Some sinks want to be unregistered automatically when
659 * the first notification goes out.
661 if ( (this->sinkAdviseFlag
& ADVF_ONLYONCE
) != 0)
663 IAdviseSink_Release(this->sinkInterface
);
665 this->sinkInterface
= NULL
;
666 this->sinkAspects
= 0;
667 this->sinkAdviseFlag
= 0;
673 /* Helper for DataCache_OpenPresStream */
674 static BOOL
DataCache_IsPresentationStream(const STATSTG
*elem
)
676 /* The presentation streams have names of the form "\002OlePresXXX",
677 * where XXX goes from 000 to 999. */
678 static const WCHAR OlePres
[] = { 2,'O','l','e','P','r','e','s' };
680 LPCWSTR name
= elem
->pwcsName
;
682 return (elem
->type
== STGTY_STREAM
)
683 && (elem
->cbSize
.s
.LowPart
>= sizeof(PresentationDataHeader
))
684 && (strlenW(name
) == 11)
685 && (strncmpW(name
, OlePres
, 8) == 0)
686 && CRTDLL_iswdigit(name
[8])
687 && CRTDLL_iswdigit(name
[9])
688 && CRTDLL_iswdigit(name
[10]);
691 /************************************************************************
692 * DataCache_OpenPresStream
694 * This method will find the stream for the given presentation. It makes
695 * no attempt at fallback.
698 * this - Pointer to the DataCache object
699 * drawAspect - The aspect of the object that we wish to draw.
700 * pStm - A returned stream. It points to the beginning of the
701 * - presentation data, including the header.
704 * S_OK The requested stream has been opened.
705 * OLE_E_BLANK The requested stream could not be found.
706 * Quite a few others I'm too lazy to map correctly.
709 * Algorithm: Scan the elements of the presentation storage, looking
710 * for presentation streams. For each presentation stream,
711 * load the header and check to see if the aspect maches.
713 * If a fallback is desired, just opening the first presentation stream
716 static HRESULT
DataCache_OpenPresStream(
725 if (!ppStm
) return E_POINTER
;
727 hr
= IStorage_EnumElements(this->presentationStorage
, 0, NULL
, 0, &pEnum
);
728 if (FAILED(hr
)) return hr
;
730 while ((hr
= IEnumSTATSTG_Next(pEnum
, 1, &elem
, NULL
)) == S_OK
)
732 if (DataCache_IsPresentationStream(&elem
))
736 hr
= IStorage_OpenStream(this->presentationStorage
, elem
.pwcsName
,
737 NULL
, STGM_READ
| STGM_SHARE_EXCLUSIVE
, 0,
741 PresentationDataHeader header
;
744 hr
= IStream_Read(pStm
, &header
, sizeof(header
), &actual_read
);
746 /* can't use SUCCEEDED(hr): S_FALSE counts as an error */
747 if (hr
== S_OK
&& actual_read
== sizeof(header
)
748 && header
.dvAspect
== drawAspect
)
750 /* Rewind the stream before returning it. */
751 LARGE_INTEGER offset
;
752 offset
.s
.LowPart
= 0;
753 offset
.s
.HighPart
= 0;
754 IStream_Seek(pStm
, offset
, STREAM_SEEK_SET
, NULL
);
758 CoTaskMemFree(elem
.pwcsName
);
759 IEnumSTATSTG_Release(pEnum
);
764 IStream_Release(pStm
);
768 CoTaskMemFree(elem
.pwcsName
);
771 IEnumSTATSTG_Release(pEnum
);
773 return (hr
== S_FALSE
? OLE_E_BLANK
: hr
);
776 /************************************************************************
777 * DataCache_ReadPresentationData
779 * This method will read information for the requested presentation
780 * into the given structure.
783 * this - Pointer to the DataCache object
784 * drawAspect - The aspect of the object that we wish to draw.
787 * This method returns a metafile handle if it is successful.
788 * it will return 0 if not.
790 static HMETAFILE
DataCache_ReadPresMetafile(
794 LARGE_INTEGER offset
;
795 IStream
* presStream
= NULL
;
799 HMETAFILE newMetafile
= 0;
802 * Open the presentation stream.
804 hres
= DataCache_OpenPresStream(
813 * Get the size of the stream.
815 hres
= IStream_Stat(presStream
,
822 offset
.s
.HighPart
= 0;
823 offset
.s
.LowPart
= sizeof(PresentationDataHeader
);
831 streamInfo
.cbSize
.s
.LowPart
-= offset
.s
.LowPart
;
834 * Allocate a buffer for the metafile bits.
836 metafileBits
= HeapAlloc(GetProcessHeap(),
838 streamInfo
.cbSize
.s
.LowPart
);
841 * Read the metafile bits.
846 streamInfo
.cbSize
.s
.LowPart
,
850 * Create a metafile with those bits.
854 newMetafile
= SetMetaFileBitsEx(streamInfo
.cbSize
.s
.LowPart
, metafileBits
);
860 HeapFree(GetProcessHeap(), 0, metafileBits
);
861 IStream_Release(presStream
);
869 /*********************************************************
870 * Method implementation for the non delegating IUnknown
871 * part of the DataCache class.
874 /************************************************************************
875 * DataCache_NDIUnknown_QueryInterface (IUnknown)
877 * See Windows documentation for more details on IUnknown methods.
879 * This version of QueryInterface will not delegate it's implementation
880 * to the outer unknown.
882 static HRESULT WINAPI
DataCache_NDIUnknown_QueryInterface(
887 _ICOM_THIS_From_NDIUnknown(DataCache
, iface
);
890 * Perform a sanity check on the parameters.
892 if ( (this==0) || (ppvObject
==0) )
896 * Initialize the return parameter.
901 * Compare the riid with the interface IDs implemented by this object.
903 if (memcmp(&IID_IUnknown
, riid
, sizeof(IID_IUnknown
)) == 0)
907 else if (memcmp(&IID_IDataObject
, riid
, sizeof(IID_IDataObject
)) == 0)
909 *ppvObject
= (IDataObject
*)&(this->lpvtbl1
);
911 else if ( (memcmp(&IID_IPersistStorage
, riid
, sizeof(IID_IPersistStorage
)) == 0) ||
912 (memcmp(&IID_IPersist
, riid
, sizeof(IID_IPersist
)) == 0) )
914 *ppvObject
= (IPersistStorage
*)&(this->lpvtbl3
);
916 else if ( (memcmp(&IID_IViewObject
, riid
, sizeof(IID_IViewObject
)) == 0) ||
917 (memcmp(&IID_IViewObject2
, riid
, sizeof(IID_IViewObject2
)) == 0) )
919 *ppvObject
= (IViewObject2
*)&(this->lpvtbl4
);
921 else if ( (memcmp(&IID_IOleCache
, riid
, sizeof(IID_IOleCache
)) == 0) ||
922 (memcmp(&IID_IOleCache2
, riid
, sizeof(IID_IOleCache2
)) == 0) )
924 *ppvObject
= (IOleCache2
*)&(this->lpvtbl5
);
926 else if (memcmp(&IID_IOleCacheControl
, riid
, sizeof(IID_IOleCacheControl
)) == 0)
928 *ppvObject
= (IOleCacheControl
*)&(this->lpvtbl6
);
932 * Check that we obtained an interface.
936 WARN( "() : asking for un supported interface %s\n", debugstr_guid(riid
));
937 return E_NOINTERFACE
;
941 * Query Interface always increases the reference count by one when it is
944 IUnknown_AddRef((IUnknown
*)*ppvObject
);
949 /************************************************************************
950 * DataCache_NDIUnknown_AddRef (IUnknown)
952 * See Windows documentation for more details on IUnknown methods.
954 * This version of QueryInterface will not delegate it's implementation
955 * to the outer unknown.
957 static ULONG WINAPI
DataCache_NDIUnknown_AddRef(
960 _ICOM_THIS_From_NDIUnknown(DataCache
, iface
);
967 /************************************************************************
968 * DataCache_NDIUnknown_Release (IUnknown)
970 * See Windows documentation for more details on IUnknown methods.
972 * This version of QueryInterface will not delegate it's implementation
973 * to the outer unknown.
975 static ULONG WINAPI
DataCache_NDIUnknown_Release(
978 _ICOM_THIS_From_NDIUnknown(DataCache
, iface
);
981 * Decrease the reference count on this object.
986 * If the reference count goes down to 0, perform suicide.
990 DataCache_Destroy(this);
998 /*********************************************************
999 * Method implementation for the IDataObject
1000 * part of the DataCache class.
1003 /************************************************************************
1004 * DataCache_IDataObject_QueryInterface (IUnknown)
1006 * See Windows documentation for more details on IUnknown methods.
1008 static HRESULT WINAPI
DataCache_IDataObject_QueryInterface(
1013 _ICOM_THIS_From_IDataObject(DataCache
, iface
);
1015 return IUnknown_QueryInterface(this->outerUnknown
, riid
, ppvObject
);
1018 /************************************************************************
1019 * DataCache_IDataObject_AddRef (IUnknown)
1021 * See Windows documentation for more details on IUnknown methods.
1023 static ULONG WINAPI
DataCache_IDataObject_AddRef(
1026 _ICOM_THIS_From_IDataObject(DataCache
, iface
);
1028 return IUnknown_AddRef(this->outerUnknown
);
1031 /************************************************************************
1032 * DataCache_IDataObject_Release (IUnknown)
1034 * See Windows documentation for more details on IUnknown methods.
1036 static ULONG WINAPI
DataCache_IDataObject_Release(
1039 _ICOM_THIS_From_IDataObject(DataCache
, iface
);
1041 return IUnknown_Release(this->outerUnknown
);
1044 /************************************************************************
1047 * Get Data from a source dataobject using format pformatetcIn->cfFormat
1048 * See Windows documentation for more details on GetData.
1049 * TODO: Currently only CF_METAFILEPICT is implemented
1051 static HRESULT WINAPI
DataCache_GetData(
1053 LPFORMATETC pformatetcIn
,
1057 HRESULT hrRet
= E_UNEXPECTED
;
1058 IPersistStorage
*pPersistStorage
= 0;
1059 IStorage
*pStorage
= 0;
1060 IStream
*pStream
= 0;
1061 OLECHAR name
[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
1062 HGLOBAL hGlobalMF
= 0;
1064 PresentationDataHeader pdh
;
1065 METAFILEPICT
*mfPict
;
1066 HMETAFILE hMetaFile
= 0;
1068 if (pformatetcIn
->cfFormat
== CF_METAFILEPICT
)
1070 /* Get the Persist Storage */
1072 hr
= IDataObject_QueryInterface(iface
, &IID_IPersistStorage
, (void**)&pPersistStorage
);
1077 /* Create a doc file to copy the doc to a storage */
1079 hr
= StgCreateDocfile(NULL
, STGM_CREATE
| STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, &pStorage
);
1084 /* Save it to storage */
1086 hr
= OleSave(pPersistStorage
, pStorage
, FALSE
);
1091 /* Open the Presentation data srteam */
1093 hr
= IStorage_OpenStream(pStorage
, name
, 0, STGM_CREATE
|STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, 0, &pStream
);
1098 /* Read the presentation header */
1100 hr
= IStream_Read(pStream
, &pdh
, sizeof(PresentationDataHeader
), NULL
);
1105 mfBits
= HeapAlloc(GetProcessHeap(), 0, pdh
.dwSize
);
1107 /* Read the Metafile bits */
1109 hr
= IStream_Read(pStream
, mfBits
, pdh
.dwSize
, NULL
);
1114 /* Create the metafile and place it in the STGMEDIUM structure */
1116 hMetaFile
= SetMetaFileBitsEx(pdh
.dwSize
, mfBits
);
1118 hGlobalMF
= GlobalAlloc(GMEM_SHARE
|GMEM_MOVEABLE
, sizeof(METAFILEPICT
));
1119 mfPict
= (METAFILEPICT
*)GlobalLock(hGlobalMF
);
1120 mfPict
->hMF
= hMetaFile
;
1122 GlobalUnlock(hGlobalMF
);
1124 pmedium
->u
.hGlobal
= hGlobalMF
;
1125 pmedium
->tymed
= TYMED_MFPICT
;
1131 HeapFree(GetProcessHeap(), 0, mfBits
);
1134 IStream_Release(pStream
);
1137 IStorage_Release(pStorage
);
1139 if (pPersistStorage
)
1140 IPersistStorage_Release(pPersistStorage
);
1145 /* TODO: Other formats are not implemented */
1150 static HRESULT WINAPI
DataCache_GetDataHere(
1152 LPFORMATETC pformatetc
,
1159 static HRESULT WINAPI
DataCache_QueryGetData(
1161 LPFORMATETC pformatetc
)
1167 /************************************************************************
1168 * DataCache_EnumFormatEtc (IDataObject)
1170 * The data cache doesn't implement this method.
1172 * See Windows documentation for more details on IDataObject methods.
1174 static HRESULT WINAPI
DataCache_GetCanonicalFormatEtc(
1176 LPFORMATETC pformatectIn
,
1177 LPFORMATETC pformatetcOut
)
1183 /************************************************************************
1184 * DataCache_IDataObject_SetData (IDataObject)
1186 * This method is delegated to the IOleCache2 implementation.
1188 * See Windows documentation for more details on IDataObject methods.
1190 static HRESULT WINAPI
DataCache_IDataObject_SetData(
1192 LPFORMATETC pformatetc
,
1196 IOleCache2
* oleCache
= NULL
;
1199 TRACE("(%p, %p, %p, %d)\n", iface
, pformatetc
, pmedium
, fRelease
);
1201 hres
= IDataObject_QueryInterface(iface
, &IID_IOleCache2
, (void**)&oleCache
);
1204 return E_UNEXPECTED
;
1206 hres
= IOleCache2_SetData(oleCache
, pformatetc
, pmedium
, fRelease
);
1208 IOleCache2_Release(oleCache
);
1213 /************************************************************************
1214 * DataCache_EnumFormatEtc (IDataObject)
1216 * The data cache doesn't implement this method.
1218 * See Windows documentation for more details on IDataObject methods.
1220 static HRESULT WINAPI
DataCache_EnumFormatEtc(
1223 IEnumFORMATETC
** ppenumFormatEtc
)
1229 /************************************************************************
1230 * DataCache_DAdvise (IDataObject)
1232 * The data cache doesn't support connections.
1234 * See Windows documentation for more details on IDataObject methods.
1236 static HRESULT WINAPI
DataCache_DAdvise(
1238 FORMATETC
* pformatetc
,
1240 IAdviseSink
* pAdvSink
,
1241 DWORD
* pdwConnection
)
1244 return OLE_E_ADVISENOTSUPPORTED
;
1247 /************************************************************************
1248 * DataCache_DUnadvise (IDataObject)
1250 * The data cache doesn't support connections.
1252 * See Windows documentation for more details on IDataObject methods.
1254 static HRESULT WINAPI
DataCache_DUnadvise(
1259 return OLE_E_NOCONNECTION
;
1262 /************************************************************************
1263 * DataCache_EnumDAdvise (IDataObject)
1265 * The data cache doesn't support connections.
1267 * See Windows documentation for more details on IDataObject methods.
1269 static HRESULT WINAPI
DataCache_EnumDAdvise(
1271 IEnumSTATDATA
** ppenumAdvise
)
1274 return OLE_E_ADVISENOTSUPPORTED
;
1277 /*********************************************************
1278 * Method implementation for the IDataObject
1279 * part of the DataCache class.
1282 /************************************************************************
1283 * DataCache_IPersistStorage_QueryInterface (IUnknown)
1285 * See Windows documentation for more details on IUnknown methods.
1287 static HRESULT WINAPI
DataCache_IPersistStorage_QueryInterface(
1288 IPersistStorage
* iface
,
1292 _ICOM_THIS_From_IPersistStorage(DataCache
, iface
);
1294 return IUnknown_QueryInterface(this->outerUnknown
, riid
, ppvObject
);
1297 /************************************************************************
1298 * DataCache_IPersistStorage_AddRef (IUnknown)
1300 * See Windows documentation for more details on IUnknown methods.
1302 static ULONG WINAPI
DataCache_IPersistStorage_AddRef(
1303 IPersistStorage
* iface
)
1305 _ICOM_THIS_From_IPersistStorage(DataCache
, iface
);
1307 return IUnknown_AddRef(this->outerUnknown
);
1310 /************************************************************************
1311 * DataCache_IPersistStorage_Release (IUnknown)
1313 * See Windows documentation for more details on IUnknown methods.
1315 static ULONG WINAPI
DataCache_IPersistStorage_Release(
1316 IPersistStorage
* iface
)
1318 _ICOM_THIS_From_IPersistStorage(DataCache
, iface
);
1320 return IUnknown_Release(this->outerUnknown
);
1323 /************************************************************************
1324 * DataCache_GetClassID (IPersistStorage)
1326 * The data cache doesn't implement this method.
1328 * See Windows documentation for more details on IPersistStorage methods.
1330 static HRESULT WINAPI
DataCache_GetClassID(
1331 IPersistStorage
* iface
,
1334 TRACE("(%p, %p)\n", iface
, pClassID
);
1338 /************************************************************************
1339 * DataCache_IsDirty (IPersistStorage)
1341 * Until we actully connect to a running object and retrieve new
1342 * information to it, we never get dirty.
1344 * See Windows documentation for more details on IPersistStorage methods.
1346 static HRESULT WINAPI
DataCache_IsDirty(
1347 IPersistStorage
* iface
)
1349 TRACE("(%p)\n", iface
);
1354 /************************************************************************
1355 * DataCache_InitNew (IPersistStorage)
1357 * The data cache implementation of IPersistStorage_InitNew simply stores
1358 * the storage pointer.
1360 * See Windows documentation for more details on IPersistStorage methods.
1362 static HRESULT WINAPI
DataCache_InitNew(
1363 IPersistStorage
* iface
,
1366 TRACE("(%p, %p)\n", iface
, pStg
);
1368 return DataCache_Load(iface
, pStg
);
1371 /************************************************************************
1372 * DataCache_Load (IPersistStorage)
1374 * The data cache implementation of IPersistStorage_Load doesn't
1375 * actually load anything. Instead, it holds on to the storage pointer
1376 * and it will load the presentation information when the
1377 * IDataObject_GetData or IViewObject2_Draw methods are called.
1379 * See Windows documentation for more details on IPersistStorage methods.
1381 static HRESULT WINAPI
DataCache_Load(
1382 IPersistStorage
* iface
,
1385 _ICOM_THIS_From_IPersistStorage(DataCache
, iface
);
1387 TRACE("(%p, %p)\n", iface
, pStg
);
1389 if (this->presentationStorage
!= NULL
)
1391 IStorage_Release(this->presentationStorage
);
1394 this->presentationStorage
= pStg
;
1396 if (this->presentationStorage
!= NULL
)
1398 IStorage_AddRef(this->presentationStorage
);
1403 /************************************************************************
1404 * DataCache_Save (IPersistStorage)
1406 * Until we actully connect to a running object and retrieve new
1407 * information to it, we never have to save anything. However, it is
1408 * our responsability to copy the information when saving to a new
1411 * See Windows documentation for more details on IPersistStorage methods.
1413 static HRESULT WINAPI
DataCache_Save(
1414 IPersistStorage
* iface
,
1418 _ICOM_THIS_From_IPersistStorage(DataCache
, iface
);
1420 TRACE("(%p, %p, %d)\n", iface
, pStg
, fSameAsLoad
);
1422 if ( (!fSameAsLoad
) &&
1423 (this->presentationStorage
!=NULL
) )
1425 return IStorage_CopyTo(this->presentationStorage
,
1435 /************************************************************************
1436 * DataCache_SaveCompleted (IPersistStorage)
1438 * This method is called to tell the cache to release the storage
1439 * pointer it's currentlu holding.
1441 * See Windows documentation for more details on IPersistStorage methods.
1443 static HRESULT WINAPI
DataCache_SaveCompleted(
1444 IPersistStorage
* iface
,
1447 TRACE("(%p, %p)\n", iface
, pStgNew
);
1452 * First, make sure we get our hands off any storage we have.
1455 DataCache_HandsOffStorage(iface
);
1458 * Then, attach to the new storage.
1461 DataCache_Load(iface
, pStgNew
);
1467 /************************************************************************
1468 * DataCache_HandsOffStorage (IPersistStorage)
1470 * This method is called to tell the cache to release the storage
1471 * pointer it's currentlu holding.
1473 * See Windows documentation for more details on IPersistStorage methods.
1475 static HRESULT WINAPI
DataCache_HandsOffStorage(
1476 IPersistStorage
* iface
)
1478 _ICOM_THIS_From_IPersistStorage(DataCache
, iface
);
1480 TRACE("(%p)\n", iface
);
1482 if (this->presentationStorage
!= NULL
)
1484 IStorage_Release(this->presentationStorage
);
1485 this->presentationStorage
= NULL
;
1491 /*********************************************************
1492 * Method implementation for the IViewObject2
1493 * part of the DataCache class.
1496 /************************************************************************
1497 * DataCache_IViewObject2_QueryInterface (IUnknown)
1499 * See Windows documentation for more details on IUnknown methods.
1501 static HRESULT WINAPI
DataCache_IViewObject2_QueryInterface(
1502 IViewObject2
* iface
,
1506 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1508 return IUnknown_QueryInterface(this->outerUnknown
, riid
, ppvObject
);
1511 /************************************************************************
1512 * DataCache_IViewObject2_AddRef (IUnknown)
1514 * See Windows documentation for more details on IUnknown methods.
1516 static ULONG WINAPI
DataCache_IViewObject2_AddRef(
1517 IViewObject2
* iface
)
1519 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1521 return IUnknown_AddRef(this->outerUnknown
);
1524 /************************************************************************
1525 * DataCache_IViewObject2_Release (IUnknown)
1527 * See Windows documentation for more details on IUnknown methods.
1529 static ULONG WINAPI
DataCache_IViewObject2_Release(
1530 IViewObject2
* iface
)
1532 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1534 return IUnknown_Release(this->outerUnknown
);
1537 /************************************************************************
1538 * DataCache_Draw (IViewObject2)
1540 * This method will draw the cached representation of the object
1541 * to the given device context.
1543 * See Windows documentation for more details on IViewObject2 methods.
1545 static HRESULT WINAPI
DataCache_Draw(
1546 IViewObject2
* iface
,
1550 DVTARGETDEVICE
* ptd
,
1553 LPCRECTL lprcBounds
,
1554 LPCRECTL lprcWBounds
,
1555 IVO_ContCallback pfnContinue
,
1558 PresentationDataHeader presData
;
1559 HMETAFILE presMetafile
= 0;
1562 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1564 TRACE("(%p, %lx, %ld, %p, %x, %x, %p, %p, %p, %lx)\n",
1579 if (lprcBounds
==NULL
)
1580 return E_INVALIDARG
;
1583 * First, we need to retrieve the dimensions of the
1584 * image in the metafile.
1586 hres
= DataCache_ReadPresentationData(this,
1594 * Then, we can extract the metafile itself from the cached
1597 * FIXME Unless it isn't a metafile. I think it could be any CF_XXX type,
1598 * particularly CF_DIB.
1600 presMetafile
= DataCache_ReadPresMetafile(this,
1604 * If we have a metafile, just draw baby...
1605 * We have to be careful not to modify the state of the
1608 if (presMetafile
!=0)
1610 INT prevMapMode
= SetMapMode(hdcDraw
, MM_ANISOTROPIC
);
1612 SIZE oldViewportExt
;
1613 POINT oldViewportOrg
;
1615 SetWindowExtEx(hdcDraw
,
1616 presData
.dwObjectExtentX
,
1617 presData
.dwObjectExtentY
,
1620 SetViewportExtEx(hdcDraw
,
1621 lprcBounds
->right
- lprcBounds
->left
,
1622 lprcBounds
->bottom
- lprcBounds
->top
,
1625 SetViewportOrgEx(hdcDraw
,
1630 PlayMetaFile(hdcDraw
, presMetafile
);
1632 SetWindowExtEx(hdcDraw
,
1637 SetViewportExtEx(hdcDraw
,
1642 SetViewportOrgEx(hdcDraw
,
1647 SetMapMode(hdcDraw
, prevMapMode
);
1649 DeleteMetaFile(presMetafile
);
1655 static HRESULT WINAPI
DataCache_GetColorSet(
1656 IViewObject2
* iface
,
1660 DVTARGETDEVICE
* ptd
,
1661 HDC hicTargetDevice
,
1662 LOGPALETTE
** ppColorSet
)
1668 static HRESULT WINAPI
DataCache_Freeze(
1669 IViewObject2
* iface
,
1679 static HRESULT WINAPI
DataCache_Unfreeze(
1680 IViewObject2
* iface
,
1687 /************************************************************************
1688 * DataCache_SetAdvise (IViewObject2)
1690 * This sets-up an advisory sink with the data cache. When the object's
1691 * view changes, this sink is called.
1693 * See Windows documentation for more details on IViewObject2 methods.
1695 static HRESULT WINAPI
DataCache_SetAdvise(
1696 IViewObject2
* iface
,
1699 IAdviseSink
* pAdvSink
)
1701 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1703 TRACE("(%p, %lx, %lx, %p)\n", iface
, aspects
, advf
, pAdvSink
);
1706 * A call to this function removes the previous sink
1708 if (this->sinkInterface
!= NULL
)
1710 IAdviseSink_Release(this->sinkInterface
);
1711 this->sinkInterface
= NULL
;
1712 this->sinkAspects
= 0;
1713 this->sinkAdviseFlag
= 0;
1717 * Now, setup the new one.
1721 this->sinkInterface
= pAdvSink
;
1722 this->sinkAspects
= aspects
;
1723 this->sinkAdviseFlag
= advf
;
1725 IAdviseSink_AddRef(this->sinkInterface
);
1729 * When the ADVF_PRIMEFIRST flag is set, we have to advise the
1732 if (advf
& ADVF_PRIMEFIRST
)
1734 DataCache_FireOnViewChange(this,
1742 /************************************************************************
1743 * DataCache_GetAdvise (IViewObject2)
1745 * This method queries the current state of the advise sink
1746 * installed on the data cache.
1748 * See Windows documentation for more details on IViewObject2 methods.
1750 static HRESULT WINAPI
DataCache_GetAdvise(
1751 IViewObject2
* iface
,
1754 IAdviseSink
** ppAdvSink
)
1756 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1758 TRACE("(%p, %p, %p, %p)\n", iface
, pAspects
, pAdvf
, ppAdvSink
);
1761 * Just copy all the requested values.
1764 *pAspects
= this->sinkAspects
;
1767 *pAdvf
= this->sinkAdviseFlag
;
1769 if (ppAdvSink
!=NULL
)
1771 IAdviseSink_QueryInterface(this->sinkInterface
,
1779 /************************************************************************
1780 * DataCache_GetExtent (IViewObject2)
1782 * This method retrieves the "natural" size of this cached object.
1784 * See Windows documentation for more details on IViewObject2 methods.
1786 static HRESULT WINAPI
DataCache_GetExtent(
1787 IViewObject2
* iface
,
1790 DVTARGETDEVICE
* ptd
,
1793 PresentationDataHeader presData
;
1794 HRESULT hres
= E_FAIL
;
1796 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1798 TRACE("(%p, %lx, %ld, %p, %p)\n",
1799 iface
, dwDrawAspect
, lindex
, ptd
, lpsizel
);
1808 * Initialize the out parameter.
1814 * This flag should be set to -1.
1817 FIXME("Unimplemented flag lindex = %ld\n", lindex
);
1820 * Right now, we suport only the callback from
1821 * the default handler.
1824 FIXME("Unimplemented ptd = %p\n", ptd
);
1827 * Get the presentation information from the
1830 hres
= DataCache_ReadPresentationData(this,
1834 if (SUCCEEDED(hres
))
1836 lpsizel
->cx
= presData
.dwObjectExtentX
;
1837 lpsizel
->cy
= presData
.dwObjectExtentY
;
1841 * This method returns OLE_E_BLANK when it fails.
1850 /*********************************************************
1851 * Method implementation for the IOleCache2
1852 * part of the DataCache class.
1855 /************************************************************************
1856 * DataCache_IOleCache2_QueryInterface (IUnknown)
1858 * See Windows documentation for more details on IUnknown methods.
1860 static HRESULT WINAPI
DataCache_IOleCache2_QueryInterface(
1865 _ICOM_THIS_From_IOleCache2(DataCache
, iface
);
1867 return IUnknown_QueryInterface(this->outerUnknown
, riid
, ppvObject
);
1870 /************************************************************************
1871 * DataCache_IOleCache2_AddRef (IUnknown)
1873 * See Windows documentation for more details on IUnknown methods.
1875 static ULONG WINAPI
DataCache_IOleCache2_AddRef(
1878 _ICOM_THIS_From_IOleCache2(DataCache
, iface
);
1880 return IUnknown_AddRef(this->outerUnknown
);
1883 /************************************************************************
1884 * DataCache_IOleCache2_Release (IUnknown)
1886 * See Windows documentation for more details on IUnknown methods.
1888 static ULONG WINAPI
DataCache_IOleCache2_Release(
1891 _ICOM_THIS_From_IOleCache2(DataCache
, iface
);
1893 return IUnknown_Release(this->outerUnknown
);
1896 static HRESULT WINAPI
DataCache_Cache(
1898 FORMATETC
* pformatetc
,
1900 DWORD
* pdwConnection
)
1906 static HRESULT WINAPI
DataCache_Uncache(
1914 static HRESULT WINAPI
DataCache_EnumCache(
1916 IEnumSTATDATA
** ppenumSTATDATA
)
1922 static HRESULT WINAPI
DataCache_InitCache(
1924 IDataObject
* pDataObject
)
1930 static HRESULT WINAPI
DataCache_IOleCache2_SetData(
1932 FORMATETC
* pformatetc
,
1940 static HRESULT WINAPI
DataCache_UpdateCache(
1942 LPDATAOBJECT pDataObject
,
1950 static HRESULT WINAPI
DataCache_DiscardCache(
1952 DWORD dwDiscardOptions
)
1959 /*********************************************************
1960 * Method implementation for the IOleCacheControl
1961 * part of the DataCache class.
1964 /************************************************************************
1965 * DataCache_IOleCacheControl_QueryInterface (IUnknown)
1967 * See Windows documentation for more details on IUnknown methods.
1969 static HRESULT WINAPI
DataCache_IOleCacheControl_QueryInterface(
1970 IOleCacheControl
* iface
,
1974 _ICOM_THIS_From_IOleCacheControl(DataCache
, iface
);
1976 return IUnknown_QueryInterface(this->outerUnknown
, riid
, ppvObject
);
1979 /************************************************************************
1980 * DataCache_IOleCacheControl_AddRef (IUnknown)
1982 * See Windows documentation for more details on IUnknown methods.
1984 static ULONG WINAPI
DataCache_IOleCacheControl_AddRef(
1985 IOleCacheControl
* iface
)
1987 _ICOM_THIS_From_IOleCacheControl(DataCache
, iface
);
1989 return IUnknown_AddRef(this->outerUnknown
);
1992 /************************************************************************
1993 * DataCache_IOleCacheControl_Release (IUnknown)
1995 * See Windows documentation for more details on IUnknown methods.
1997 static ULONG WINAPI
DataCache_IOleCacheControl_Release(
1998 IOleCacheControl
* iface
)
2000 _ICOM_THIS_From_IOleCacheControl(DataCache
, iface
);
2002 return IUnknown_Release(this->outerUnknown
);
2005 static HRESULT WINAPI
DataCache_OnRun(
2006 IOleCacheControl
* iface
,
2007 LPDATAOBJECT pDataObject
)
2013 static HRESULT WINAPI
DataCache_OnStop(
2014 IOleCacheControl
* iface
)