4 * Copyright 1999 Francis Beaudet
5 * Copyright 2000 Abey George
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * The OLE2 data cache supports a whole whack of
23 * interfaces including:
24 * IDataObject, IPersistStorage, IViewObject2,
25 * IOleCache2 and IOleCacheControl.
27 * Most of the implementation details are taken from: Inside OLE
28 * second edition by Kraig Brockschmidt,
31 * - This implementation of the datacache will let your application
32 * load documents that have embedded OLE objects in them and it will
33 * also retrieve the metafile representation of those objects.
34 * - This implementation of the datacache will also allow your
35 * application to save new documents with OLE objects in them.
36 * - The main thing that it doesn't do is allow you to activate
37 * or modify the OLE objects in any way.
38 * - I haven't found any good documentation on the real usage of
39 * the streams created by the data cache. In particular, How to
40 * determine what the XXX stands for in the stream name
41 * "\002OlePresXXX". It appears to just be a counter.
42 * - Also, I don't know the real content of the presentation stream
43 * header. I was able to figure-out where the extent of the object
44 * was stored and the aspect, but that's about it.
50 #define NONAMELESSUNION
51 #define NONAMELESSSTRUCT
57 #include "wine/unicode.h"
59 #include "wine/debug.h"
61 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
63 /****************************************************************************
64 * PresentationDataHeader
66 * This structure represents the header of the \002OlePresXXX stream in
67 * the OLE object strorage.
69 * Most fields are still unknown.
71 typedef struct PresentationDataHeader
73 DWORD unknown1
; /* -1 */
74 DWORD unknown2
; /* 3, possibly CF_METAFILEPICT */
75 DWORD unknown3
; /* 4, possibly TYMED_ISTREAM */
77 DWORD unknown5
; /* -1 */
80 DWORD unknown7
; /* 0 */
81 DWORD dwObjectExtentX
;
82 DWORD dwObjectExtentY
;
84 } PresentationDataHeader
;
86 /****************************************************************************
92 * List all interface VTables here
94 IDataObjectVtbl
* lpvtbl1
;
95 IUnknownVtbl
* lpvtbl2
;
96 IPersistStorageVtbl
* lpvtbl3
;
97 IViewObject2Vtbl
* lpvtbl4
;
98 IOleCache2Vtbl
* lpvtbl5
;
99 IOleCacheControlVtbl
* lpvtbl6
;
102 * Reference count of this object
107 * IUnknown implementation of the outer object.
109 IUnknown
* outerUnknown
;
112 * This storage pointer is set through a call to
113 * IPersistStorage_Load. This is where the visual
114 * representation of the object is stored.
116 IStorage
* presentationStorage
;
119 * The user of this object can setup ONE advise sink
120 * connection with the object. These parameters describe
124 DWORD sinkAdviseFlag
;
125 IAdviseSink
* sinkInterface
;
129 typedef struct DataCache DataCache
;
132 * Here, I define utility macros to help with the casting of the
134 * There is a version to accomodate all of the VTables implemented
137 #define _ICOM_THIS_From_IDataObject(class,name) class* this = (class*)name;
138 #define _ICOM_THIS_From_NDIUnknown(class, name) class* this = (class*)(((char*)name)-sizeof(void*));
139 #define _ICOM_THIS_From_IPersistStorage(class, name) class* this = (class*)(((char*)name)-2*sizeof(void*));
140 #define _ICOM_THIS_From_IViewObject2(class, name) class* this = (class*)(((char*)name)-3*sizeof(void*));
141 #define _ICOM_THIS_From_IOleCache2(class, name) class* this = (class*)(((char*)name)-4*sizeof(void*));
142 #define _ICOM_THIS_From_IOleCacheControl(class, name) class* this = (class*)(((char*)name)-5*sizeof(void*));
145 * Prototypes for the methods of the DataCache class.
147 static DataCache
* DataCache_Construct(REFCLSID clsid
,
148 LPUNKNOWN pUnkOuter
);
149 static void DataCache_Destroy(DataCache
* ptrToDestroy
);
150 static HRESULT
DataCache_ReadPresentationData(DataCache
* this,
152 PresentationDataHeader
* header
);
153 static HRESULT
DataCache_OpenPresStream(DataCache
*this,
156 static HMETAFILE
DataCache_ReadPresMetafile(DataCache
* this,
158 static void DataCache_FireOnViewChange(DataCache
* this,
163 * Prototypes for the methods of the DataCache class
164 * that implement non delegating IUnknown methods.
166 static HRESULT WINAPI
DataCache_NDIUnknown_QueryInterface(
170 static ULONG WINAPI
DataCache_NDIUnknown_AddRef(
172 static ULONG WINAPI
DataCache_NDIUnknown_Release(
176 * Prototypes for the methods of the DataCache class
177 * that implement IDataObject methods.
179 static HRESULT WINAPI
DataCache_IDataObject_QueryInterface(
183 static ULONG WINAPI
DataCache_IDataObject_AddRef(
185 static ULONG WINAPI
DataCache_IDataObject_Release(
187 static HRESULT WINAPI
DataCache_GetData(
189 LPFORMATETC pformatetcIn
,
191 static HRESULT WINAPI
DataCache_GetDataHere(
193 LPFORMATETC pformatetc
,
195 static HRESULT WINAPI
DataCache_QueryGetData(
197 LPFORMATETC pformatetc
);
198 static HRESULT WINAPI
DataCache_GetCanonicalFormatEtc(
200 LPFORMATETC pformatectIn
,
201 LPFORMATETC pformatetcOut
);
202 static HRESULT WINAPI
DataCache_IDataObject_SetData(
204 LPFORMATETC pformatetc
,
207 static HRESULT WINAPI
DataCache_EnumFormatEtc(
210 IEnumFORMATETC
** ppenumFormatEtc
);
211 static HRESULT WINAPI
DataCache_DAdvise(
213 FORMATETC
* pformatetc
,
215 IAdviseSink
* pAdvSink
,
216 DWORD
* pdwConnection
);
217 static HRESULT WINAPI
DataCache_DUnadvise(
220 static HRESULT WINAPI
DataCache_EnumDAdvise(
222 IEnumSTATDATA
** ppenumAdvise
);
225 * Prototypes for the methods of the DataCache class
226 * that implement IPersistStorage methods.
228 static HRESULT WINAPI
DataCache_IPersistStorage_QueryInterface(
229 IPersistStorage
* iface
,
232 static ULONG WINAPI
DataCache_IPersistStorage_AddRef(
233 IPersistStorage
* iface
);
234 static ULONG WINAPI
DataCache_IPersistStorage_Release(
235 IPersistStorage
* iface
);
236 static HRESULT WINAPI
DataCache_GetClassID(
237 IPersistStorage
* iface
,
239 static HRESULT WINAPI
DataCache_IsDirty(
240 IPersistStorage
* iface
);
241 static HRESULT WINAPI
DataCache_InitNew(
242 IPersistStorage
* iface
,
244 static HRESULT WINAPI
DataCache_Load(
245 IPersistStorage
* iface
,
247 static HRESULT WINAPI
DataCache_Save(
248 IPersistStorage
* iface
,
251 static HRESULT WINAPI
DataCache_SaveCompleted(
252 IPersistStorage
* iface
,
254 static HRESULT WINAPI
DataCache_HandsOffStorage(
255 IPersistStorage
* iface
);
258 * Prototypes for the methods of the DataCache class
259 * that implement IViewObject2 methods.
261 static HRESULT WINAPI
DataCache_IViewObject2_QueryInterface(
265 static ULONG WINAPI
DataCache_IViewObject2_AddRef(
266 IViewObject2
* iface
);
267 static ULONG WINAPI
DataCache_IViewObject2_Release(
268 IViewObject2
* iface
);
269 static HRESULT WINAPI
DataCache_Draw(
278 LPCRECTL lprcWBounds
,
279 BOOL (CALLBACK
*pfnContinue
)(ULONG_PTR dwContinue
),
281 static HRESULT WINAPI
DataCache_GetColorSet(
288 LOGPALETTE
** ppColorSet
);
289 static HRESULT WINAPI
DataCache_Freeze(
295 static HRESULT WINAPI
DataCache_Unfreeze(
298 static HRESULT WINAPI
DataCache_SetAdvise(
302 IAdviseSink
* pAdvSink
);
303 static HRESULT WINAPI
DataCache_GetAdvise(
307 IAdviseSink
** ppAdvSink
);
308 static HRESULT WINAPI
DataCache_GetExtent(
316 * Prototypes for the methods of the DataCache class
317 * that implement IOleCache2 methods.
319 static HRESULT WINAPI
DataCache_IOleCache2_QueryInterface(
323 static ULONG WINAPI
DataCache_IOleCache2_AddRef(
325 static ULONG WINAPI
DataCache_IOleCache2_Release(
327 static HRESULT WINAPI
DataCache_Cache(
329 FORMATETC
* pformatetc
,
331 DWORD
* pdwConnection
);
332 static HRESULT WINAPI
DataCache_Uncache(
335 static HRESULT WINAPI
DataCache_EnumCache(
337 IEnumSTATDATA
** ppenumSTATDATA
);
338 static HRESULT WINAPI
DataCache_InitCache(
340 IDataObject
* pDataObject
);
341 static HRESULT WINAPI
DataCache_IOleCache2_SetData(
343 FORMATETC
* pformatetc
,
346 static HRESULT WINAPI
DataCache_UpdateCache(
348 LPDATAOBJECT pDataObject
,
351 static HRESULT WINAPI
DataCache_DiscardCache(
353 DWORD dwDiscardOptions
);
356 * Prototypes for the methods of the DataCache class
357 * that implement IOleCacheControl methods.
359 static HRESULT WINAPI
DataCache_IOleCacheControl_QueryInterface(
360 IOleCacheControl
* iface
,
363 static ULONG WINAPI
DataCache_IOleCacheControl_AddRef(
364 IOleCacheControl
* iface
);
365 static ULONG WINAPI
DataCache_IOleCacheControl_Release(
366 IOleCacheControl
* iface
);
367 static HRESULT WINAPI
DataCache_OnRun(
368 IOleCacheControl
* iface
,
369 LPDATAOBJECT pDataObject
);
370 static HRESULT WINAPI
DataCache_OnStop(
371 IOleCacheControl
* iface
);
374 * Virtual function tables for the DataCache class.
376 static IUnknownVtbl DataCache_NDIUnknown_VTable
=
378 DataCache_NDIUnknown_QueryInterface
,
379 DataCache_NDIUnknown_AddRef
,
380 DataCache_NDIUnknown_Release
383 static IDataObjectVtbl DataCache_IDataObject_VTable
=
385 DataCache_IDataObject_QueryInterface
,
386 DataCache_IDataObject_AddRef
,
387 DataCache_IDataObject_Release
,
389 DataCache_GetDataHere
,
390 DataCache_QueryGetData
,
391 DataCache_GetCanonicalFormatEtc
,
392 DataCache_IDataObject_SetData
,
393 DataCache_EnumFormatEtc
,
396 DataCache_EnumDAdvise
399 static IPersistStorageVtbl DataCache_IPersistStorage_VTable
=
401 DataCache_IPersistStorage_QueryInterface
,
402 DataCache_IPersistStorage_AddRef
,
403 DataCache_IPersistStorage_Release
,
404 DataCache_GetClassID
,
409 DataCache_SaveCompleted
,
410 DataCache_HandsOffStorage
413 static IViewObject2Vtbl DataCache_IViewObject2_VTable
=
415 DataCache_IViewObject2_QueryInterface
,
416 DataCache_IViewObject2_AddRef
,
417 DataCache_IViewObject2_Release
,
419 DataCache_GetColorSet
,
427 static IOleCache2Vtbl DataCache_IOleCache2_VTable
=
429 DataCache_IOleCache2_QueryInterface
,
430 DataCache_IOleCache2_AddRef
,
431 DataCache_IOleCache2_Release
,
436 DataCache_IOleCache2_SetData
,
437 DataCache_UpdateCache
,
438 DataCache_DiscardCache
441 static IOleCacheControlVtbl DataCache_IOleCacheControl_VTable
=
443 DataCache_IOleCacheControl_QueryInterface
,
444 DataCache_IOleCacheControl_AddRef
,
445 DataCache_IOleCacheControl_Release
,
450 /******************************************************************************
451 * CreateDataCache [OLE32.@]
453 HRESULT WINAPI
CreateDataCache(
459 DataCache
* newCache
= NULL
;
462 TRACE("(%s, %p, %s, %p)\n", debugstr_guid(rclsid
), pUnkOuter
, debugstr_guid(riid
), ppvObj
);
473 * If this cache is constructed for aggregation, make sure
474 * the caller is requesting the IUnknown interface.
475 * This is necessary because it's the only time the non-delegating
476 * IUnknown pointer can be returned to the outside.
478 if ( (pUnkOuter
!=NULL
) &&
479 (memcmp(&IID_IUnknown
, riid
, sizeof(IID_IUnknown
)) != 0) )
480 return CLASS_E_NOAGGREGATION
;
483 * Try to construct a new instance of the class.
485 newCache
= DataCache_Construct(rclsid
,
489 return E_OUTOFMEMORY
;
492 * Make sure it supports the interface required by the caller.
494 hr
= IUnknown_QueryInterface((IUnknown
*)&(newCache
->lpvtbl2
), riid
, ppvObj
);
497 * Release the reference obtained in the constructor. If
498 * the QueryInterface was unsuccessful, it will free the class.
500 IUnknown_Release((IUnknown
*)&(newCache
->lpvtbl2
));
505 /*********************************************************
506 * Method implementation for DataCache class.
508 static DataCache
* DataCache_Construct(
512 DataCache
* newObject
= 0;
515 * Allocate space for the object.
517 newObject
= HeapAlloc(GetProcessHeap(), 0, sizeof(DataCache
));
523 * Initialize the virtual function table.
525 newObject
->lpvtbl1
= &DataCache_IDataObject_VTable
;
526 newObject
->lpvtbl2
= &DataCache_NDIUnknown_VTable
;
527 newObject
->lpvtbl3
= &DataCache_IPersistStorage_VTable
;
528 newObject
->lpvtbl4
= &DataCache_IViewObject2_VTable
;
529 newObject
->lpvtbl5
= &DataCache_IOleCache2_VTable
;
530 newObject
->lpvtbl6
= &DataCache_IOleCacheControl_VTable
;
533 * Start with one reference count. The caller of this function
534 * must release the interface pointer when it is done.
539 * Initialize the outer unknown
540 * We don't keep a reference on the outer unknown since, the way
541 * aggregation works, our lifetime is at least as large as it's
545 pUnkOuter
= (IUnknown
*)&(newObject
->lpvtbl2
);
547 newObject
->outerUnknown
= pUnkOuter
;
550 * Initialize the other members of the structure.
552 newObject
->presentationStorage
= NULL
;
553 newObject
->sinkAspects
= 0;
554 newObject
->sinkAdviseFlag
= 0;
555 newObject
->sinkInterface
= 0;
560 static void DataCache_Destroy(
561 DataCache
* ptrToDestroy
)
565 if (ptrToDestroy
->sinkInterface
!= NULL
)
567 IAdviseSink_Release(ptrToDestroy
->sinkInterface
);
568 ptrToDestroy
->sinkInterface
= NULL
;
571 if (ptrToDestroy
->presentationStorage
!= NULL
)
573 IStorage_Release(ptrToDestroy
->presentationStorage
);
574 ptrToDestroy
->presentationStorage
= NULL
;
578 * Free the datacache pointer.
580 HeapFree(GetProcessHeap(), 0, ptrToDestroy
);
583 /************************************************************************
584 * DataCache_ReadPresentationData
586 * This method will read information for the requested presentation
587 * into the given structure.
590 * this - Pointer to the DataCache object
591 * drawAspect - The aspect of the object that we wish to draw.
592 * header - The structure containing information about this
593 * aspect of the object.
595 static HRESULT
DataCache_ReadPresentationData(
598 PresentationDataHeader
* header
)
600 IStream
* presStream
= NULL
;
604 * Open the presentation stream.
606 hres
= DataCache_OpenPresStream(
621 sizeof(PresentationDataHeader
),
627 IStream_Release(presStream
);
630 * We don't want to propagate any other error
631 * code than a failure.
639 /************************************************************************
640 * DataCache_FireOnViewChange
642 * This method will fire an OnViewChange notification to the advise
643 * sink registered with the datacache.
645 * See IAdviseSink::OnViewChange for more details.
647 static void DataCache_FireOnViewChange(
652 TRACE("(%p, %lx, %ld)\n", this, aspect
, lindex
);
655 * The sink supplies a filter when it registers
656 * we make sure we only send the notifications when that
659 if ((this->sinkAspects
& aspect
) != 0)
661 if (this->sinkInterface
!= NULL
)
663 IAdviseSink_OnViewChange(this->sinkInterface
,
668 * Some sinks want to be unregistered automatically when
669 * the first notification goes out.
671 if ( (this->sinkAdviseFlag
& ADVF_ONLYONCE
) != 0)
673 IAdviseSink_Release(this->sinkInterface
);
675 this->sinkInterface
= NULL
;
676 this->sinkAspects
= 0;
677 this->sinkAdviseFlag
= 0;
683 /* Helper for DataCache_OpenPresStream */
684 static BOOL
DataCache_IsPresentationStream(const STATSTG
*elem
)
686 /* The presentation streams have names of the form "\002OlePresXXX",
687 * where XXX goes from 000 to 999. */
688 static const WCHAR OlePres
[] = { 2,'O','l','e','P','r','e','s' };
690 LPCWSTR name
= elem
->pwcsName
;
692 return (elem
->type
== STGTY_STREAM
)
693 && (elem
->cbSize
.u
.LowPart
>= sizeof(PresentationDataHeader
))
694 && (strlenW(name
) == 11)
695 && (strncmpW(name
, OlePres
, 8) == 0)
696 && (name
[8] >= '0') && (name
[8] <= '9')
697 && (name
[9] >= '0') && (name
[9] <= '9')
698 && (name
[10] >= '0') && (name
[10] <= '9');
701 /************************************************************************
702 * DataCache_OpenPresStream
704 * This method will find the stream for the given presentation. It makes
705 * no attempt at fallback.
708 * this - Pointer to the DataCache object
709 * drawAspect - The aspect of the object that we wish to draw.
710 * pStm - A returned stream. It points to the beginning of the
711 * - presentation data, including the header.
714 * S_OK The requested stream has been opened.
715 * OLE_E_BLANK The requested stream could not be found.
716 * Quite a few others I'm too lazy to map correctly.
719 * Algorithm: Scan the elements of the presentation storage, looking
720 * for presentation streams. For each presentation stream,
721 * load the header and check to see if the aspect maches.
723 * If a fallback is desired, just opening the first presentation stream
726 static HRESULT
DataCache_OpenPresStream(
735 if (!ppStm
) return E_POINTER
;
737 hr
= IStorage_EnumElements(this->presentationStorage
, 0, NULL
, 0, &pEnum
);
738 if (FAILED(hr
)) return hr
;
740 while ((hr
= IEnumSTATSTG_Next(pEnum
, 1, &elem
, NULL
)) == S_OK
)
742 if (DataCache_IsPresentationStream(&elem
))
746 hr
= IStorage_OpenStream(this->presentationStorage
, elem
.pwcsName
,
747 NULL
, STGM_READ
| STGM_SHARE_EXCLUSIVE
, 0,
751 PresentationDataHeader header
;
754 hr
= IStream_Read(pStm
, &header
, sizeof(header
), &actual_read
);
756 /* can't use SUCCEEDED(hr): S_FALSE counts as an error */
757 if (hr
== S_OK
&& actual_read
== sizeof(header
)
758 && header
.dvAspect
== drawAspect
)
760 /* Rewind the stream before returning it. */
761 LARGE_INTEGER offset
;
762 offset
.u
.LowPart
= 0;
763 offset
.u
.HighPart
= 0;
764 IStream_Seek(pStm
, offset
, STREAM_SEEK_SET
, NULL
);
768 CoTaskMemFree(elem
.pwcsName
);
769 IEnumSTATSTG_Release(pEnum
);
774 IStream_Release(pStm
);
778 CoTaskMemFree(elem
.pwcsName
);
781 IEnumSTATSTG_Release(pEnum
);
783 return (hr
== S_FALSE
? OLE_E_BLANK
: hr
);
786 /************************************************************************
787 * DataCache_ReadPresentationData
789 * This method will read information for the requested presentation
790 * into the given structure.
793 * this - Pointer to the DataCache object
794 * drawAspect - The aspect of the object that we wish to draw.
797 * This method returns a metafile handle if it is successful.
798 * it will return 0 if not.
800 static HMETAFILE
DataCache_ReadPresMetafile(
804 LARGE_INTEGER offset
;
805 IStream
* presStream
= NULL
;
809 HMETAFILE newMetafile
= 0;
812 * Open the presentation stream.
814 hres
= DataCache_OpenPresStream(
820 return (HMETAFILE
)hres
;
823 * Get the size of the stream.
825 hres
= IStream_Stat(presStream
,
832 offset
.u
.HighPart
= 0;
833 offset
.u
.LowPart
= sizeof(PresentationDataHeader
);
841 streamInfo
.cbSize
.u
.LowPart
-= offset
.u
.LowPart
;
844 * Allocate a buffer for the metafile bits.
846 metafileBits
= HeapAlloc(GetProcessHeap(),
848 streamInfo
.cbSize
.u
.LowPart
);
851 * Read the metafile bits.
856 streamInfo
.cbSize
.u
.LowPart
,
860 * Create a metafile with those bits.
864 newMetafile
= SetMetaFileBitsEx(streamInfo
.cbSize
.u
.LowPart
, metafileBits
);
870 HeapFree(GetProcessHeap(), 0, metafileBits
);
871 IStream_Release(presStream
);
879 /*********************************************************
880 * Method implementation for the non delegating IUnknown
881 * part of the DataCache class.
884 /************************************************************************
885 * DataCache_NDIUnknown_QueryInterface (IUnknown)
887 * See Windows documentation for more details on IUnknown methods.
889 * This version of QueryInterface will not delegate it's implementation
890 * to the outer unknown.
892 static HRESULT WINAPI
DataCache_NDIUnknown_QueryInterface(
897 _ICOM_THIS_From_NDIUnknown(DataCache
, iface
);
900 * Perform a sanity check on the parameters.
902 if ( (this==0) || (ppvObject
==0) )
906 * Initialize the return parameter.
911 * Compare the riid with the interface IDs implemented by this object.
913 if (memcmp(&IID_IUnknown
, riid
, sizeof(IID_IUnknown
)) == 0)
917 else if (memcmp(&IID_IDataObject
, riid
, sizeof(IID_IDataObject
)) == 0)
919 *ppvObject
= (IDataObject
*)&(this->lpvtbl1
);
921 else if ( (memcmp(&IID_IPersistStorage
, riid
, sizeof(IID_IPersistStorage
)) == 0) ||
922 (memcmp(&IID_IPersist
, riid
, sizeof(IID_IPersist
)) == 0) )
924 *ppvObject
= (IPersistStorage
*)&(this->lpvtbl3
);
926 else if ( (memcmp(&IID_IViewObject
, riid
, sizeof(IID_IViewObject
)) == 0) ||
927 (memcmp(&IID_IViewObject2
, riid
, sizeof(IID_IViewObject2
)) == 0) )
929 *ppvObject
= (IViewObject2
*)&(this->lpvtbl4
);
931 else if ( (memcmp(&IID_IOleCache
, riid
, sizeof(IID_IOleCache
)) == 0) ||
932 (memcmp(&IID_IOleCache2
, riid
, sizeof(IID_IOleCache2
)) == 0) )
934 *ppvObject
= (IOleCache2
*)&(this->lpvtbl5
);
936 else if (memcmp(&IID_IOleCacheControl
, riid
, sizeof(IID_IOleCacheControl
)) == 0)
938 *ppvObject
= (IOleCacheControl
*)&(this->lpvtbl6
);
942 * Check that we obtained an interface.
946 WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid
));
947 return E_NOINTERFACE
;
951 * Query Interface always increases the reference count by one when it is
954 IUnknown_AddRef((IUnknown
*)*ppvObject
);
959 /************************************************************************
960 * DataCache_NDIUnknown_AddRef (IUnknown)
962 * See Windows documentation for more details on IUnknown methods.
964 * This version of QueryInterface will not delegate it's implementation
965 * to the outer unknown.
967 static ULONG WINAPI
DataCache_NDIUnknown_AddRef(
970 _ICOM_THIS_From_NDIUnknown(DataCache
, iface
);
977 /************************************************************************
978 * DataCache_NDIUnknown_Release (IUnknown)
980 * See Windows documentation for more details on IUnknown methods.
982 * This version of QueryInterface will not delegate it's implementation
983 * to the outer unknown.
985 static ULONG WINAPI
DataCache_NDIUnknown_Release(
988 _ICOM_THIS_From_NDIUnknown(DataCache
, iface
);
991 * Decrease the reference count on this object.
996 * If the reference count goes down to 0, perform suicide.
1000 DataCache_Destroy(this);
1008 /*********************************************************
1009 * Method implementation for the IDataObject
1010 * part of the DataCache class.
1013 /************************************************************************
1014 * DataCache_IDataObject_QueryInterface (IUnknown)
1016 * See Windows documentation for more details on IUnknown methods.
1018 static HRESULT WINAPI
DataCache_IDataObject_QueryInterface(
1023 _ICOM_THIS_From_IDataObject(DataCache
, iface
);
1025 return IUnknown_QueryInterface(this->outerUnknown
, riid
, ppvObject
);
1028 /************************************************************************
1029 * DataCache_IDataObject_AddRef (IUnknown)
1031 * See Windows documentation for more details on IUnknown methods.
1033 static ULONG WINAPI
DataCache_IDataObject_AddRef(
1036 _ICOM_THIS_From_IDataObject(DataCache
, iface
);
1038 return IUnknown_AddRef(this->outerUnknown
);
1041 /************************************************************************
1042 * DataCache_IDataObject_Release (IUnknown)
1044 * See Windows documentation for more details on IUnknown methods.
1046 static ULONG WINAPI
DataCache_IDataObject_Release(
1049 _ICOM_THIS_From_IDataObject(DataCache
, iface
);
1051 return IUnknown_Release(this->outerUnknown
);
1054 /************************************************************************
1057 * Get Data from a source dataobject using format pformatetcIn->cfFormat
1058 * See Windows documentation for more details on GetData.
1059 * TODO: Currently only CF_METAFILEPICT is implemented
1061 static HRESULT WINAPI
DataCache_GetData(
1063 LPFORMATETC pformatetcIn
,
1067 HRESULT hrRet
= E_UNEXPECTED
;
1068 IPersistStorage
*pPersistStorage
= 0;
1069 IStorage
*pStorage
= 0;
1070 IStream
*pStream
= 0;
1071 OLECHAR name
[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
1072 HGLOBAL hGlobalMF
= 0;
1074 PresentationDataHeader pdh
;
1075 METAFILEPICT
*mfPict
;
1076 HMETAFILE hMetaFile
= 0;
1078 if (pformatetcIn
->cfFormat
== CF_METAFILEPICT
)
1080 /* Get the Persist Storage */
1082 hr
= IDataObject_QueryInterface(iface
, &IID_IPersistStorage
, (void**)&pPersistStorage
);
1087 /* Create a doc file to copy the doc to a storage */
1089 hr
= StgCreateDocfile(NULL
, STGM_CREATE
| STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, &pStorage
);
1094 /* Save it to storage */
1096 hr
= OleSave(pPersistStorage
, pStorage
, FALSE
);
1101 /* Open the Presentation data srteam */
1103 hr
= IStorage_OpenStream(pStorage
, name
, 0, STGM_CREATE
|STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, 0, &pStream
);
1108 /* Read the presentation header */
1110 hr
= IStream_Read(pStream
, &pdh
, sizeof(PresentationDataHeader
), NULL
);
1115 mfBits
= HeapAlloc(GetProcessHeap(), 0, pdh
.dwSize
);
1117 /* Read the Metafile bits */
1119 hr
= IStream_Read(pStream
, mfBits
, pdh
.dwSize
, NULL
);
1124 /* Create the metafile and place it in the STGMEDIUM structure */
1126 hMetaFile
= SetMetaFileBitsEx(pdh
.dwSize
, mfBits
);
1128 hGlobalMF
= GlobalAlloc(GMEM_SHARE
|GMEM_MOVEABLE
, sizeof(METAFILEPICT
));
1129 mfPict
= (METAFILEPICT
*)GlobalLock(hGlobalMF
);
1130 mfPict
->hMF
= hMetaFile
;
1132 GlobalUnlock(hGlobalMF
);
1134 pmedium
->u
.hGlobal
= hGlobalMF
;
1135 pmedium
->tymed
= TYMED_MFPICT
;
1141 HeapFree(GetProcessHeap(), 0, mfBits
);
1144 IStream_Release(pStream
);
1147 IStorage_Release(pStorage
);
1149 if (pPersistStorage
)
1150 IPersistStorage_Release(pPersistStorage
);
1155 /* TODO: Other formats are not implemented */
1160 static HRESULT WINAPI
DataCache_GetDataHere(
1162 LPFORMATETC pformatetc
,
1169 static HRESULT WINAPI
DataCache_QueryGetData(
1171 LPFORMATETC pformatetc
)
1177 /************************************************************************
1178 * DataCache_EnumFormatEtc (IDataObject)
1180 * The data cache doesn't implement this method.
1182 * See Windows documentation for more details on IDataObject methods.
1184 static HRESULT WINAPI
DataCache_GetCanonicalFormatEtc(
1186 LPFORMATETC pformatectIn
,
1187 LPFORMATETC pformatetcOut
)
1193 /************************************************************************
1194 * DataCache_IDataObject_SetData (IDataObject)
1196 * This method is delegated to the IOleCache2 implementation.
1198 * See Windows documentation for more details on IDataObject methods.
1200 static HRESULT WINAPI
DataCache_IDataObject_SetData(
1202 LPFORMATETC pformatetc
,
1206 IOleCache2
* oleCache
= NULL
;
1209 TRACE("(%p, %p, %p, %d)\n", iface
, pformatetc
, pmedium
, fRelease
);
1211 hres
= IDataObject_QueryInterface(iface
, &IID_IOleCache2
, (void**)&oleCache
);
1214 return E_UNEXPECTED
;
1216 hres
= IOleCache2_SetData(oleCache
, pformatetc
, pmedium
, fRelease
);
1218 IOleCache2_Release(oleCache
);
1223 /************************************************************************
1224 * DataCache_EnumFormatEtc (IDataObject)
1226 * The data cache doesn't implement this method.
1228 * See Windows documentation for more details on IDataObject methods.
1230 static HRESULT WINAPI
DataCache_EnumFormatEtc(
1233 IEnumFORMATETC
** ppenumFormatEtc
)
1239 /************************************************************************
1240 * DataCache_DAdvise (IDataObject)
1242 * The data cache doesn't support connections.
1244 * See Windows documentation for more details on IDataObject methods.
1246 static HRESULT WINAPI
DataCache_DAdvise(
1248 FORMATETC
* pformatetc
,
1250 IAdviseSink
* pAdvSink
,
1251 DWORD
* pdwConnection
)
1254 return OLE_E_ADVISENOTSUPPORTED
;
1257 /************************************************************************
1258 * DataCache_DUnadvise (IDataObject)
1260 * The data cache doesn't support connections.
1262 * See Windows documentation for more details on IDataObject methods.
1264 static HRESULT WINAPI
DataCache_DUnadvise(
1269 return OLE_E_NOCONNECTION
;
1272 /************************************************************************
1273 * DataCache_EnumDAdvise (IDataObject)
1275 * The data cache doesn't support connections.
1277 * See Windows documentation for more details on IDataObject methods.
1279 static HRESULT WINAPI
DataCache_EnumDAdvise(
1281 IEnumSTATDATA
** ppenumAdvise
)
1284 return OLE_E_ADVISENOTSUPPORTED
;
1287 /*********************************************************
1288 * Method implementation for the IDataObject
1289 * part of the DataCache class.
1292 /************************************************************************
1293 * DataCache_IPersistStorage_QueryInterface (IUnknown)
1295 * See Windows documentation for more details on IUnknown methods.
1297 static HRESULT WINAPI
DataCache_IPersistStorage_QueryInterface(
1298 IPersistStorage
* iface
,
1302 _ICOM_THIS_From_IPersistStorage(DataCache
, iface
);
1304 return IUnknown_QueryInterface(this->outerUnknown
, riid
, ppvObject
);
1307 /************************************************************************
1308 * DataCache_IPersistStorage_AddRef (IUnknown)
1310 * See Windows documentation for more details on IUnknown methods.
1312 static ULONG WINAPI
DataCache_IPersistStorage_AddRef(
1313 IPersistStorage
* iface
)
1315 _ICOM_THIS_From_IPersistStorage(DataCache
, iface
);
1317 return IUnknown_AddRef(this->outerUnknown
);
1320 /************************************************************************
1321 * DataCache_IPersistStorage_Release (IUnknown)
1323 * See Windows documentation for more details on IUnknown methods.
1325 static ULONG WINAPI
DataCache_IPersistStorage_Release(
1326 IPersistStorage
* iface
)
1328 _ICOM_THIS_From_IPersistStorage(DataCache
, iface
);
1330 return IUnknown_Release(this->outerUnknown
);
1333 /************************************************************************
1334 * DataCache_GetClassID (IPersistStorage)
1336 * The data cache doesn't implement this method.
1338 * See Windows documentation for more details on IPersistStorage methods.
1340 static HRESULT WINAPI
DataCache_GetClassID(
1341 IPersistStorage
* iface
,
1344 TRACE("(%p, %p)\n", iface
, pClassID
);
1348 /************************************************************************
1349 * DataCache_IsDirty (IPersistStorage)
1351 * Until we actully connect to a running object and retrieve new
1352 * information to it, we never get dirty.
1354 * See Windows documentation for more details on IPersistStorage methods.
1356 static HRESULT WINAPI
DataCache_IsDirty(
1357 IPersistStorage
* iface
)
1359 TRACE("(%p)\n", iface
);
1364 /************************************************************************
1365 * DataCache_InitNew (IPersistStorage)
1367 * The data cache implementation of IPersistStorage_InitNew simply stores
1368 * the storage pointer.
1370 * See Windows documentation for more details on IPersistStorage methods.
1372 static HRESULT WINAPI
DataCache_InitNew(
1373 IPersistStorage
* iface
,
1376 TRACE("(%p, %p)\n", iface
, pStg
);
1378 return DataCache_Load(iface
, pStg
);
1381 /************************************************************************
1382 * DataCache_Load (IPersistStorage)
1384 * The data cache implementation of IPersistStorage_Load doesn't
1385 * actually load anything. Instead, it holds on to the storage pointer
1386 * and it will load the presentation information when the
1387 * IDataObject_GetData or IViewObject2_Draw methods are called.
1389 * See Windows documentation for more details on IPersistStorage methods.
1391 static HRESULT WINAPI
DataCache_Load(
1392 IPersistStorage
* iface
,
1395 _ICOM_THIS_From_IPersistStorage(DataCache
, iface
);
1397 TRACE("(%p, %p)\n", iface
, pStg
);
1399 if (this->presentationStorage
!= NULL
)
1401 IStorage_Release(this->presentationStorage
);
1404 this->presentationStorage
= pStg
;
1406 if (this->presentationStorage
!= NULL
)
1408 IStorage_AddRef(this->presentationStorage
);
1413 /************************************************************************
1414 * DataCache_Save (IPersistStorage)
1416 * Until we actully connect to a running object and retrieve new
1417 * information to it, we never have to save anything. However, it is
1418 * our responsability to copy the information when saving to a new
1421 * See Windows documentation for more details on IPersistStorage methods.
1423 static HRESULT WINAPI
DataCache_Save(
1424 IPersistStorage
* iface
,
1428 _ICOM_THIS_From_IPersistStorage(DataCache
, iface
);
1430 TRACE("(%p, %p, %d)\n", iface
, pStg
, fSameAsLoad
);
1432 if ( (!fSameAsLoad
) &&
1433 (this->presentationStorage
!=NULL
) )
1435 return IStorage_CopyTo(this->presentationStorage
,
1445 /************************************************************************
1446 * DataCache_SaveCompleted (IPersistStorage)
1448 * This method is called to tell the cache to release the storage
1449 * pointer it's currentlu holding.
1451 * See Windows documentation for more details on IPersistStorage methods.
1453 static HRESULT WINAPI
DataCache_SaveCompleted(
1454 IPersistStorage
* iface
,
1457 TRACE("(%p, %p)\n", iface
, pStgNew
);
1462 * First, make sure we get our hands off any storage we have.
1465 DataCache_HandsOffStorage(iface
);
1468 * Then, attach to the new storage.
1471 DataCache_Load(iface
, pStgNew
);
1477 /************************************************************************
1478 * DataCache_HandsOffStorage (IPersistStorage)
1480 * This method is called to tell the cache to release the storage
1481 * pointer it's currentlu holding.
1483 * See Windows documentation for more details on IPersistStorage methods.
1485 static HRESULT WINAPI
DataCache_HandsOffStorage(
1486 IPersistStorage
* iface
)
1488 _ICOM_THIS_From_IPersistStorage(DataCache
, iface
);
1490 TRACE("(%p)\n", iface
);
1492 if (this->presentationStorage
!= NULL
)
1494 IStorage_Release(this->presentationStorage
);
1495 this->presentationStorage
= NULL
;
1501 /*********************************************************
1502 * Method implementation for the IViewObject2
1503 * part of the DataCache class.
1506 /************************************************************************
1507 * DataCache_IViewObject2_QueryInterface (IUnknown)
1509 * See Windows documentation for more details on IUnknown methods.
1511 static HRESULT WINAPI
DataCache_IViewObject2_QueryInterface(
1512 IViewObject2
* iface
,
1516 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1518 return IUnknown_QueryInterface(this->outerUnknown
, riid
, ppvObject
);
1521 /************************************************************************
1522 * DataCache_IViewObject2_AddRef (IUnknown)
1524 * See Windows documentation for more details on IUnknown methods.
1526 static ULONG WINAPI
DataCache_IViewObject2_AddRef(
1527 IViewObject2
* iface
)
1529 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1531 return IUnknown_AddRef(this->outerUnknown
);
1534 /************************************************************************
1535 * DataCache_IViewObject2_Release (IUnknown)
1537 * See Windows documentation for more details on IUnknown methods.
1539 static ULONG WINAPI
DataCache_IViewObject2_Release(
1540 IViewObject2
* iface
)
1542 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1544 return IUnknown_Release(this->outerUnknown
);
1547 /************************************************************************
1548 * DataCache_Draw (IViewObject2)
1550 * This method will draw the cached representation of the object
1551 * to the given device context.
1553 * See Windows documentation for more details on IViewObject2 methods.
1555 static HRESULT WINAPI
DataCache_Draw(
1556 IViewObject2
* iface
,
1560 DVTARGETDEVICE
* ptd
,
1563 LPCRECTL lprcBounds
,
1564 LPCRECTL lprcWBounds
,
1565 BOOL (CALLBACK
*pfnContinue
)(ULONG_PTR dwContinue
),
1568 PresentationDataHeader presData
;
1569 HMETAFILE presMetafile
= 0;
1572 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1574 TRACE("(%p, %lx, %ld, %p, %p, %p, %p, %p, %p, %lx)\n",
1589 if (lprcBounds
==NULL
)
1590 return E_INVALIDARG
;
1593 * First, we need to retrieve the dimensions of the
1594 * image in the metafile.
1596 hres
= DataCache_ReadPresentationData(this,
1604 * Then, we can extract the metafile itself from the cached
1607 * FIXME Unless it isn't a metafile. I think it could be any CF_XXX type,
1608 * particularly CF_DIB.
1610 presMetafile
= DataCache_ReadPresMetafile(this,
1614 * If we have a metafile, just draw baby...
1615 * We have to be careful not to modify the state of the
1618 if (presMetafile
!=0)
1620 INT prevMapMode
= SetMapMode(hdcDraw
, MM_ANISOTROPIC
);
1622 SIZE oldViewportExt
;
1623 POINT oldViewportOrg
;
1625 SetWindowExtEx(hdcDraw
,
1626 presData
.dwObjectExtentX
,
1627 presData
.dwObjectExtentY
,
1630 SetViewportExtEx(hdcDraw
,
1631 lprcBounds
->right
- lprcBounds
->left
,
1632 lprcBounds
->bottom
- lprcBounds
->top
,
1635 SetViewportOrgEx(hdcDraw
,
1640 PlayMetaFile(hdcDraw
, presMetafile
);
1642 SetWindowExtEx(hdcDraw
,
1647 SetViewportExtEx(hdcDraw
,
1652 SetViewportOrgEx(hdcDraw
,
1657 SetMapMode(hdcDraw
, prevMapMode
);
1659 DeleteMetaFile(presMetafile
);
1665 static HRESULT WINAPI
DataCache_GetColorSet(
1666 IViewObject2
* iface
,
1670 DVTARGETDEVICE
* ptd
,
1671 HDC hicTargetDevice
,
1672 LOGPALETTE
** ppColorSet
)
1678 static HRESULT WINAPI
DataCache_Freeze(
1679 IViewObject2
* iface
,
1689 static HRESULT WINAPI
DataCache_Unfreeze(
1690 IViewObject2
* iface
,
1697 /************************************************************************
1698 * DataCache_SetAdvise (IViewObject2)
1700 * This sets-up an advisory sink with the data cache. When the object's
1701 * view changes, this sink is called.
1703 * See Windows documentation for more details on IViewObject2 methods.
1705 static HRESULT WINAPI
DataCache_SetAdvise(
1706 IViewObject2
* iface
,
1709 IAdviseSink
* pAdvSink
)
1711 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1713 TRACE("(%p, %lx, %lx, %p)\n", iface
, aspects
, advf
, pAdvSink
);
1716 * A call to this function removes the previous sink
1718 if (this->sinkInterface
!= NULL
)
1720 IAdviseSink_Release(this->sinkInterface
);
1721 this->sinkInterface
= NULL
;
1722 this->sinkAspects
= 0;
1723 this->sinkAdviseFlag
= 0;
1727 * Now, setup the new one.
1731 this->sinkInterface
= pAdvSink
;
1732 this->sinkAspects
= aspects
;
1733 this->sinkAdviseFlag
= advf
;
1735 IAdviseSink_AddRef(this->sinkInterface
);
1739 * When the ADVF_PRIMEFIRST flag is set, we have to advise the
1742 if (advf
& ADVF_PRIMEFIRST
)
1744 DataCache_FireOnViewChange(this,
1752 /************************************************************************
1753 * DataCache_GetAdvise (IViewObject2)
1755 * This method queries the current state of the advise sink
1756 * installed on the data cache.
1758 * See Windows documentation for more details on IViewObject2 methods.
1760 static HRESULT WINAPI
DataCache_GetAdvise(
1761 IViewObject2
* iface
,
1764 IAdviseSink
** ppAdvSink
)
1766 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1768 TRACE("(%p, %p, %p, %p)\n", iface
, pAspects
, pAdvf
, ppAdvSink
);
1771 * Just copy all the requested values.
1774 *pAspects
= this->sinkAspects
;
1777 *pAdvf
= this->sinkAdviseFlag
;
1779 if (ppAdvSink
!=NULL
)
1781 IAdviseSink_QueryInterface(this->sinkInterface
,
1789 /************************************************************************
1790 * DataCache_GetExtent (IViewObject2)
1792 * This method retrieves the "natural" size of this cached object.
1794 * See Windows documentation for more details on IViewObject2 methods.
1796 static HRESULT WINAPI
DataCache_GetExtent(
1797 IViewObject2
* iface
,
1800 DVTARGETDEVICE
* ptd
,
1803 PresentationDataHeader presData
;
1804 HRESULT hres
= E_FAIL
;
1806 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1808 TRACE("(%p, %lx, %ld, %p, %p)\n",
1809 iface
, dwDrawAspect
, lindex
, ptd
, lpsizel
);
1818 * Initialize the out parameter.
1824 * This flag should be set to -1.
1827 FIXME("Unimplemented flag lindex = %ld\n", lindex
);
1830 * Right now, we support only the callback from
1831 * the default handler.
1834 FIXME("Unimplemented ptd = %p\n", ptd
);
1837 * Get the presentation information from the
1840 hres
= DataCache_ReadPresentationData(this,
1844 if (SUCCEEDED(hres
))
1846 lpsizel
->cx
= presData
.dwObjectExtentX
;
1847 lpsizel
->cy
= presData
.dwObjectExtentY
;
1851 * This method returns OLE_E_BLANK when it fails.
1860 /*********************************************************
1861 * Method implementation for the IOleCache2
1862 * part of the DataCache class.
1865 /************************************************************************
1866 * DataCache_IOleCache2_QueryInterface (IUnknown)
1868 * See Windows documentation for more details on IUnknown methods.
1870 static HRESULT WINAPI
DataCache_IOleCache2_QueryInterface(
1875 _ICOM_THIS_From_IOleCache2(DataCache
, iface
);
1877 return IUnknown_QueryInterface(this->outerUnknown
, riid
, ppvObject
);
1880 /************************************************************************
1881 * DataCache_IOleCache2_AddRef (IUnknown)
1883 * See Windows documentation for more details on IUnknown methods.
1885 static ULONG WINAPI
DataCache_IOleCache2_AddRef(
1888 _ICOM_THIS_From_IOleCache2(DataCache
, iface
);
1890 return IUnknown_AddRef(this->outerUnknown
);
1893 /************************************************************************
1894 * DataCache_IOleCache2_Release (IUnknown)
1896 * See Windows documentation for more details on IUnknown methods.
1898 static ULONG WINAPI
DataCache_IOleCache2_Release(
1901 _ICOM_THIS_From_IOleCache2(DataCache
, iface
);
1903 return IUnknown_Release(this->outerUnknown
);
1906 static HRESULT WINAPI
DataCache_Cache(
1908 FORMATETC
* pformatetc
,
1910 DWORD
* pdwConnection
)
1916 static HRESULT WINAPI
DataCache_Uncache(
1924 static HRESULT WINAPI
DataCache_EnumCache(
1926 IEnumSTATDATA
** ppenumSTATDATA
)
1932 static HRESULT WINAPI
DataCache_InitCache(
1934 IDataObject
* pDataObject
)
1940 static HRESULT WINAPI
DataCache_IOleCache2_SetData(
1942 FORMATETC
* pformatetc
,
1950 static HRESULT WINAPI
DataCache_UpdateCache(
1952 LPDATAOBJECT pDataObject
,
1960 static HRESULT WINAPI
DataCache_DiscardCache(
1962 DWORD dwDiscardOptions
)
1969 /*********************************************************
1970 * Method implementation for the IOleCacheControl
1971 * part of the DataCache class.
1974 /************************************************************************
1975 * DataCache_IOleCacheControl_QueryInterface (IUnknown)
1977 * See Windows documentation for more details on IUnknown methods.
1979 static HRESULT WINAPI
DataCache_IOleCacheControl_QueryInterface(
1980 IOleCacheControl
* iface
,
1984 _ICOM_THIS_From_IOleCacheControl(DataCache
, iface
);
1986 return IUnknown_QueryInterface(this->outerUnknown
, riid
, ppvObject
);
1989 /************************************************************************
1990 * DataCache_IOleCacheControl_AddRef (IUnknown)
1992 * See Windows documentation for more details on IUnknown methods.
1994 static ULONG WINAPI
DataCache_IOleCacheControl_AddRef(
1995 IOleCacheControl
* iface
)
1997 _ICOM_THIS_From_IOleCacheControl(DataCache
, iface
);
1999 return IUnknown_AddRef(this->outerUnknown
);
2002 /************************************************************************
2003 * DataCache_IOleCacheControl_Release (IUnknown)
2005 * See Windows documentation for more details on IUnknown methods.
2007 static ULONG WINAPI
DataCache_IOleCacheControl_Release(
2008 IOleCacheControl
* iface
)
2010 _ICOM_THIS_From_IOleCacheControl(DataCache
, iface
);
2012 return IUnknown_Release(this->outerUnknown
);
2015 static HRESULT WINAPI
DataCache_OnRun(
2016 IOleCacheControl
* iface
,
2017 LPDATAOBJECT pDataObject
)
2023 static HRESULT WINAPI
DataCache_OnStop(
2024 IOleCacheControl
* iface
)