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_base.h"
39 #include "wine/obj_misc.h"
40 #include "wine/obj_storage.h"
41 #include "wine/obj_moniker.h"
42 #include "wine/obj_dataobject.h"
43 #include "wine/obj_oleview.h"
44 #include "wine/obj_cache.h"
45 #include "wine/unicode.h"
47 #include "debugtools.h"
49 DEFAULT_DEBUG_CHANNEL(ole
);
51 /****************************************************************************
52 * PresentationDataHeader
54 * This structure represents the header of the \002OlePresXXX stream in
55 * the OLE object strorage.
57 * Most fields are still unknown.
59 typedef struct PresentationDataHeader
61 DWORD unknown1
; /* -1 */
62 DWORD unknown2
; /* 3, possibly CF_METAFILEPICT */
63 DWORD unknown3
; /* 4, possibly TYMED_ISTREAM */
65 DWORD unknown5
; /* -1 */
68 DWORD unknown7
; /* 0 */
69 DWORD dwObjectExtentX
;
70 DWORD dwObjectExtentY
;
72 } PresentationDataHeader
;
74 /****************************************************************************
80 * List all interface VTables here
82 ICOM_VTABLE(IDataObject
)* lpvtbl1
;
83 ICOM_VTABLE(IUnknown
)* lpvtbl2
;
84 ICOM_VTABLE(IPersistStorage
)* lpvtbl3
;
85 ICOM_VTABLE(IViewObject2
)* lpvtbl4
;
86 ICOM_VTABLE(IOleCache2
)* lpvtbl5
;
87 ICOM_VTABLE(IOleCacheControl
)* lpvtbl6
;
90 * Reference count of this object
95 * IUnknown implementation of the outer object.
97 IUnknown
* outerUnknown
;
100 * This storage pointer is set through a call to
101 * IPersistStorage_Load. This is where the visual
102 * representation of the object is stored.
104 IStorage
* presentationStorage
;
107 * The user of this object can setup ONE advise sink
108 * connection with the object. These parameters describe
112 DWORD sinkAdviseFlag
;
113 IAdviseSink
* sinkInterface
;
117 typedef struct DataCache DataCache
;
120 * Here, I define utility macros to help with the casting of the
122 * There is a version to accomodate all of the VTables implemented
125 #define _ICOM_THIS_From_IDataObject(class,name) class* this = (class*)name;
126 #define _ICOM_THIS_From_NDIUnknown(class, name) class* this = (class*)(((char*)name)-sizeof(void*));
127 #define _ICOM_THIS_From_IPersistStorage(class, name) class* this = (class*)(((char*)name)-2*sizeof(void*));
128 #define _ICOM_THIS_From_IViewObject2(class, name) class* this = (class*)(((char*)name)-3*sizeof(void*));
129 #define _ICOM_THIS_From_IOleCache2(class, name) class* this = (class*)(((char*)name)-4*sizeof(void*));
130 #define _ICOM_THIS_From_IOleCacheControl(class, name) class* this = (class*)(((char*)name)-5*sizeof(void*));
133 * Prototypes for the methods of the DataCache class.
135 static DataCache
* DataCache_Construct(REFCLSID clsid
,
136 LPUNKNOWN pUnkOuter
);
137 static void DataCache_Destroy(DataCache
* ptrToDestroy
);
138 static HRESULT
DataCache_ReadPresentationData(DataCache
* this,
140 PresentationDataHeader
* header
);
141 static HRESULT
DataCache_OpenPresStream(DataCache
*this,
144 static HMETAFILE
DataCache_ReadPresMetafile(DataCache
* this,
146 static void DataCache_FireOnViewChange(DataCache
* this,
151 * Prototypes for the methods of the DataCache class
152 * that implement non delegating IUnknown methods.
154 static HRESULT WINAPI
DataCache_NDIUnknown_QueryInterface(
158 static ULONG WINAPI
DataCache_NDIUnknown_AddRef(
160 static ULONG WINAPI
DataCache_NDIUnknown_Release(
164 * Prototypes for the methods of the DataCache class
165 * that implement IDataObject methods.
167 static HRESULT WINAPI
DataCache_IDataObject_QueryInterface(
171 static ULONG WINAPI
DataCache_IDataObject_AddRef(
173 static ULONG WINAPI
DataCache_IDataObject_Release(
175 static HRESULT WINAPI
DataCache_GetData(
177 LPFORMATETC pformatetcIn
,
179 static HRESULT WINAPI
DataCache_GetDataHere(
181 LPFORMATETC pformatetc
,
183 static HRESULT WINAPI
DataCache_QueryGetData(
185 LPFORMATETC pformatetc
);
186 static HRESULT WINAPI
DataCache_GetCanonicalFormatEtc(
188 LPFORMATETC pformatectIn
,
189 LPFORMATETC pformatetcOut
);
190 static HRESULT WINAPI
DataCache_IDataObject_SetData(
192 LPFORMATETC pformatetc
,
195 static HRESULT WINAPI
DataCache_EnumFormatEtc(
198 IEnumFORMATETC
** ppenumFormatEtc
);
199 static HRESULT WINAPI
DataCache_DAdvise(
201 FORMATETC
* pformatetc
,
203 IAdviseSink
* pAdvSink
,
204 DWORD
* pdwConnection
);
205 static HRESULT WINAPI
DataCache_DUnadvise(
208 static HRESULT WINAPI
DataCache_EnumDAdvise(
210 IEnumSTATDATA
** ppenumAdvise
);
213 * Prototypes for the methods of the DataCache class
214 * that implement IPersistStorage methods.
216 static HRESULT WINAPI
DataCache_IPersistStorage_QueryInterface(
217 IPersistStorage
* iface
,
220 static ULONG WINAPI
DataCache_IPersistStorage_AddRef(
221 IPersistStorage
* iface
);
222 static ULONG WINAPI
DataCache_IPersistStorage_Release(
223 IPersistStorage
* iface
);
224 static HRESULT WINAPI
DataCache_GetClassID(
225 IPersistStorage
* iface
,
227 static HRESULT WINAPI
DataCache_IsDirty(
228 IPersistStorage
* iface
);
229 static HRESULT WINAPI
DataCache_InitNew(
230 IPersistStorage
* iface
,
232 static HRESULT WINAPI
DataCache_Load(
233 IPersistStorage
* iface
,
235 static HRESULT WINAPI
DataCache_Save(
236 IPersistStorage
* iface
,
239 static HRESULT WINAPI
DataCache_SaveCompleted(
240 IPersistStorage
* iface
,
242 static HRESULT WINAPI
DataCache_HandsOffStorage(
243 IPersistStorage
* iface
);
246 * Prototypes for the methods of the DataCache class
247 * that implement IViewObject2 methods.
249 static HRESULT WINAPI
DataCache_IViewObject2_QueryInterface(
253 static ULONG WINAPI
DataCache_IViewObject2_AddRef(
254 IViewObject2
* iface
);
255 static ULONG WINAPI
DataCache_IViewObject2_Release(
256 IViewObject2
* iface
);
257 static HRESULT WINAPI
DataCache_Draw(
266 LPCRECTL lprcWBounds
,
267 IVO_ContCallback pfnContinue
,
269 static HRESULT WINAPI
DataCache_GetColorSet(
276 LOGPALETTE
** ppColorSet
);
277 static HRESULT WINAPI
DataCache_Freeze(
283 static HRESULT WINAPI
DataCache_Unfreeze(
286 static HRESULT WINAPI
DataCache_SetAdvise(
290 IAdviseSink
* pAdvSink
);
291 static HRESULT WINAPI
DataCache_GetAdvise(
295 IAdviseSink
** ppAdvSink
);
296 static HRESULT WINAPI
DataCache_GetExtent(
304 * Prototypes for the methods of the DataCache class
305 * that implement IOleCache2 methods.
307 static HRESULT WINAPI
DataCache_IOleCache2_QueryInterface(
311 static ULONG WINAPI
DataCache_IOleCache2_AddRef(
313 static ULONG WINAPI
DataCache_IOleCache2_Release(
315 static HRESULT WINAPI
DataCache_Cache(
317 FORMATETC
* pformatetc
,
319 DWORD
* pdwConnection
);
320 static HRESULT WINAPI
DataCache_Uncache(
323 static HRESULT WINAPI
DataCache_EnumCache(
325 IEnumSTATDATA
** ppenumSTATDATA
);
326 static HRESULT WINAPI
DataCache_InitCache(
328 IDataObject
* pDataObject
);
329 static HRESULT WINAPI
DataCache_IOleCache2_SetData(
331 FORMATETC
* pformatetc
,
334 static HRESULT WINAPI
DataCache_UpdateCache(
336 LPDATAOBJECT pDataObject
,
339 static HRESULT WINAPI
DataCache_DiscardCache(
341 DWORD dwDiscardOptions
);
344 * Prototypes for the methods of the DataCache class
345 * that implement IOleCacheControl methods.
347 static HRESULT WINAPI
DataCache_IOleCacheControl_QueryInterface(
348 IOleCacheControl
* iface
,
351 static ULONG WINAPI
DataCache_IOleCacheControl_AddRef(
352 IOleCacheControl
* iface
);
353 static ULONG WINAPI
DataCache_IOleCacheControl_Release(
354 IOleCacheControl
* iface
);
355 static HRESULT WINAPI
DataCache_OnRun(
356 IOleCacheControl
* iface
,
357 LPDATAOBJECT pDataObject
);
358 static HRESULT WINAPI
DataCache_OnStop(
359 IOleCacheControl
* iface
);
362 * Virtual function tables for the DataCache class.
364 static ICOM_VTABLE(IUnknown
) DataCache_NDIUnknown_VTable
=
366 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
367 DataCache_NDIUnknown_QueryInterface
,
368 DataCache_NDIUnknown_AddRef
,
369 DataCache_NDIUnknown_Release
372 static ICOM_VTABLE(IDataObject
) DataCache_IDataObject_VTable
=
374 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
375 DataCache_IDataObject_QueryInterface
,
376 DataCache_IDataObject_AddRef
,
377 DataCache_IDataObject_Release
,
379 DataCache_GetDataHere
,
380 DataCache_QueryGetData
,
381 DataCache_GetCanonicalFormatEtc
,
382 DataCache_IDataObject_SetData
,
383 DataCache_EnumFormatEtc
,
386 DataCache_EnumDAdvise
389 static ICOM_VTABLE(IPersistStorage
) DataCache_IPersistStorage_VTable
=
391 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
392 DataCache_IPersistStorage_QueryInterface
,
393 DataCache_IPersistStorage_AddRef
,
394 DataCache_IPersistStorage_Release
,
395 DataCache_GetClassID
,
400 DataCache_SaveCompleted
,
401 DataCache_HandsOffStorage
404 static ICOM_VTABLE(IViewObject2
) DataCache_IViewObject2_VTable
=
406 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
407 DataCache_IViewObject2_QueryInterface
,
408 DataCache_IViewObject2_AddRef
,
409 DataCache_IViewObject2_Release
,
411 DataCache_GetColorSet
,
419 static ICOM_VTABLE(IOleCache2
) DataCache_IOleCache2_VTable
=
421 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
422 DataCache_IOleCache2_QueryInterface
,
423 DataCache_IOleCache2_AddRef
,
424 DataCache_IOleCache2_Release
,
429 DataCache_IOleCache2_SetData
,
430 DataCache_UpdateCache
,
431 DataCache_DiscardCache
434 static ICOM_VTABLE(IOleCacheControl
) DataCache_IOleCacheControl_VTable
=
436 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
437 DataCache_IOleCacheControl_QueryInterface
,
438 DataCache_IOleCacheControl_AddRef
,
439 DataCache_IOleCacheControl_Release
,
444 /******************************************************************************
445 * CreateDataCache [OLE32.54]
447 HRESULT WINAPI
CreateDataCache(
453 DataCache
* newCache
= NULL
;
456 TRACE("(%s, %p, %s, %p)\n", debugstr_guid(rclsid
), pUnkOuter
, debugstr_guid(riid
), ppvObj
);
467 * If this cache is constructed for aggregation, make sure
468 * the caller is requesting the IUnknown interface.
469 * This is necessary because it's the only time the non-delegating
470 * IUnknown pointer can be returned to the outside.
472 if ( (pUnkOuter
!=NULL
) &&
473 (memcmp(&IID_IUnknown
, riid
, sizeof(IID_IUnknown
)) != 0) )
474 return CLASS_E_NOAGGREGATION
;
477 * Try to construct a new instance of the class.
479 newCache
= DataCache_Construct(rclsid
,
483 return E_OUTOFMEMORY
;
486 * Make sure it supports the interface required by the caller.
488 hr
= IUnknown_QueryInterface((IUnknown
*)&(newCache
->lpvtbl2
), riid
, ppvObj
);
491 * Release the reference obtained in the constructor. If
492 * the QueryInterface was unsuccessful, it will free the class.
494 IUnknown_Release((IUnknown
*)&(newCache
->lpvtbl2
));
499 /*********************************************************
500 * Method implementation for DataCache class.
502 static DataCache
* DataCache_Construct(
506 DataCache
* newObject
= 0;
509 * Allocate space for the object.
511 newObject
= HeapAlloc(GetProcessHeap(), 0, sizeof(DataCache
));
517 * Initialize the virtual function table.
519 newObject
->lpvtbl1
= &DataCache_IDataObject_VTable
;
520 newObject
->lpvtbl2
= &DataCache_NDIUnknown_VTable
;
521 newObject
->lpvtbl3
= &DataCache_IPersistStorage_VTable
;
522 newObject
->lpvtbl4
= &DataCache_IViewObject2_VTable
;
523 newObject
->lpvtbl5
= &DataCache_IOleCache2_VTable
;
524 newObject
->lpvtbl6
= &DataCache_IOleCacheControl_VTable
;
527 * Start with one reference count. The caller of this function
528 * must release the interface pointer when it is done.
533 * Initialize the outer unknown
534 * We don't keep a reference on the outer unknown since, the way
535 * aggregation works, our lifetime is at least as large as it's
539 pUnkOuter
= (IUnknown
*)&(newObject
->lpvtbl2
);
541 newObject
->outerUnknown
= pUnkOuter
;
544 * Initialize the other members of the structure.
546 newObject
->presentationStorage
= NULL
;
547 newObject
->sinkAspects
= 0;
548 newObject
->sinkAdviseFlag
= 0;
549 newObject
->sinkInterface
= 0;
554 static void DataCache_Destroy(
555 DataCache
* ptrToDestroy
)
559 if (ptrToDestroy
->sinkInterface
!= NULL
)
561 IAdviseSink_Release(ptrToDestroy
->sinkInterface
);
562 ptrToDestroy
->sinkInterface
= NULL
;
565 if (ptrToDestroy
->presentationStorage
!= NULL
)
567 IStorage_Release(ptrToDestroy
->presentationStorage
);
568 ptrToDestroy
->presentationStorage
= NULL
;
572 * Free the datacache pointer.
574 HeapFree(GetProcessHeap(), 0, ptrToDestroy
);
577 /************************************************************************
578 * DataCache_ReadPresentationData
580 * This method will read information for the requested presentation
581 * into the given structure.
584 * this - Pointer to the DataCache object
585 * drawAspect - The aspect of the object that we wish to draw.
586 * header - The structure containing information about this
587 * aspect of the object.
589 static HRESULT
DataCache_ReadPresentationData(
592 PresentationDataHeader
* header
)
594 IStream
* presStream
= NULL
;
598 * Open the presentation stream.
600 hres
= DataCache_OpenPresStream(
615 sizeof(PresentationDataHeader
),
621 IStream_Release(presStream
);
624 * We don't want to propagate any other error
625 * code than a failure.
633 /************************************************************************
634 * DataCache_FireOnViewChange
636 * This method will fire an OnViewChange notification to the advise
637 * sink registered with the datacache.
639 * See IAdviseSink::OnViewChange for more details.
641 static void DataCache_FireOnViewChange(
646 TRACE("(%p, %lx, %ld)\n", this, aspect
, lindex
);
649 * The sink supplies a filter when it registers
650 * we make sure we only send the notifications when that
653 if ((this->sinkAspects
& aspect
) != 0)
655 if (this->sinkInterface
!= NULL
)
657 IAdviseSink_OnViewChange(this->sinkInterface
,
662 * Some sinks want to be unregistered automatically when
663 * the first notification goes out.
665 if ( (this->sinkAdviseFlag
& ADVF_ONLYONCE
) != 0)
667 IAdviseSink_Release(this->sinkInterface
);
669 this->sinkInterface
= NULL
;
670 this->sinkAspects
= 0;
671 this->sinkAdviseFlag
= 0;
677 /* Helper for DataCache_OpenPresStream */
678 static BOOL
DataCache_IsPresentationStream(const STATSTG
*elem
)
680 /* The presentation streams have names of the form "\002OlePresXXX",
681 * where XXX goes from 000 to 999. */
682 static const WCHAR OlePres
[] = { 2,'O','l','e','P','r','e','s' };
684 LPCWSTR name
= elem
->pwcsName
;
686 return (elem
->type
== STGTY_STREAM
)
687 && (elem
->cbSize
.s
.LowPart
>= sizeof(PresentationDataHeader
))
688 && (strlenW(name
) == 11)
689 && (strncmpW(name
, OlePres
, 8) == 0)
690 && (name
[8] >= '0') && (name
[8] <= '9')
691 && (name
[9] >= '0') && (name
[9] <= '9')
692 && (name
[10] >= '0') && (name
[10] <= '9');
695 /************************************************************************
696 * DataCache_OpenPresStream
698 * This method will find the stream for the given presentation. It makes
699 * no attempt at fallback.
702 * this - Pointer to the DataCache object
703 * drawAspect - The aspect of the object that we wish to draw.
704 * pStm - A returned stream. It points to the beginning of the
705 * - presentation data, including the header.
708 * S_OK The requested stream has been opened.
709 * OLE_E_BLANK The requested stream could not be found.
710 * Quite a few others I'm too lazy to map correctly.
713 * Algorithm: Scan the elements of the presentation storage, looking
714 * for presentation streams. For each presentation stream,
715 * load the header and check to see if the aspect maches.
717 * If a fallback is desired, just opening the first presentation stream
720 static HRESULT
DataCache_OpenPresStream(
729 if (!ppStm
) return E_POINTER
;
731 hr
= IStorage_EnumElements(this->presentationStorage
, 0, NULL
, 0, &pEnum
);
732 if (FAILED(hr
)) return hr
;
734 while ((hr
= IEnumSTATSTG_Next(pEnum
, 1, &elem
, NULL
)) == S_OK
)
736 if (DataCache_IsPresentationStream(&elem
))
740 hr
= IStorage_OpenStream(this->presentationStorage
, elem
.pwcsName
,
741 NULL
, STGM_READ
| STGM_SHARE_EXCLUSIVE
, 0,
745 PresentationDataHeader header
;
748 hr
= IStream_Read(pStm
, &header
, sizeof(header
), &actual_read
);
750 /* can't use SUCCEEDED(hr): S_FALSE counts as an error */
751 if (hr
== S_OK
&& actual_read
== sizeof(header
)
752 && header
.dvAspect
== drawAspect
)
754 /* Rewind the stream before returning it. */
755 LARGE_INTEGER offset
;
756 offset
.s
.LowPart
= 0;
757 offset
.s
.HighPart
= 0;
758 IStream_Seek(pStm
, offset
, STREAM_SEEK_SET
, NULL
);
762 CoTaskMemFree(elem
.pwcsName
);
763 IEnumSTATSTG_Release(pEnum
);
768 IStream_Release(pStm
);
772 CoTaskMemFree(elem
.pwcsName
);
775 IEnumSTATSTG_Release(pEnum
);
777 return (hr
== S_FALSE
? OLE_E_BLANK
: hr
);
780 /************************************************************************
781 * DataCache_ReadPresentationData
783 * This method will read information for the requested presentation
784 * into the given structure.
787 * this - Pointer to the DataCache object
788 * drawAspect - The aspect of the object that we wish to draw.
791 * This method returns a metafile handle if it is successful.
792 * it will return 0 if not.
794 static HMETAFILE
DataCache_ReadPresMetafile(
798 LARGE_INTEGER offset
;
799 IStream
* presStream
= NULL
;
803 HMETAFILE newMetafile
= 0;
806 * Open the presentation stream.
808 hres
= DataCache_OpenPresStream(
817 * Get the size of the stream.
819 hres
= IStream_Stat(presStream
,
826 offset
.s
.HighPart
= 0;
827 offset
.s
.LowPart
= sizeof(PresentationDataHeader
);
835 streamInfo
.cbSize
.s
.LowPart
-= offset
.s
.LowPart
;
838 * Allocate a buffer for the metafile bits.
840 metafileBits
= HeapAlloc(GetProcessHeap(),
842 streamInfo
.cbSize
.s
.LowPart
);
845 * Read the metafile bits.
850 streamInfo
.cbSize
.s
.LowPart
,
854 * Create a metafile with those bits.
858 newMetafile
= SetMetaFileBitsEx(streamInfo
.cbSize
.s
.LowPart
, metafileBits
);
864 HeapFree(GetProcessHeap(), 0, metafileBits
);
865 IStream_Release(presStream
);
873 /*********************************************************
874 * Method implementation for the non delegating IUnknown
875 * part of the DataCache class.
878 /************************************************************************
879 * DataCache_NDIUnknown_QueryInterface (IUnknown)
881 * See Windows documentation for more details on IUnknown methods.
883 * This version of QueryInterface will not delegate it's implementation
884 * to the outer unknown.
886 static HRESULT WINAPI
DataCache_NDIUnknown_QueryInterface(
891 _ICOM_THIS_From_NDIUnknown(DataCache
, iface
);
894 * Perform a sanity check on the parameters.
896 if ( (this==0) || (ppvObject
==0) )
900 * Initialize the return parameter.
905 * Compare the riid with the interface IDs implemented by this object.
907 if (memcmp(&IID_IUnknown
, riid
, sizeof(IID_IUnknown
)) == 0)
911 else if (memcmp(&IID_IDataObject
, riid
, sizeof(IID_IDataObject
)) == 0)
913 *ppvObject
= (IDataObject
*)&(this->lpvtbl1
);
915 else if ( (memcmp(&IID_IPersistStorage
, riid
, sizeof(IID_IPersistStorage
)) == 0) ||
916 (memcmp(&IID_IPersist
, riid
, sizeof(IID_IPersist
)) == 0) )
918 *ppvObject
= (IPersistStorage
*)&(this->lpvtbl3
);
920 else if ( (memcmp(&IID_IViewObject
, riid
, sizeof(IID_IViewObject
)) == 0) ||
921 (memcmp(&IID_IViewObject2
, riid
, sizeof(IID_IViewObject2
)) == 0) )
923 *ppvObject
= (IViewObject2
*)&(this->lpvtbl4
);
925 else if ( (memcmp(&IID_IOleCache
, riid
, sizeof(IID_IOleCache
)) == 0) ||
926 (memcmp(&IID_IOleCache2
, riid
, sizeof(IID_IOleCache2
)) == 0) )
928 *ppvObject
= (IOleCache2
*)&(this->lpvtbl5
);
930 else if (memcmp(&IID_IOleCacheControl
, riid
, sizeof(IID_IOleCacheControl
)) == 0)
932 *ppvObject
= (IOleCacheControl
*)&(this->lpvtbl6
);
936 * Check that we obtained an interface.
940 WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid
));
941 return E_NOINTERFACE
;
945 * Query Interface always increases the reference count by one when it is
948 IUnknown_AddRef((IUnknown
*)*ppvObject
);
953 /************************************************************************
954 * DataCache_NDIUnknown_AddRef (IUnknown)
956 * See Windows documentation for more details on IUnknown methods.
958 * This version of QueryInterface will not delegate it's implementation
959 * to the outer unknown.
961 static ULONG WINAPI
DataCache_NDIUnknown_AddRef(
964 _ICOM_THIS_From_NDIUnknown(DataCache
, iface
);
971 /************************************************************************
972 * DataCache_NDIUnknown_Release (IUnknown)
974 * See Windows documentation for more details on IUnknown methods.
976 * This version of QueryInterface will not delegate it's implementation
977 * to the outer unknown.
979 static ULONG WINAPI
DataCache_NDIUnknown_Release(
982 _ICOM_THIS_From_NDIUnknown(DataCache
, iface
);
985 * Decrease the reference count on this object.
990 * If the reference count goes down to 0, perform suicide.
994 DataCache_Destroy(this);
1002 /*********************************************************
1003 * Method implementation for the IDataObject
1004 * part of the DataCache class.
1007 /************************************************************************
1008 * DataCache_IDataObject_QueryInterface (IUnknown)
1010 * See Windows documentation for more details on IUnknown methods.
1012 static HRESULT WINAPI
DataCache_IDataObject_QueryInterface(
1017 _ICOM_THIS_From_IDataObject(DataCache
, iface
);
1019 return IUnknown_QueryInterface(this->outerUnknown
, riid
, ppvObject
);
1022 /************************************************************************
1023 * DataCache_IDataObject_AddRef (IUnknown)
1025 * See Windows documentation for more details on IUnknown methods.
1027 static ULONG WINAPI
DataCache_IDataObject_AddRef(
1030 _ICOM_THIS_From_IDataObject(DataCache
, iface
);
1032 return IUnknown_AddRef(this->outerUnknown
);
1035 /************************************************************************
1036 * DataCache_IDataObject_Release (IUnknown)
1038 * See Windows documentation for more details on IUnknown methods.
1040 static ULONG WINAPI
DataCache_IDataObject_Release(
1043 _ICOM_THIS_From_IDataObject(DataCache
, iface
);
1045 return IUnknown_Release(this->outerUnknown
);
1048 /************************************************************************
1051 * Get Data from a source dataobject using format pformatetcIn->cfFormat
1052 * See Windows documentation for more details on GetData.
1053 * TODO: Currently only CF_METAFILEPICT is implemented
1055 static HRESULT WINAPI
DataCache_GetData(
1057 LPFORMATETC pformatetcIn
,
1061 HRESULT hrRet
= E_UNEXPECTED
;
1062 IPersistStorage
*pPersistStorage
= 0;
1063 IStorage
*pStorage
= 0;
1064 IStream
*pStream
= 0;
1065 OLECHAR name
[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
1066 HGLOBAL hGlobalMF
= 0;
1068 PresentationDataHeader pdh
;
1069 METAFILEPICT
*mfPict
;
1070 HMETAFILE hMetaFile
= 0;
1072 if (pformatetcIn
->cfFormat
== CF_METAFILEPICT
)
1074 /* Get the Persist Storage */
1076 hr
= IDataObject_QueryInterface(iface
, &IID_IPersistStorage
, (void**)&pPersistStorage
);
1081 /* Create a doc file to copy the doc to a storage */
1083 hr
= StgCreateDocfile(NULL
, STGM_CREATE
| STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, &pStorage
);
1088 /* Save it to storage */
1090 hr
= OleSave(pPersistStorage
, pStorage
, FALSE
);
1095 /* Open the Presentation data srteam */
1097 hr
= IStorage_OpenStream(pStorage
, name
, 0, STGM_CREATE
|STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, 0, &pStream
);
1102 /* Read the presentation header */
1104 hr
= IStream_Read(pStream
, &pdh
, sizeof(PresentationDataHeader
), NULL
);
1109 mfBits
= HeapAlloc(GetProcessHeap(), 0, pdh
.dwSize
);
1111 /* Read the Metafile bits */
1113 hr
= IStream_Read(pStream
, mfBits
, pdh
.dwSize
, NULL
);
1118 /* Create the metafile and place it in the STGMEDIUM structure */
1120 hMetaFile
= SetMetaFileBitsEx(pdh
.dwSize
, mfBits
);
1122 hGlobalMF
= GlobalAlloc(GMEM_SHARE
|GMEM_MOVEABLE
, sizeof(METAFILEPICT
));
1123 mfPict
= (METAFILEPICT
*)GlobalLock(hGlobalMF
);
1124 mfPict
->hMF
= hMetaFile
;
1126 GlobalUnlock(hGlobalMF
);
1128 pmedium
->u
.hGlobal
= hGlobalMF
;
1129 pmedium
->tymed
= TYMED_MFPICT
;
1135 HeapFree(GetProcessHeap(), 0, mfBits
);
1138 IStream_Release(pStream
);
1141 IStorage_Release(pStorage
);
1143 if (pPersistStorage
)
1144 IPersistStorage_Release(pPersistStorage
);
1149 /* TODO: Other formats are not implemented */
1154 static HRESULT WINAPI
DataCache_GetDataHere(
1156 LPFORMATETC pformatetc
,
1163 static HRESULT WINAPI
DataCache_QueryGetData(
1165 LPFORMATETC pformatetc
)
1171 /************************************************************************
1172 * DataCache_EnumFormatEtc (IDataObject)
1174 * The data cache doesn't implement this method.
1176 * See Windows documentation for more details on IDataObject methods.
1178 static HRESULT WINAPI
DataCache_GetCanonicalFormatEtc(
1180 LPFORMATETC pformatectIn
,
1181 LPFORMATETC pformatetcOut
)
1187 /************************************************************************
1188 * DataCache_IDataObject_SetData (IDataObject)
1190 * This method is delegated to the IOleCache2 implementation.
1192 * See Windows documentation for more details on IDataObject methods.
1194 static HRESULT WINAPI
DataCache_IDataObject_SetData(
1196 LPFORMATETC pformatetc
,
1200 IOleCache2
* oleCache
= NULL
;
1203 TRACE("(%p, %p, %p, %d)\n", iface
, pformatetc
, pmedium
, fRelease
);
1205 hres
= IDataObject_QueryInterface(iface
, &IID_IOleCache2
, (void**)&oleCache
);
1208 return E_UNEXPECTED
;
1210 hres
= IOleCache2_SetData(oleCache
, pformatetc
, pmedium
, fRelease
);
1212 IOleCache2_Release(oleCache
);
1217 /************************************************************************
1218 * DataCache_EnumFormatEtc (IDataObject)
1220 * The data cache doesn't implement this method.
1222 * See Windows documentation for more details on IDataObject methods.
1224 static HRESULT WINAPI
DataCache_EnumFormatEtc(
1227 IEnumFORMATETC
** ppenumFormatEtc
)
1233 /************************************************************************
1234 * DataCache_DAdvise (IDataObject)
1236 * The data cache doesn't support connections.
1238 * See Windows documentation for more details on IDataObject methods.
1240 static HRESULT WINAPI
DataCache_DAdvise(
1242 FORMATETC
* pformatetc
,
1244 IAdviseSink
* pAdvSink
,
1245 DWORD
* pdwConnection
)
1248 return OLE_E_ADVISENOTSUPPORTED
;
1251 /************************************************************************
1252 * DataCache_DUnadvise (IDataObject)
1254 * The data cache doesn't support connections.
1256 * See Windows documentation for more details on IDataObject methods.
1258 static HRESULT WINAPI
DataCache_DUnadvise(
1263 return OLE_E_NOCONNECTION
;
1266 /************************************************************************
1267 * DataCache_EnumDAdvise (IDataObject)
1269 * The data cache doesn't support connections.
1271 * See Windows documentation for more details on IDataObject methods.
1273 static HRESULT WINAPI
DataCache_EnumDAdvise(
1275 IEnumSTATDATA
** ppenumAdvise
)
1278 return OLE_E_ADVISENOTSUPPORTED
;
1281 /*********************************************************
1282 * Method implementation for the IDataObject
1283 * part of the DataCache class.
1286 /************************************************************************
1287 * DataCache_IPersistStorage_QueryInterface (IUnknown)
1289 * See Windows documentation for more details on IUnknown methods.
1291 static HRESULT WINAPI
DataCache_IPersistStorage_QueryInterface(
1292 IPersistStorage
* iface
,
1296 _ICOM_THIS_From_IPersistStorage(DataCache
, iface
);
1298 return IUnknown_QueryInterface(this->outerUnknown
, riid
, ppvObject
);
1301 /************************************************************************
1302 * DataCache_IPersistStorage_AddRef (IUnknown)
1304 * See Windows documentation for more details on IUnknown methods.
1306 static ULONG WINAPI
DataCache_IPersistStorage_AddRef(
1307 IPersistStorage
* iface
)
1309 _ICOM_THIS_From_IPersistStorage(DataCache
, iface
);
1311 return IUnknown_AddRef(this->outerUnknown
);
1314 /************************************************************************
1315 * DataCache_IPersistStorage_Release (IUnknown)
1317 * See Windows documentation for more details on IUnknown methods.
1319 static ULONG WINAPI
DataCache_IPersistStorage_Release(
1320 IPersistStorage
* iface
)
1322 _ICOM_THIS_From_IPersistStorage(DataCache
, iface
);
1324 return IUnknown_Release(this->outerUnknown
);
1327 /************************************************************************
1328 * DataCache_GetClassID (IPersistStorage)
1330 * The data cache doesn't implement this method.
1332 * See Windows documentation for more details on IPersistStorage methods.
1334 static HRESULT WINAPI
DataCache_GetClassID(
1335 IPersistStorage
* iface
,
1338 TRACE("(%p, %p)\n", iface
, pClassID
);
1342 /************************************************************************
1343 * DataCache_IsDirty (IPersistStorage)
1345 * Until we actully connect to a running object and retrieve new
1346 * information to it, we never get dirty.
1348 * See Windows documentation for more details on IPersistStorage methods.
1350 static HRESULT WINAPI
DataCache_IsDirty(
1351 IPersistStorage
* iface
)
1353 TRACE("(%p)\n", iface
);
1358 /************************************************************************
1359 * DataCache_InitNew (IPersistStorage)
1361 * The data cache implementation of IPersistStorage_InitNew simply stores
1362 * the storage pointer.
1364 * See Windows documentation for more details on IPersistStorage methods.
1366 static HRESULT WINAPI
DataCache_InitNew(
1367 IPersistStorage
* iface
,
1370 TRACE("(%p, %p)\n", iface
, pStg
);
1372 return DataCache_Load(iface
, pStg
);
1375 /************************************************************************
1376 * DataCache_Load (IPersistStorage)
1378 * The data cache implementation of IPersistStorage_Load doesn't
1379 * actually load anything. Instead, it holds on to the storage pointer
1380 * and it will load the presentation information when the
1381 * IDataObject_GetData or IViewObject2_Draw methods are called.
1383 * See Windows documentation for more details on IPersistStorage methods.
1385 static HRESULT WINAPI
DataCache_Load(
1386 IPersistStorage
* iface
,
1389 _ICOM_THIS_From_IPersistStorage(DataCache
, iface
);
1391 TRACE("(%p, %p)\n", iface
, pStg
);
1393 if (this->presentationStorage
!= NULL
)
1395 IStorage_Release(this->presentationStorage
);
1398 this->presentationStorage
= pStg
;
1400 if (this->presentationStorage
!= NULL
)
1402 IStorage_AddRef(this->presentationStorage
);
1407 /************************************************************************
1408 * DataCache_Save (IPersistStorage)
1410 * Until we actully connect to a running object and retrieve new
1411 * information to it, we never have to save anything. However, it is
1412 * our responsability to copy the information when saving to a new
1415 * See Windows documentation for more details on IPersistStorage methods.
1417 static HRESULT WINAPI
DataCache_Save(
1418 IPersistStorage
* iface
,
1422 _ICOM_THIS_From_IPersistStorage(DataCache
, iface
);
1424 TRACE("(%p, %p, %d)\n", iface
, pStg
, fSameAsLoad
);
1426 if ( (!fSameAsLoad
) &&
1427 (this->presentationStorage
!=NULL
) )
1429 return IStorage_CopyTo(this->presentationStorage
,
1439 /************************************************************************
1440 * DataCache_SaveCompleted (IPersistStorage)
1442 * This method is called to tell the cache to release the storage
1443 * pointer it's currentlu holding.
1445 * See Windows documentation for more details on IPersistStorage methods.
1447 static HRESULT WINAPI
DataCache_SaveCompleted(
1448 IPersistStorage
* iface
,
1451 TRACE("(%p, %p)\n", iface
, pStgNew
);
1456 * First, make sure we get our hands off any storage we have.
1459 DataCache_HandsOffStorage(iface
);
1462 * Then, attach to the new storage.
1465 DataCache_Load(iface
, pStgNew
);
1471 /************************************************************************
1472 * DataCache_HandsOffStorage (IPersistStorage)
1474 * This method is called to tell the cache to release the storage
1475 * pointer it's currentlu holding.
1477 * See Windows documentation for more details on IPersistStorage methods.
1479 static HRESULT WINAPI
DataCache_HandsOffStorage(
1480 IPersistStorage
* iface
)
1482 _ICOM_THIS_From_IPersistStorage(DataCache
, iface
);
1484 TRACE("(%p)\n", iface
);
1486 if (this->presentationStorage
!= NULL
)
1488 IStorage_Release(this->presentationStorage
);
1489 this->presentationStorage
= NULL
;
1495 /*********************************************************
1496 * Method implementation for the IViewObject2
1497 * part of the DataCache class.
1500 /************************************************************************
1501 * DataCache_IViewObject2_QueryInterface (IUnknown)
1503 * See Windows documentation for more details on IUnknown methods.
1505 static HRESULT WINAPI
DataCache_IViewObject2_QueryInterface(
1506 IViewObject2
* iface
,
1510 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1512 return IUnknown_QueryInterface(this->outerUnknown
, riid
, ppvObject
);
1515 /************************************************************************
1516 * DataCache_IViewObject2_AddRef (IUnknown)
1518 * See Windows documentation for more details on IUnknown methods.
1520 static ULONG WINAPI
DataCache_IViewObject2_AddRef(
1521 IViewObject2
* iface
)
1523 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1525 return IUnknown_AddRef(this->outerUnknown
);
1528 /************************************************************************
1529 * DataCache_IViewObject2_Release (IUnknown)
1531 * See Windows documentation for more details on IUnknown methods.
1533 static ULONG WINAPI
DataCache_IViewObject2_Release(
1534 IViewObject2
* iface
)
1536 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1538 return IUnknown_Release(this->outerUnknown
);
1541 /************************************************************************
1542 * DataCache_Draw (IViewObject2)
1544 * This method will draw the cached representation of the object
1545 * to the given device context.
1547 * See Windows documentation for more details on IViewObject2 methods.
1549 static HRESULT WINAPI
DataCache_Draw(
1550 IViewObject2
* iface
,
1554 DVTARGETDEVICE
* ptd
,
1557 LPCRECTL lprcBounds
,
1558 LPCRECTL lprcWBounds
,
1559 IVO_ContCallback pfnContinue
,
1562 PresentationDataHeader presData
;
1563 HMETAFILE presMetafile
= 0;
1566 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1568 TRACE("(%p, %lx, %ld, %p, %x, %x, %p, %p, %p, %lx)\n",
1583 if (lprcBounds
==NULL
)
1584 return E_INVALIDARG
;
1587 * First, we need to retrieve the dimensions of the
1588 * image in the metafile.
1590 hres
= DataCache_ReadPresentationData(this,
1598 * Then, we can extract the metafile itself from the cached
1601 * FIXME Unless it isn't a metafile. I think it could be any CF_XXX type,
1602 * particularly CF_DIB.
1604 presMetafile
= DataCache_ReadPresMetafile(this,
1608 * If we have a metafile, just draw baby...
1609 * We have to be careful not to modify the state of the
1612 if (presMetafile
!=0)
1614 INT prevMapMode
= SetMapMode(hdcDraw
, MM_ANISOTROPIC
);
1616 SIZE oldViewportExt
;
1617 POINT oldViewportOrg
;
1619 SetWindowExtEx(hdcDraw
,
1620 presData
.dwObjectExtentX
,
1621 presData
.dwObjectExtentY
,
1624 SetViewportExtEx(hdcDraw
,
1625 lprcBounds
->right
- lprcBounds
->left
,
1626 lprcBounds
->bottom
- lprcBounds
->top
,
1629 SetViewportOrgEx(hdcDraw
,
1634 PlayMetaFile(hdcDraw
, presMetafile
);
1636 SetWindowExtEx(hdcDraw
,
1641 SetViewportExtEx(hdcDraw
,
1646 SetViewportOrgEx(hdcDraw
,
1651 SetMapMode(hdcDraw
, prevMapMode
);
1653 DeleteMetaFile(presMetafile
);
1659 static HRESULT WINAPI
DataCache_GetColorSet(
1660 IViewObject2
* iface
,
1664 DVTARGETDEVICE
* ptd
,
1665 HDC hicTargetDevice
,
1666 LOGPALETTE
** ppColorSet
)
1672 static HRESULT WINAPI
DataCache_Freeze(
1673 IViewObject2
* iface
,
1683 static HRESULT WINAPI
DataCache_Unfreeze(
1684 IViewObject2
* iface
,
1691 /************************************************************************
1692 * DataCache_SetAdvise (IViewObject2)
1694 * This sets-up an advisory sink with the data cache. When the object's
1695 * view changes, this sink is called.
1697 * See Windows documentation for more details on IViewObject2 methods.
1699 static HRESULT WINAPI
DataCache_SetAdvise(
1700 IViewObject2
* iface
,
1703 IAdviseSink
* pAdvSink
)
1705 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1707 TRACE("(%p, %lx, %lx, %p)\n", iface
, aspects
, advf
, pAdvSink
);
1710 * A call to this function removes the previous sink
1712 if (this->sinkInterface
!= NULL
)
1714 IAdviseSink_Release(this->sinkInterface
);
1715 this->sinkInterface
= NULL
;
1716 this->sinkAspects
= 0;
1717 this->sinkAdviseFlag
= 0;
1721 * Now, setup the new one.
1725 this->sinkInterface
= pAdvSink
;
1726 this->sinkAspects
= aspects
;
1727 this->sinkAdviseFlag
= advf
;
1729 IAdviseSink_AddRef(this->sinkInterface
);
1733 * When the ADVF_PRIMEFIRST flag is set, we have to advise the
1736 if (advf
& ADVF_PRIMEFIRST
)
1738 DataCache_FireOnViewChange(this,
1746 /************************************************************************
1747 * DataCache_GetAdvise (IViewObject2)
1749 * This method queries the current state of the advise sink
1750 * installed on the data cache.
1752 * See Windows documentation for more details on IViewObject2 methods.
1754 static HRESULT WINAPI
DataCache_GetAdvise(
1755 IViewObject2
* iface
,
1758 IAdviseSink
** ppAdvSink
)
1760 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1762 TRACE("(%p, %p, %p, %p)\n", iface
, pAspects
, pAdvf
, ppAdvSink
);
1765 * Just copy all the requested values.
1768 *pAspects
= this->sinkAspects
;
1771 *pAdvf
= this->sinkAdviseFlag
;
1773 if (ppAdvSink
!=NULL
)
1775 IAdviseSink_QueryInterface(this->sinkInterface
,
1783 /************************************************************************
1784 * DataCache_GetExtent (IViewObject2)
1786 * This method retrieves the "natural" size of this cached object.
1788 * See Windows documentation for more details on IViewObject2 methods.
1790 static HRESULT WINAPI
DataCache_GetExtent(
1791 IViewObject2
* iface
,
1794 DVTARGETDEVICE
* ptd
,
1797 PresentationDataHeader presData
;
1798 HRESULT hres
= E_FAIL
;
1800 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1802 TRACE("(%p, %lx, %ld, %p, %p)\n",
1803 iface
, dwDrawAspect
, lindex
, ptd
, lpsizel
);
1812 * Initialize the out parameter.
1818 * This flag should be set to -1.
1821 FIXME("Unimplemented flag lindex = %ld\n", lindex
);
1824 * Right now, we suport only the callback from
1825 * the default handler.
1828 FIXME("Unimplemented ptd = %p\n", ptd
);
1831 * Get the presentation information from the
1834 hres
= DataCache_ReadPresentationData(this,
1838 if (SUCCEEDED(hres
))
1840 lpsizel
->cx
= presData
.dwObjectExtentX
;
1841 lpsizel
->cy
= presData
.dwObjectExtentY
;
1845 * This method returns OLE_E_BLANK when it fails.
1854 /*********************************************************
1855 * Method implementation for the IOleCache2
1856 * part of the DataCache class.
1859 /************************************************************************
1860 * DataCache_IOleCache2_QueryInterface (IUnknown)
1862 * See Windows documentation for more details on IUnknown methods.
1864 static HRESULT WINAPI
DataCache_IOleCache2_QueryInterface(
1869 _ICOM_THIS_From_IOleCache2(DataCache
, iface
);
1871 return IUnknown_QueryInterface(this->outerUnknown
, riid
, ppvObject
);
1874 /************************************************************************
1875 * DataCache_IOleCache2_AddRef (IUnknown)
1877 * See Windows documentation for more details on IUnknown methods.
1879 static ULONG WINAPI
DataCache_IOleCache2_AddRef(
1882 _ICOM_THIS_From_IOleCache2(DataCache
, iface
);
1884 return IUnknown_AddRef(this->outerUnknown
);
1887 /************************************************************************
1888 * DataCache_IOleCache2_Release (IUnknown)
1890 * See Windows documentation for more details on IUnknown methods.
1892 static ULONG WINAPI
DataCache_IOleCache2_Release(
1895 _ICOM_THIS_From_IOleCache2(DataCache
, iface
);
1897 return IUnknown_Release(this->outerUnknown
);
1900 static HRESULT WINAPI
DataCache_Cache(
1902 FORMATETC
* pformatetc
,
1904 DWORD
* pdwConnection
)
1910 static HRESULT WINAPI
DataCache_Uncache(
1918 static HRESULT WINAPI
DataCache_EnumCache(
1920 IEnumSTATDATA
** ppenumSTATDATA
)
1926 static HRESULT WINAPI
DataCache_InitCache(
1928 IDataObject
* pDataObject
)
1934 static HRESULT WINAPI
DataCache_IOleCache2_SetData(
1936 FORMATETC
* pformatetc
,
1944 static HRESULT WINAPI
DataCache_UpdateCache(
1946 LPDATAOBJECT pDataObject
,
1954 static HRESULT WINAPI
DataCache_DiscardCache(
1956 DWORD dwDiscardOptions
)
1963 /*********************************************************
1964 * Method implementation for the IOleCacheControl
1965 * part of the DataCache class.
1968 /************************************************************************
1969 * DataCache_IOleCacheControl_QueryInterface (IUnknown)
1971 * See Windows documentation for more details on IUnknown methods.
1973 static HRESULT WINAPI
DataCache_IOleCacheControl_QueryInterface(
1974 IOleCacheControl
* iface
,
1978 _ICOM_THIS_From_IOleCacheControl(DataCache
, iface
);
1980 return IUnknown_QueryInterface(this->outerUnknown
, riid
, ppvObject
);
1983 /************************************************************************
1984 * DataCache_IOleCacheControl_AddRef (IUnknown)
1986 * See Windows documentation for more details on IUnknown methods.
1988 static ULONG WINAPI
DataCache_IOleCacheControl_AddRef(
1989 IOleCacheControl
* iface
)
1991 _ICOM_THIS_From_IOleCacheControl(DataCache
, iface
);
1993 return IUnknown_AddRef(this->outerUnknown
);
1996 /************************************************************************
1997 * DataCache_IOleCacheControl_Release (IUnknown)
1999 * See Windows documentation for more details on IUnknown methods.
2001 static ULONG WINAPI
DataCache_IOleCacheControl_Release(
2002 IOleCacheControl
* iface
)
2004 _ICOM_THIS_From_IOleCacheControl(DataCache
, iface
);
2006 return IUnknown_Release(this->outerUnknown
);
2009 static HRESULT WINAPI
DataCache_OnRun(
2010 IOleCacheControl
* iface
,
2011 LPDATAOBJECT pDataObject
)
2017 static HRESULT WINAPI
DataCache_OnStop(
2018 IOleCacheControl
* iface
)