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.
38 #include "wine/obj_oleview.h"
39 #include "wine/obj_cache.h"
40 #include "wine/unicode.h"
42 #include "debugtools.h"
44 DEFAULT_DEBUG_CHANNEL(ole
);
46 /****************************************************************************
47 * PresentationDataHeader
49 * This structure represents the header of the \002OlePresXXX stream in
50 * the OLE object strorage.
52 * Most fields are still unknown.
54 typedef struct PresentationDataHeader
56 DWORD unknown1
; /* -1 */
57 DWORD unknown2
; /* 3, possibly CF_METAFILEPICT */
58 DWORD unknown3
; /* 4, possibly TYMED_ISTREAM */
60 DWORD unknown5
; /* -1 */
63 DWORD unknown7
; /* 0 */
64 DWORD dwObjectExtentX
;
65 DWORD dwObjectExtentY
;
67 } PresentationDataHeader
;
69 /****************************************************************************
75 * List all interface VTables here
77 ICOM_VTABLE(IDataObject
)* lpvtbl1
;
78 ICOM_VTABLE(IUnknown
)* lpvtbl2
;
79 ICOM_VTABLE(IPersistStorage
)* lpvtbl3
;
80 ICOM_VTABLE(IViewObject2
)* lpvtbl4
;
81 ICOM_VTABLE(IOleCache2
)* lpvtbl5
;
82 ICOM_VTABLE(IOleCacheControl
)* lpvtbl6
;
85 * Reference count of this object
90 * IUnknown implementation of the outer object.
92 IUnknown
* outerUnknown
;
95 * This storage pointer is set through a call to
96 * IPersistStorage_Load. This is where the visual
97 * representation of the object is stored.
99 IStorage
* presentationStorage
;
102 * The user of this object can setup ONE advise sink
103 * connection with the object. These parameters describe
107 DWORD sinkAdviseFlag
;
108 IAdviseSink
* sinkInterface
;
112 typedef struct DataCache DataCache
;
115 * Here, I define utility macros to help with the casting of the
117 * There is a version to accomodate all of the VTables implemented
120 #define _ICOM_THIS_From_IDataObject(class,name) class* this = (class*)name;
121 #define _ICOM_THIS_From_NDIUnknown(class, name) class* this = (class*)(((char*)name)-sizeof(void*));
122 #define _ICOM_THIS_From_IPersistStorage(class, name) class* this = (class*)(((char*)name)-2*sizeof(void*));
123 #define _ICOM_THIS_From_IViewObject2(class, name) class* this = (class*)(((char*)name)-3*sizeof(void*));
124 #define _ICOM_THIS_From_IOleCache2(class, name) class* this = (class*)(((char*)name)-4*sizeof(void*));
125 #define _ICOM_THIS_From_IOleCacheControl(class, name) class* this = (class*)(((char*)name)-5*sizeof(void*));
128 * Prototypes for the methods of the DataCache class.
130 static DataCache
* DataCache_Construct(REFCLSID clsid
,
131 LPUNKNOWN pUnkOuter
);
132 static void DataCache_Destroy(DataCache
* ptrToDestroy
);
133 static HRESULT
DataCache_ReadPresentationData(DataCache
* this,
135 PresentationDataHeader
* header
);
136 static HRESULT
DataCache_OpenPresStream(DataCache
*this,
139 static HMETAFILE
DataCache_ReadPresMetafile(DataCache
* this,
141 static void DataCache_FireOnViewChange(DataCache
* this,
146 * Prototypes for the methods of the DataCache class
147 * that implement non delegating IUnknown methods.
149 static HRESULT WINAPI
DataCache_NDIUnknown_QueryInterface(
153 static ULONG WINAPI
DataCache_NDIUnknown_AddRef(
155 static ULONG WINAPI
DataCache_NDIUnknown_Release(
159 * Prototypes for the methods of the DataCache class
160 * that implement IDataObject methods.
162 static HRESULT WINAPI
DataCache_IDataObject_QueryInterface(
166 static ULONG WINAPI
DataCache_IDataObject_AddRef(
168 static ULONG WINAPI
DataCache_IDataObject_Release(
170 static HRESULT WINAPI
DataCache_GetData(
172 LPFORMATETC pformatetcIn
,
174 static HRESULT WINAPI
DataCache_GetDataHere(
176 LPFORMATETC pformatetc
,
178 static HRESULT WINAPI
DataCache_QueryGetData(
180 LPFORMATETC pformatetc
);
181 static HRESULT WINAPI
DataCache_GetCanonicalFormatEtc(
183 LPFORMATETC pformatectIn
,
184 LPFORMATETC pformatetcOut
);
185 static HRESULT WINAPI
DataCache_IDataObject_SetData(
187 LPFORMATETC pformatetc
,
190 static HRESULT WINAPI
DataCache_EnumFormatEtc(
193 IEnumFORMATETC
** ppenumFormatEtc
);
194 static HRESULT WINAPI
DataCache_DAdvise(
196 FORMATETC
* pformatetc
,
198 IAdviseSink
* pAdvSink
,
199 DWORD
* pdwConnection
);
200 static HRESULT WINAPI
DataCache_DUnadvise(
203 static HRESULT WINAPI
DataCache_EnumDAdvise(
205 IEnumSTATDATA
** ppenumAdvise
);
208 * Prototypes for the methods of the DataCache class
209 * that implement IPersistStorage methods.
211 static HRESULT WINAPI
DataCache_IPersistStorage_QueryInterface(
212 IPersistStorage
* iface
,
215 static ULONG WINAPI
DataCache_IPersistStorage_AddRef(
216 IPersistStorage
* iface
);
217 static ULONG WINAPI
DataCache_IPersistStorage_Release(
218 IPersistStorage
* iface
);
219 static HRESULT WINAPI
DataCache_GetClassID(
220 IPersistStorage
* iface
,
222 static HRESULT WINAPI
DataCache_IsDirty(
223 IPersistStorage
* iface
);
224 static HRESULT WINAPI
DataCache_InitNew(
225 IPersistStorage
* iface
,
227 static HRESULT WINAPI
DataCache_Load(
228 IPersistStorage
* iface
,
230 static HRESULT WINAPI
DataCache_Save(
231 IPersistStorage
* iface
,
234 static HRESULT WINAPI
DataCache_SaveCompleted(
235 IPersistStorage
* iface
,
237 static HRESULT WINAPI
DataCache_HandsOffStorage(
238 IPersistStorage
* iface
);
241 * Prototypes for the methods of the DataCache class
242 * that implement IViewObject2 methods.
244 static HRESULT WINAPI
DataCache_IViewObject2_QueryInterface(
248 static ULONG WINAPI
DataCache_IViewObject2_AddRef(
249 IViewObject2
* iface
);
250 static ULONG WINAPI
DataCache_IViewObject2_Release(
251 IViewObject2
* iface
);
252 static HRESULT WINAPI
DataCache_Draw(
261 LPCRECTL lprcWBounds
,
262 IVO_ContCallback pfnContinue
,
264 static HRESULT WINAPI
DataCache_GetColorSet(
271 LOGPALETTE
** ppColorSet
);
272 static HRESULT WINAPI
DataCache_Freeze(
278 static HRESULT WINAPI
DataCache_Unfreeze(
281 static HRESULT WINAPI
DataCache_SetAdvise(
285 IAdviseSink
* pAdvSink
);
286 static HRESULT WINAPI
DataCache_GetAdvise(
290 IAdviseSink
** ppAdvSink
);
291 static HRESULT WINAPI
DataCache_GetExtent(
299 * Prototypes for the methods of the DataCache class
300 * that implement IOleCache2 methods.
302 static HRESULT WINAPI
DataCache_IOleCache2_QueryInterface(
306 static ULONG WINAPI
DataCache_IOleCache2_AddRef(
308 static ULONG WINAPI
DataCache_IOleCache2_Release(
310 static HRESULT WINAPI
DataCache_Cache(
312 FORMATETC
* pformatetc
,
314 DWORD
* pdwConnection
);
315 static HRESULT WINAPI
DataCache_Uncache(
318 static HRESULT WINAPI
DataCache_EnumCache(
320 IEnumSTATDATA
** ppenumSTATDATA
);
321 static HRESULT WINAPI
DataCache_InitCache(
323 IDataObject
* pDataObject
);
324 static HRESULT WINAPI
DataCache_IOleCache2_SetData(
326 FORMATETC
* pformatetc
,
329 static HRESULT WINAPI
DataCache_UpdateCache(
331 LPDATAOBJECT pDataObject
,
334 static HRESULT WINAPI
DataCache_DiscardCache(
336 DWORD dwDiscardOptions
);
339 * Prototypes for the methods of the DataCache class
340 * that implement IOleCacheControl methods.
342 static HRESULT WINAPI
DataCache_IOleCacheControl_QueryInterface(
343 IOleCacheControl
* iface
,
346 static ULONG WINAPI
DataCache_IOleCacheControl_AddRef(
347 IOleCacheControl
* iface
);
348 static ULONG WINAPI
DataCache_IOleCacheControl_Release(
349 IOleCacheControl
* iface
);
350 static HRESULT WINAPI
DataCache_OnRun(
351 IOleCacheControl
* iface
,
352 LPDATAOBJECT pDataObject
);
353 static HRESULT WINAPI
DataCache_OnStop(
354 IOleCacheControl
* iface
);
357 * Virtual function tables for the DataCache class.
359 static ICOM_VTABLE(IUnknown
) DataCache_NDIUnknown_VTable
=
361 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
362 DataCache_NDIUnknown_QueryInterface
,
363 DataCache_NDIUnknown_AddRef
,
364 DataCache_NDIUnknown_Release
367 static ICOM_VTABLE(IDataObject
) DataCache_IDataObject_VTable
=
369 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
370 DataCache_IDataObject_QueryInterface
,
371 DataCache_IDataObject_AddRef
,
372 DataCache_IDataObject_Release
,
374 DataCache_GetDataHere
,
375 DataCache_QueryGetData
,
376 DataCache_GetCanonicalFormatEtc
,
377 DataCache_IDataObject_SetData
,
378 DataCache_EnumFormatEtc
,
381 DataCache_EnumDAdvise
384 static ICOM_VTABLE(IPersistStorage
) DataCache_IPersistStorage_VTable
=
386 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
387 DataCache_IPersistStorage_QueryInterface
,
388 DataCache_IPersistStorage_AddRef
,
389 DataCache_IPersistStorage_Release
,
390 DataCache_GetClassID
,
395 DataCache_SaveCompleted
,
396 DataCache_HandsOffStorage
399 static ICOM_VTABLE(IViewObject2
) DataCache_IViewObject2_VTable
=
401 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
402 DataCache_IViewObject2_QueryInterface
,
403 DataCache_IViewObject2_AddRef
,
404 DataCache_IViewObject2_Release
,
406 DataCache_GetColorSet
,
414 static ICOM_VTABLE(IOleCache2
) DataCache_IOleCache2_VTable
=
416 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
417 DataCache_IOleCache2_QueryInterface
,
418 DataCache_IOleCache2_AddRef
,
419 DataCache_IOleCache2_Release
,
424 DataCache_IOleCache2_SetData
,
425 DataCache_UpdateCache
,
426 DataCache_DiscardCache
429 static ICOM_VTABLE(IOleCacheControl
) DataCache_IOleCacheControl_VTable
=
431 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
432 DataCache_IOleCacheControl_QueryInterface
,
433 DataCache_IOleCacheControl_AddRef
,
434 DataCache_IOleCacheControl_Release
,
439 /******************************************************************************
440 * CreateDataCache [OLE32.54]
442 HRESULT WINAPI
CreateDataCache(
448 DataCache
* newCache
= NULL
;
451 TRACE("(%s, %p, %s, %p)\n", debugstr_guid(rclsid
), pUnkOuter
, debugstr_guid(riid
), ppvObj
);
462 * If this cache is constructed for aggregation, make sure
463 * the caller is requesting the IUnknown interface.
464 * This is necessary because it's the only time the non-delegating
465 * IUnknown pointer can be returned to the outside.
467 if ( (pUnkOuter
!=NULL
) &&
468 (memcmp(&IID_IUnknown
, riid
, sizeof(IID_IUnknown
)) != 0) )
469 return CLASS_E_NOAGGREGATION
;
472 * Try to construct a new instance of the class.
474 newCache
= DataCache_Construct(rclsid
,
478 return E_OUTOFMEMORY
;
481 * Make sure it supports the interface required by the caller.
483 hr
= IUnknown_QueryInterface((IUnknown
*)&(newCache
->lpvtbl2
), riid
, ppvObj
);
486 * Release the reference obtained in the constructor. If
487 * the QueryInterface was unsuccessful, it will free the class.
489 IUnknown_Release((IUnknown
*)&(newCache
->lpvtbl2
));
494 /*********************************************************
495 * Method implementation for DataCache class.
497 static DataCache
* DataCache_Construct(
501 DataCache
* newObject
= 0;
504 * Allocate space for the object.
506 newObject
= HeapAlloc(GetProcessHeap(), 0, sizeof(DataCache
));
512 * Initialize the virtual function table.
514 newObject
->lpvtbl1
= &DataCache_IDataObject_VTable
;
515 newObject
->lpvtbl2
= &DataCache_NDIUnknown_VTable
;
516 newObject
->lpvtbl3
= &DataCache_IPersistStorage_VTable
;
517 newObject
->lpvtbl4
= &DataCache_IViewObject2_VTable
;
518 newObject
->lpvtbl5
= &DataCache_IOleCache2_VTable
;
519 newObject
->lpvtbl6
= &DataCache_IOleCacheControl_VTable
;
522 * Start with one reference count. The caller of this function
523 * must release the interface pointer when it is done.
528 * Initialize the outer unknown
529 * We don't keep a reference on the outer unknown since, the way
530 * aggregation works, our lifetime is at least as large as it's
534 pUnkOuter
= (IUnknown
*)&(newObject
->lpvtbl2
);
536 newObject
->outerUnknown
= pUnkOuter
;
539 * Initialize the other members of the structure.
541 newObject
->presentationStorage
= NULL
;
542 newObject
->sinkAspects
= 0;
543 newObject
->sinkAdviseFlag
= 0;
544 newObject
->sinkInterface
= 0;
549 static void DataCache_Destroy(
550 DataCache
* ptrToDestroy
)
554 if (ptrToDestroy
->sinkInterface
!= NULL
)
556 IAdviseSink_Release(ptrToDestroy
->sinkInterface
);
557 ptrToDestroy
->sinkInterface
= NULL
;
560 if (ptrToDestroy
->presentationStorage
!= NULL
)
562 IStorage_Release(ptrToDestroy
->presentationStorage
);
563 ptrToDestroy
->presentationStorage
= NULL
;
567 * Free the datacache pointer.
569 HeapFree(GetProcessHeap(), 0, ptrToDestroy
);
572 /************************************************************************
573 * DataCache_ReadPresentationData
575 * This method will read information for the requested presentation
576 * into the given structure.
579 * this - Pointer to the DataCache object
580 * drawAspect - The aspect of the object that we wish to draw.
581 * header - The structure containing information about this
582 * aspect of the object.
584 static HRESULT
DataCache_ReadPresentationData(
587 PresentationDataHeader
* header
)
589 IStream
* presStream
= NULL
;
593 * Open the presentation stream.
595 hres
= DataCache_OpenPresStream(
610 sizeof(PresentationDataHeader
),
616 IStream_Release(presStream
);
619 * We don't want to propagate any other error
620 * code than a failure.
628 /************************************************************************
629 * DataCache_FireOnViewChange
631 * This method will fire an OnViewChange notification to the advise
632 * sink registered with the datacache.
634 * See IAdviseSink::OnViewChange for more details.
636 static void DataCache_FireOnViewChange(
641 TRACE("(%p, %lx, %ld)\n", this, aspect
, lindex
);
644 * The sink supplies a filter when it registers
645 * we make sure we only send the notifications when that
648 if ((this->sinkAspects
& aspect
) != 0)
650 if (this->sinkInterface
!= NULL
)
652 IAdviseSink_OnViewChange(this->sinkInterface
,
657 * Some sinks want to be unregistered automatically when
658 * the first notification goes out.
660 if ( (this->sinkAdviseFlag
& ADVF_ONLYONCE
) != 0)
662 IAdviseSink_Release(this->sinkInterface
);
664 this->sinkInterface
= NULL
;
665 this->sinkAspects
= 0;
666 this->sinkAdviseFlag
= 0;
672 /* Helper for DataCache_OpenPresStream */
673 static BOOL
DataCache_IsPresentationStream(const STATSTG
*elem
)
675 /* The presentation streams have names of the form "\002OlePresXXX",
676 * where XXX goes from 000 to 999. */
677 static const WCHAR OlePres
[] = { 2,'O','l','e','P','r','e','s' };
679 LPCWSTR name
= elem
->pwcsName
;
681 return (elem
->type
== STGTY_STREAM
)
682 && (elem
->cbSize
.s
.LowPart
>= sizeof(PresentationDataHeader
))
683 && (strlenW(name
) == 11)
684 && (strncmpW(name
, OlePres
, 8) == 0)
685 && (name
[8] >= '0') && (name
[8] <= '9')
686 && (name
[9] >= '0') && (name
[9] <= '9')
687 && (name
[10] >= '0') && (name
[10] <= '9');
690 /************************************************************************
691 * DataCache_OpenPresStream
693 * This method will find the stream for the given presentation. It makes
694 * no attempt at fallback.
697 * this - Pointer to the DataCache object
698 * drawAspect - The aspect of the object that we wish to draw.
699 * pStm - A returned stream. It points to the beginning of the
700 * - presentation data, including the header.
703 * S_OK The requested stream has been opened.
704 * OLE_E_BLANK The requested stream could not be found.
705 * Quite a few others I'm too lazy to map correctly.
708 * Algorithm: Scan the elements of the presentation storage, looking
709 * for presentation streams. For each presentation stream,
710 * load the header and check to see if the aspect maches.
712 * If a fallback is desired, just opening the first presentation stream
715 static HRESULT
DataCache_OpenPresStream(
724 if (!ppStm
) return E_POINTER
;
726 hr
= IStorage_EnumElements(this->presentationStorage
, 0, NULL
, 0, &pEnum
);
727 if (FAILED(hr
)) return hr
;
729 while ((hr
= IEnumSTATSTG_Next(pEnum
, 1, &elem
, NULL
)) == S_OK
)
731 if (DataCache_IsPresentationStream(&elem
))
735 hr
= IStorage_OpenStream(this->presentationStorage
, elem
.pwcsName
,
736 NULL
, STGM_READ
| STGM_SHARE_EXCLUSIVE
, 0,
740 PresentationDataHeader header
;
743 hr
= IStream_Read(pStm
, &header
, sizeof(header
), &actual_read
);
745 /* can't use SUCCEEDED(hr): S_FALSE counts as an error */
746 if (hr
== S_OK
&& actual_read
== sizeof(header
)
747 && header
.dvAspect
== drawAspect
)
749 /* Rewind the stream before returning it. */
750 LARGE_INTEGER offset
;
751 offset
.s
.LowPart
= 0;
752 offset
.s
.HighPart
= 0;
753 IStream_Seek(pStm
, offset
, STREAM_SEEK_SET
, NULL
);
757 CoTaskMemFree(elem
.pwcsName
);
758 IEnumSTATSTG_Release(pEnum
);
763 IStream_Release(pStm
);
767 CoTaskMemFree(elem
.pwcsName
);
770 IEnumSTATSTG_Release(pEnum
);
772 return (hr
== S_FALSE
? OLE_E_BLANK
: hr
);
775 /************************************************************************
776 * DataCache_ReadPresentationData
778 * This method will read information for the requested presentation
779 * into the given structure.
782 * this - Pointer to the DataCache object
783 * drawAspect - The aspect of the object that we wish to draw.
786 * This method returns a metafile handle if it is successful.
787 * it will return 0 if not.
789 static HMETAFILE
DataCache_ReadPresMetafile(
793 LARGE_INTEGER offset
;
794 IStream
* presStream
= NULL
;
798 HMETAFILE newMetafile
= 0;
801 * Open the presentation stream.
803 hres
= DataCache_OpenPresStream(
812 * Get the size of the stream.
814 hres
= IStream_Stat(presStream
,
821 offset
.s
.HighPart
= 0;
822 offset
.s
.LowPart
= sizeof(PresentationDataHeader
);
830 streamInfo
.cbSize
.s
.LowPart
-= offset
.s
.LowPart
;
833 * Allocate a buffer for the metafile bits.
835 metafileBits
= HeapAlloc(GetProcessHeap(),
837 streamInfo
.cbSize
.s
.LowPart
);
840 * Read the metafile bits.
845 streamInfo
.cbSize
.s
.LowPart
,
849 * Create a metafile with those bits.
853 newMetafile
= SetMetaFileBitsEx(streamInfo
.cbSize
.s
.LowPart
, metafileBits
);
859 HeapFree(GetProcessHeap(), 0, metafileBits
);
860 IStream_Release(presStream
);
868 /*********************************************************
869 * Method implementation for the non delegating IUnknown
870 * part of the DataCache class.
873 /************************************************************************
874 * DataCache_NDIUnknown_QueryInterface (IUnknown)
876 * See Windows documentation for more details on IUnknown methods.
878 * This version of QueryInterface will not delegate it's implementation
879 * to the outer unknown.
881 static HRESULT WINAPI
DataCache_NDIUnknown_QueryInterface(
886 _ICOM_THIS_From_NDIUnknown(DataCache
, iface
);
889 * Perform a sanity check on the parameters.
891 if ( (this==0) || (ppvObject
==0) )
895 * Initialize the return parameter.
900 * Compare the riid with the interface IDs implemented by this object.
902 if (memcmp(&IID_IUnknown
, riid
, sizeof(IID_IUnknown
)) == 0)
906 else if (memcmp(&IID_IDataObject
, riid
, sizeof(IID_IDataObject
)) == 0)
908 *ppvObject
= (IDataObject
*)&(this->lpvtbl1
);
910 else if ( (memcmp(&IID_IPersistStorage
, riid
, sizeof(IID_IPersistStorage
)) == 0) ||
911 (memcmp(&IID_IPersist
, riid
, sizeof(IID_IPersist
)) == 0) )
913 *ppvObject
= (IPersistStorage
*)&(this->lpvtbl3
);
915 else if ( (memcmp(&IID_IViewObject
, riid
, sizeof(IID_IViewObject
)) == 0) ||
916 (memcmp(&IID_IViewObject2
, riid
, sizeof(IID_IViewObject2
)) == 0) )
918 *ppvObject
= (IViewObject2
*)&(this->lpvtbl4
);
920 else if ( (memcmp(&IID_IOleCache
, riid
, sizeof(IID_IOleCache
)) == 0) ||
921 (memcmp(&IID_IOleCache2
, riid
, sizeof(IID_IOleCache2
)) == 0) )
923 *ppvObject
= (IOleCache2
*)&(this->lpvtbl5
);
925 else if (memcmp(&IID_IOleCacheControl
, riid
, sizeof(IID_IOleCacheControl
)) == 0)
927 *ppvObject
= (IOleCacheControl
*)&(this->lpvtbl6
);
931 * Check that we obtained an interface.
935 WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid
));
936 return E_NOINTERFACE
;
940 * Query Interface always increases the reference count by one when it is
943 IUnknown_AddRef((IUnknown
*)*ppvObject
);
948 /************************************************************************
949 * DataCache_NDIUnknown_AddRef (IUnknown)
951 * See Windows documentation for more details on IUnknown methods.
953 * This version of QueryInterface will not delegate it's implementation
954 * to the outer unknown.
956 static ULONG WINAPI
DataCache_NDIUnknown_AddRef(
959 _ICOM_THIS_From_NDIUnknown(DataCache
, iface
);
966 /************************************************************************
967 * DataCache_NDIUnknown_Release (IUnknown)
969 * See Windows documentation for more details on IUnknown methods.
971 * This version of QueryInterface will not delegate it's implementation
972 * to the outer unknown.
974 static ULONG WINAPI
DataCache_NDIUnknown_Release(
977 _ICOM_THIS_From_NDIUnknown(DataCache
, iface
);
980 * Decrease the reference count on this object.
985 * If the reference count goes down to 0, perform suicide.
989 DataCache_Destroy(this);
997 /*********************************************************
998 * Method implementation for the IDataObject
999 * part of the DataCache class.
1002 /************************************************************************
1003 * DataCache_IDataObject_QueryInterface (IUnknown)
1005 * See Windows documentation for more details on IUnknown methods.
1007 static HRESULT WINAPI
DataCache_IDataObject_QueryInterface(
1012 _ICOM_THIS_From_IDataObject(DataCache
, iface
);
1014 return IUnknown_QueryInterface(this->outerUnknown
, riid
, ppvObject
);
1017 /************************************************************************
1018 * DataCache_IDataObject_AddRef (IUnknown)
1020 * See Windows documentation for more details on IUnknown methods.
1022 static ULONG WINAPI
DataCache_IDataObject_AddRef(
1025 _ICOM_THIS_From_IDataObject(DataCache
, iface
);
1027 return IUnknown_AddRef(this->outerUnknown
);
1030 /************************************************************************
1031 * DataCache_IDataObject_Release (IUnknown)
1033 * See Windows documentation for more details on IUnknown methods.
1035 static ULONG WINAPI
DataCache_IDataObject_Release(
1038 _ICOM_THIS_From_IDataObject(DataCache
, iface
);
1040 return IUnknown_Release(this->outerUnknown
);
1043 /************************************************************************
1046 * Get Data from a source dataobject using format pformatetcIn->cfFormat
1047 * See Windows documentation for more details on GetData.
1048 * TODO: Currently only CF_METAFILEPICT is implemented
1050 static HRESULT WINAPI
DataCache_GetData(
1052 LPFORMATETC pformatetcIn
,
1056 HRESULT hrRet
= E_UNEXPECTED
;
1057 IPersistStorage
*pPersistStorage
= 0;
1058 IStorage
*pStorage
= 0;
1059 IStream
*pStream
= 0;
1060 OLECHAR name
[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
1061 HGLOBAL hGlobalMF
= 0;
1063 PresentationDataHeader pdh
;
1064 METAFILEPICT
*mfPict
;
1065 HMETAFILE hMetaFile
= 0;
1067 if (pformatetcIn
->cfFormat
== CF_METAFILEPICT
)
1069 /* Get the Persist Storage */
1071 hr
= IDataObject_QueryInterface(iface
, &IID_IPersistStorage
, (void**)&pPersistStorage
);
1076 /* Create a doc file to copy the doc to a storage */
1078 hr
= StgCreateDocfile(NULL
, STGM_CREATE
| STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, &pStorage
);
1083 /* Save it to storage */
1085 hr
= OleSave(pPersistStorage
, pStorage
, FALSE
);
1090 /* Open the Presentation data srteam */
1092 hr
= IStorage_OpenStream(pStorage
, name
, 0, STGM_CREATE
|STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, 0, &pStream
);
1097 /* Read the presentation header */
1099 hr
= IStream_Read(pStream
, &pdh
, sizeof(PresentationDataHeader
), NULL
);
1104 mfBits
= HeapAlloc(GetProcessHeap(), 0, pdh
.dwSize
);
1106 /* Read the Metafile bits */
1108 hr
= IStream_Read(pStream
, mfBits
, pdh
.dwSize
, NULL
);
1113 /* Create the metafile and place it in the STGMEDIUM structure */
1115 hMetaFile
= SetMetaFileBitsEx(pdh
.dwSize
, mfBits
);
1117 hGlobalMF
= GlobalAlloc(GMEM_SHARE
|GMEM_MOVEABLE
, sizeof(METAFILEPICT
));
1118 mfPict
= (METAFILEPICT
*)GlobalLock(hGlobalMF
);
1119 mfPict
->hMF
= hMetaFile
;
1121 GlobalUnlock(hGlobalMF
);
1123 pmedium
->u
.hGlobal
= hGlobalMF
;
1124 pmedium
->tymed
= TYMED_MFPICT
;
1130 HeapFree(GetProcessHeap(), 0, mfBits
);
1133 IStream_Release(pStream
);
1136 IStorage_Release(pStorage
);
1138 if (pPersistStorage
)
1139 IPersistStorage_Release(pPersistStorage
);
1144 /* TODO: Other formats are not implemented */
1149 static HRESULT WINAPI
DataCache_GetDataHere(
1151 LPFORMATETC pformatetc
,
1158 static HRESULT WINAPI
DataCache_QueryGetData(
1160 LPFORMATETC pformatetc
)
1166 /************************************************************************
1167 * DataCache_EnumFormatEtc (IDataObject)
1169 * The data cache doesn't implement this method.
1171 * See Windows documentation for more details on IDataObject methods.
1173 static HRESULT WINAPI
DataCache_GetCanonicalFormatEtc(
1175 LPFORMATETC pformatectIn
,
1176 LPFORMATETC pformatetcOut
)
1182 /************************************************************************
1183 * DataCache_IDataObject_SetData (IDataObject)
1185 * This method is delegated to the IOleCache2 implementation.
1187 * See Windows documentation for more details on IDataObject methods.
1189 static HRESULT WINAPI
DataCache_IDataObject_SetData(
1191 LPFORMATETC pformatetc
,
1195 IOleCache2
* oleCache
= NULL
;
1198 TRACE("(%p, %p, %p, %d)\n", iface
, pformatetc
, pmedium
, fRelease
);
1200 hres
= IDataObject_QueryInterface(iface
, &IID_IOleCache2
, (void**)&oleCache
);
1203 return E_UNEXPECTED
;
1205 hres
= IOleCache2_SetData(oleCache
, pformatetc
, pmedium
, fRelease
);
1207 IOleCache2_Release(oleCache
);
1212 /************************************************************************
1213 * DataCache_EnumFormatEtc (IDataObject)
1215 * The data cache doesn't implement this method.
1217 * See Windows documentation for more details on IDataObject methods.
1219 static HRESULT WINAPI
DataCache_EnumFormatEtc(
1222 IEnumFORMATETC
** ppenumFormatEtc
)
1228 /************************************************************************
1229 * DataCache_DAdvise (IDataObject)
1231 * The data cache doesn't support connections.
1233 * See Windows documentation for more details on IDataObject methods.
1235 static HRESULT WINAPI
DataCache_DAdvise(
1237 FORMATETC
* pformatetc
,
1239 IAdviseSink
* pAdvSink
,
1240 DWORD
* pdwConnection
)
1243 return OLE_E_ADVISENOTSUPPORTED
;
1246 /************************************************************************
1247 * DataCache_DUnadvise (IDataObject)
1249 * The data cache doesn't support connections.
1251 * See Windows documentation for more details on IDataObject methods.
1253 static HRESULT WINAPI
DataCache_DUnadvise(
1258 return OLE_E_NOCONNECTION
;
1261 /************************************************************************
1262 * DataCache_EnumDAdvise (IDataObject)
1264 * The data cache doesn't support connections.
1266 * See Windows documentation for more details on IDataObject methods.
1268 static HRESULT WINAPI
DataCache_EnumDAdvise(
1270 IEnumSTATDATA
** ppenumAdvise
)
1273 return OLE_E_ADVISENOTSUPPORTED
;
1276 /*********************************************************
1277 * Method implementation for the IDataObject
1278 * part of the DataCache class.
1281 /************************************************************************
1282 * DataCache_IPersistStorage_QueryInterface (IUnknown)
1284 * See Windows documentation for more details on IUnknown methods.
1286 static HRESULT WINAPI
DataCache_IPersistStorage_QueryInterface(
1287 IPersistStorage
* iface
,
1291 _ICOM_THIS_From_IPersistStorage(DataCache
, iface
);
1293 return IUnknown_QueryInterface(this->outerUnknown
, riid
, ppvObject
);
1296 /************************************************************************
1297 * DataCache_IPersistStorage_AddRef (IUnknown)
1299 * See Windows documentation for more details on IUnknown methods.
1301 static ULONG WINAPI
DataCache_IPersistStorage_AddRef(
1302 IPersistStorage
* iface
)
1304 _ICOM_THIS_From_IPersistStorage(DataCache
, iface
);
1306 return IUnknown_AddRef(this->outerUnknown
);
1309 /************************************************************************
1310 * DataCache_IPersistStorage_Release (IUnknown)
1312 * See Windows documentation for more details on IUnknown methods.
1314 static ULONG WINAPI
DataCache_IPersistStorage_Release(
1315 IPersistStorage
* iface
)
1317 _ICOM_THIS_From_IPersistStorage(DataCache
, iface
);
1319 return IUnknown_Release(this->outerUnknown
);
1322 /************************************************************************
1323 * DataCache_GetClassID (IPersistStorage)
1325 * The data cache doesn't implement this method.
1327 * See Windows documentation for more details on IPersistStorage methods.
1329 static HRESULT WINAPI
DataCache_GetClassID(
1330 IPersistStorage
* iface
,
1333 TRACE("(%p, %p)\n", iface
, pClassID
);
1337 /************************************************************************
1338 * DataCache_IsDirty (IPersistStorage)
1340 * Until we actully connect to a running object and retrieve new
1341 * information to it, we never get dirty.
1343 * See Windows documentation for more details on IPersistStorage methods.
1345 static HRESULT WINAPI
DataCache_IsDirty(
1346 IPersistStorage
* iface
)
1348 TRACE("(%p)\n", iface
);
1353 /************************************************************************
1354 * DataCache_InitNew (IPersistStorage)
1356 * The data cache implementation of IPersistStorage_InitNew simply stores
1357 * the storage pointer.
1359 * See Windows documentation for more details on IPersistStorage methods.
1361 static HRESULT WINAPI
DataCache_InitNew(
1362 IPersistStorage
* iface
,
1365 TRACE("(%p, %p)\n", iface
, pStg
);
1367 return DataCache_Load(iface
, pStg
);
1370 /************************************************************************
1371 * DataCache_Load (IPersistStorage)
1373 * The data cache implementation of IPersistStorage_Load doesn't
1374 * actually load anything. Instead, it holds on to the storage pointer
1375 * and it will load the presentation information when the
1376 * IDataObject_GetData or IViewObject2_Draw methods are called.
1378 * See Windows documentation for more details on IPersistStorage methods.
1380 static HRESULT WINAPI
DataCache_Load(
1381 IPersistStorage
* iface
,
1384 _ICOM_THIS_From_IPersistStorage(DataCache
, iface
);
1386 TRACE("(%p, %p)\n", iface
, pStg
);
1388 if (this->presentationStorage
!= NULL
)
1390 IStorage_Release(this->presentationStorage
);
1393 this->presentationStorage
= pStg
;
1395 if (this->presentationStorage
!= NULL
)
1397 IStorage_AddRef(this->presentationStorage
);
1402 /************************************************************************
1403 * DataCache_Save (IPersistStorage)
1405 * Until we actully connect to a running object and retrieve new
1406 * information to it, we never have to save anything. However, it is
1407 * our responsability to copy the information when saving to a new
1410 * See Windows documentation for more details on IPersistStorage methods.
1412 static HRESULT WINAPI
DataCache_Save(
1413 IPersistStorage
* iface
,
1417 _ICOM_THIS_From_IPersistStorage(DataCache
, iface
);
1419 TRACE("(%p, %p, %d)\n", iface
, pStg
, fSameAsLoad
);
1421 if ( (!fSameAsLoad
) &&
1422 (this->presentationStorage
!=NULL
) )
1424 return IStorage_CopyTo(this->presentationStorage
,
1434 /************************************************************************
1435 * DataCache_SaveCompleted (IPersistStorage)
1437 * This method is called to tell the cache to release the storage
1438 * pointer it's currentlu holding.
1440 * See Windows documentation for more details on IPersistStorage methods.
1442 static HRESULT WINAPI
DataCache_SaveCompleted(
1443 IPersistStorage
* iface
,
1446 TRACE("(%p, %p)\n", iface
, pStgNew
);
1451 * First, make sure we get our hands off any storage we have.
1454 DataCache_HandsOffStorage(iface
);
1457 * Then, attach to the new storage.
1460 DataCache_Load(iface
, pStgNew
);
1466 /************************************************************************
1467 * DataCache_HandsOffStorage (IPersistStorage)
1469 * This method is called to tell the cache to release the storage
1470 * pointer it's currentlu holding.
1472 * See Windows documentation for more details on IPersistStorage methods.
1474 static HRESULT WINAPI
DataCache_HandsOffStorage(
1475 IPersistStorage
* iface
)
1477 _ICOM_THIS_From_IPersistStorage(DataCache
, iface
);
1479 TRACE("(%p)\n", iface
);
1481 if (this->presentationStorage
!= NULL
)
1483 IStorage_Release(this->presentationStorage
);
1484 this->presentationStorage
= NULL
;
1490 /*********************************************************
1491 * Method implementation for the IViewObject2
1492 * part of the DataCache class.
1495 /************************************************************************
1496 * DataCache_IViewObject2_QueryInterface (IUnknown)
1498 * See Windows documentation for more details on IUnknown methods.
1500 static HRESULT WINAPI
DataCache_IViewObject2_QueryInterface(
1501 IViewObject2
* iface
,
1505 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1507 return IUnknown_QueryInterface(this->outerUnknown
, riid
, ppvObject
);
1510 /************************************************************************
1511 * DataCache_IViewObject2_AddRef (IUnknown)
1513 * See Windows documentation for more details on IUnknown methods.
1515 static ULONG WINAPI
DataCache_IViewObject2_AddRef(
1516 IViewObject2
* iface
)
1518 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1520 return IUnknown_AddRef(this->outerUnknown
);
1523 /************************************************************************
1524 * DataCache_IViewObject2_Release (IUnknown)
1526 * See Windows documentation for more details on IUnknown methods.
1528 static ULONG WINAPI
DataCache_IViewObject2_Release(
1529 IViewObject2
* iface
)
1531 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1533 return IUnknown_Release(this->outerUnknown
);
1536 /************************************************************************
1537 * DataCache_Draw (IViewObject2)
1539 * This method will draw the cached representation of the object
1540 * to the given device context.
1542 * See Windows documentation for more details on IViewObject2 methods.
1544 static HRESULT WINAPI
DataCache_Draw(
1545 IViewObject2
* iface
,
1549 DVTARGETDEVICE
* ptd
,
1552 LPCRECTL lprcBounds
,
1553 LPCRECTL lprcWBounds
,
1554 IVO_ContCallback pfnContinue
,
1557 PresentationDataHeader presData
;
1558 HMETAFILE presMetafile
= 0;
1561 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1563 TRACE("(%p, %lx, %ld, %p, %x, %x, %p, %p, %p, %lx)\n",
1578 if (lprcBounds
==NULL
)
1579 return E_INVALIDARG
;
1582 * First, we need to retrieve the dimensions of the
1583 * image in the metafile.
1585 hres
= DataCache_ReadPresentationData(this,
1593 * Then, we can extract the metafile itself from the cached
1596 * FIXME Unless it isn't a metafile. I think it could be any CF_XXX type,
1597 * particularly CF_DIB.
1599 presMetafile
= DataCache_ReadPresMetafile(this,
1603 * If we have a metafile, just draw baby...
1604 * We have to be careful not to modify the state of the
1607 if (presMetafile
!=0)
1609 INT prevMapMode
= SetMapMode(hdcDraw
, MM_ANISOTROPIC
);
1611 SIZE oldViewportExt
;
1612 POINT oldViewportOrg
;
1614 SetWindowExtEx(hdcDraw
,
1615 presData
.dwObjectExtentX
,
1616 presData
.dwObjectExtentY
,
1619 SetViewportExtEx(hdcDraw
,
1620 lprcBounds
->right
- lprcBounds
->left
,
1621 lprcBounds
->bottom
- lprcBounds
->top
,
1624 SetViewportOrgEx(hdcDraw
,
1629 PlayMetaFile(hdcDraw
, presMetafile
);
1631 SetWindowExtEx(hdcDraw
,
1636 SetViewportExtEx(hdcDraw
,
1641 SetViewportOrgEx(hdcDraw
,
1646 SetMapMode(hdcDraw
, prevMapMode
);
1648 DeleteMetaFile(presMetafile
);
1654 static HRESULT WINAPI
DataCache_GetColorSet(
1655 IViewObject2
* iface
,
1659 DVTARGETDEVICE
* ptd
,
1660 HDC hicTargetDevice
,
1661 LOGPALETTE
** ppColorSet
)
1667 static HRESULT WINAPI
DataCache_Freeze(
1668 IViewObject2
* iface
,
1678 static HRESULT WINAPI
DataCache_Unfreeze(
1679 IViewObject2
* iface
,
1686 /************************************************************************
1687 * DataCache_SetAdvise (IViewObject2)
1689 * This sets-up an advisory sink with the data cache. When the object's
1690 * view changes, this sink is called.
1692 * See Windows documentation for more details on IViewObject2 methods.
1694 static HRESULT WINAPI
DataCache_SetAdvise(
1695 IViewObject2
* iface
,
1698 IAdviseSink
* pAdvSink
)
1700 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1702 TRACE("(%p, %lx, %lx, %p)\n", iface
, aspects
, advf
, pAdvSink
);
1705 * A call to this function removes the previous sink
1707 if (this->sinkInterface
!= NULL
)
1709 IAdviseSink_Release(this->sinkInterface
);
1710 this->sinkInterface
= NULL
;
1711 this->sinkAspects
= 0;
1712 this->sinkAdviseFlag
= 0;
1716 * Now, setup the new one.
1720 this->sinkInterface
= pAdvSink
;
1721 this->sinkAspects
= aspects
;
1722 this->sinkAdviseFlag
= advf
;
1724 IAdviseSink_AddRef(this->sinkInterface
);
1728 * When the ADVF_PRIMEFIRST flag is set, we have to advise the
1731 if (advf
& ADVF_PRIMEFIRST
)
1733 DataCache_FireOnViewChange(this,
1741 /************************************************************************
1742 * DataCache_GetAdvise (IViewObject2)
1744 * This method queries the current state of the advise sink
1745 * installed on the data cache.
1747 * See Windows documentation for more details on IViewObject2 methods.
1749 static HRESULT WINAPI
DataCache_GetAdvise(
1750 IViewObject2
* iface
,
1753 IAdviseSink
** ppAdvSink
)
1755 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1757 TRACE("(%p, %p, %p, %p)\n", iface
, pAspects
, pAdvf
, ppAdvSink
);
1760 * Just copy all the requested values.
1763 *pAspects
= this->sinkAspects
;
1766 *pAdvf
= this->sinkAdviseFlag
;
1768 if (ppAdvSink
!=NULL
)
1770 IAdviseSink_QueryInterface(this->sinkInterface
,
1778 /************************************************************************
1779 * DataCache_GetExtent (IViewObject2)
1781 * This method retrieves the "natural" size of this cached object.
1783 * See Windows documentation for more details on IViewObject2 methods.
1785 static HRESULT WINAPI
DataCache_GetExtent(
1786 IViewObject2
* iface
,
1789 DVTARGETDEVICE
* ptd
,
1792 PresentationDataHeader presData
;
1793 HRESULT hres
= E_FAIL
;
1795 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1797 TRACE("(%p, %lx, %ld, %p, %p)\n",
1798 iface
, dwDrawAspect
, lindex
, ptd
, lpsizel
);
1807 * Initialize the out parameter.
1813 * This flag should be set to -1.
1816 FIXME("Unimplemented flag lindex = %ld\n", lindex
);
1819 * Right now, we suport only the callback from
1820 * the default handler.
1823 FIXME("Unimplemented ptd = %p\n", ptd
);
1826 * Get the presentation information from the
1829 hres
= DataCache_ReadPresentationData(this,
1833 if (SUCCEEDED(hres
))
1835 lpsizel
->cx
= presData
.dwObjectExtentX
;
1836 lpsizel
->cy
= presData
.dwObjectExtentY
;
1840 * This method returns OLE_E_BLANK when it fails.
1849 /*********************************************************
1850 * Method implementation for the IOleCache2
1851 * part of the DataCache class.
1854 /************************************************************************
1855 * DataCache_IOleCache2_QueryInterface (IUnknown)
1857 * See Windows documentation for more details on IUnknown methods.
1859 static HRESULT WINAPI
DataCache_IOleCache2_QueryInterface(
1864 _ICOM_THIS_From_IOleCache2(DataCache
, iface
);
1866 return IUnknown_QueryInterface(this->outerUnknown
, riid
, ppvObject
);
1869 /************************************************************************
1870 * DataCache_IOleCache2_AddRef (IUnknown)
1872 * See Windows documentation for more details on IUnknown methods.
1874 static ULONG WINAPI
DataCache_IOleCache2_AddRef(
1877 _ICOM_THIS_From_IOleCache2(DataCache
, iface
);
1879 return IUnknown_AddRef(this->outerUnknown
);
1882 /************************************************************************
1883 * DataCache_IOleCache2_Release (IUnknown)
1885 * See Windows documentation for more details on IUnknown methods.
1887 static ULONG WINAPI
DataCache_IOleCache2_Release(
1890 _ICOM_THIS_From_IOleCache2(DataCache
, iface
);
1892 return IUnknown_Release(this->outerUnknown
);
1895 static HRESULT WINAPI
DataCache_Cache(
1897 FORMATETC
* pformatetc
,
1899 DWORD
* pdwConnection
)
1905 static HRESULT WINAPI
DataCache_Uncache(
1913 static HRESULT WINAPI
DataCache_EnumCache(
1915 IEnumSTATDATA
** ppenumSTATDATA
)
1921 static HRESULT WINAPI
DataCache_InitCache(
1923 IDataObject
* pDataObject
)
1929 static HRESULT WINAPI
DataCache_IOleCache2_SetData(
1931 FORMATETC
* pformatetc
,
1939 static HRESULT WINAPI
DataCache_UpdateCache(
1941 LPDATAOBJECT pDataObject
,
1949 static HRESULT WINAPI
DataCache_DiscardCache(
1951 DWORD dwDiscardOptions
)
1958 /*********************************************************
1959 * Method implementation for the IOleCacheControl
1960 * part of the DataCache class.
1963 /************************************************************************
1964 * DataCache_IOleCacheControl_QueryInterface (IUnknown)
1966 * See Windows documentation for more details on IUnknown methods.
1968 static HRESULT WINAPI
DataCache_IOleCacheControl_QueryInterface(
1969 IOleCacheControl
* iface
,
1973 _ICOM_THIS_From_IOleCacheControl(DataCache
, iface
);
1975 return IUnknown_QueryInterface(this->outerUnknown
, riid
, ppvObject
);
1978 /************************************************************************
1979 * DataCache_IOleCacheControl_AddRef (IUnknown)
1981 * See Windows documentation for more details on IUnknown methods.
1983 static ULONG WINAPI
DataCache_IOleCacheControl_AddRef(
1984 IOleCacheControl
* iface
)
1986 _ICOM_THIS_From_IOleCacheControl(DataCache
, iface
);
1988 return IUnknown_AddRef(this->outerUnknown
);
1991 /************************************************************************
1992 * DataCache_IOleCacheControl_Release (IUnknown)
1994 * See Windows documentation for more details on IUnknown methods.
1996 static ULONG WINAPI
DataCache_IOleCacheControl_Release(
1997 IOleCacheControl
* iface
)
1999 _ICOM_THIS_From_IOleCacheControl(DataCache
, iface
);
2001 return IUnknown_Release(this->outerUnknown
);
2004 static HRESULT WINAPI
DataCache_OnRun(
2005 IOleCacheControl
* iface
,
2006 LPDATAOBJECT pDataObject
)
2012 static HRESULT WINAPI
DataCache_OnStop(
2013 IOleCacheControl
* iface
)