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.
51 #define NONAMELESSUNION
52 #define NONAMELESSSTRUCT
59 #include "wine/unicode.h"
61 #include "wine/debug.h"
63 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
65 /****************************************************************************
66 * PresentationDataHeader
68 * This structure represents the header of the \002OlePresXXX stream in
69 * the OLE object strorage.
71 * Most fields are still unknown.
73 typedef struct PresentationDataHeader
75 DWORD unknown1
; /* -1 */
76 DWORD unknown2
; /* 3, possibly CF_METAFILEPICT */
77 DWORD unknown3
; /* 4, possibly TYMED_ISTREAM */
79 DWORD unknown5
; /* -1 */
82 DWORD unknown7
; /* 0 */
83 DWORD dwObjectExtentX
;
84 DWORD dwObjectExtentY
;
86 } PresentationDataHeader
;
88 /****************************************************************************
94 * List all interface VTables here
96 IDataObjectVtbl
* lpvtbl1
;
97 IUnknownVtbl
* lpvtbl2
;
98 IPersistStorageVtbl
* lpvtbl3
;
99 IViewObject2Vtbl
* lpvtbl4
;
100 IOleCache2Vtbl
* lpvtbl5
;
101 IOleCacheControlVtbl
* lpvtbl6
;
104 * Reference count of this object
109 * IUnknown implementation of the outer object.
111 IUnknown
* outerUnknown
;
114 * This storage pointer is set through a call to
115 * IPersistStorage_Load. This is where the visual
116 * representation of the object is stored.
118 IStorage
* presentationStorage
;
121 * The user of this object can setup ONE advise sink
122 * connection with the object. These parameters describe
126 DWORD sinkAdviseFlag
;
127 IAdviseSink
* sinkInterface
;
131 typedef struct DataCache DataCache
;
134 * Here, I define utility macros to help with the casting of the
136 * There is a version to accommodate all of the VTables implemented
139 #define _ICOM_THIS_From_IDataObject(class,name) class* this = (class*)name
140 #define _ICOM_THIS_From_NDIUnknown(class, name) class* this = (class*)(((char*)name)-sizeof(void*))
141 #define _ICOM_THIS_From_IPersistStorage(class, name) class* this = (class*)(((char*)name)-2*sizeof(void*))
142 #define _ICOM_THIS_From_IViewObject2(class, name) class* this = (class*)(((char*)name)-3*sizeof(void*))
143 #define _ICOM_THIS_From_IOleCache2(class, name) class* this = (class*)(((char*)name)-4*sizeof(void*))
144 #define _ICOM_THIS_From_IOleCacheControl(class, name) class* this = (class*)(((char*)name)-5*sizeof(void*))
147 * Prototypes for the methods of the DataCache class.
149 static DataCache
* DataCache_Construct(REFCLSID clsid
,
150 LPUNKNOWN pUnkOuter
);
151 static void DataCache_Destroy(DataCache
* ptrToDestroy
);
152 static HRESULT
DataCache_ReadPresentationData(DataCache
* this,
154 PresentationDataHeader
* header
);
155 static HRESULT
DataCache_OpenPresStream(DataCache
*this,
158 static HMETAFILE
DataCache_ReadPresMetafile(DataCache
* this,
160 static void DataCache_FireOnViewChange(DataCache
* this,
165 * Prototypes for the methods of the DataCache class
166 * that implement non delegating IUnknown methods.
168 static HRESULT WINAPI
DataCache_NDIUnknown_QueryInterface(
172 static ULONG WINAPI
DataCache_NDIUnknown_AddRef(
174 static ULONG WINAPI
DataCache_NDIUnknown_Release(
178 * Prototypes for the methods of the DataCache class
179 * that implement IDataObject methods.
181 static HRESULT WINAPI
DataCache_IDataObject_QueryInterface(
185 static ULONG WINAPI
DataCache_IDataObject_AddRef(
187 static ULONG WINAPI
DataCache_IDataObject_Release(
189 static HRESULT WINAPI
DataCache_GetData(
191 LPFORMATETC pformatetcIn
,
193 static HRESULT WINAPI
DataCache_GetDataHere(
195 LPFORMATETC pformatetc
,
197 static HRESULT WINAPI
DataCache_QueryGetData(
199 LPFORMATETC pformatetc
);
200 static HRESULT WINAPI
DataCache_GetCanonicalFormatEtc(
202 LPFORMATETC pformatectIn
,
203 LPFORMATETC pformatetcOut
);
204 static HRESULT WINAPI
DataCache_IDataObject_SetData(
206 LPFORMATETC pformatetc
,
209 static HRESULT WINAPI
DataCache_EnumFormatEtc(
212 IEnumFORMATETC
** ppenumFormatEtc
);
213 static HRESULT WINAPI
DataCache_DAdvise(
215 FORMATETC
* pformatetc
,
217 IAdviseSink
* pAdvSink
,
218 DWORD
* pdwConnection
);
219 static HRESULT WINAPI
DataCache_DUnadvise(
222 static HRESULT WINAPI
DataCache_EnumDAdvise(
224 IEnumSTATDATA
** ppenumAdvise
);
227 * Prototypes for the methods of the DataCache class
228 * that implement IPersistStorage methods.
230 static HRESULT WINAPI
DataCache_IPersistStorage_QueryInterface(
231 IPersistStorage
* iface
,
234 static ULONG WINAPI
DataCache_IPersistStorage_AddRef(
235 IPersistStorage
* iface
);
236 static ULONG WINAPI
DataCache_IPersistStorage_Release(
237 IPersistStorage
* iface
);
238 static HRESULT WINAPI
DataCache_GetClassID(
239 IPersistStorage
* iface
,
241 static HRESULT WINAPI
DataCache_IsDirty(
242 IPersistStorage
* iface
);
243 static HRESULT WINAPI
DataCache_InitNew(
244 IPersistStorage
* iface
,
246 static HRESULT WINAPI
DataCache_Load(
247 IPersistStorage
* iface
,
249 static HRESULT WINAPI
DataCache_Save(
250 IPersistStorage
* iface
,
253 static HRESULT WINAPI
DataCache_SaveCompleted(
254 IPersistStorage
* iface
,
256 static HRESULT WINAPI
DataCache_HandsOffStorage(
257 IPersistStorage
* iface
);
260 * Prototypes for the methods of the DataCache class
261 * that implement IViewObject2 methods.
263 static HRESULT WINAPI
DataCache_IViewObject2_QueryInterface(
267 static ULONG WINAPI
DataCache_IViewObject2_AddRef(
268 IViewObject2
* iface
);
269 static ULONG WINAPI
DataCache_IViewObject2_Release(
270 IViewObject2
* iface
);
271 static HRESULT WINAPI
DataCache_Draw(
280 LPCRECTL lprcWBounds
,
281 BOOL (CALLBACK
*pfnContinue
)(ULONG_PTR dwContinue
),
282 ULONG_PTR dwContinue
);
283 static HRESULT WINAPI
DataCache_GetColorSet(
290 LOGPALETTE
** ppColorSet
);
291 static HRESULT WINAPI
DataCache_Freeze(
297 static HRESULT WINAPI
DataCache_Unfreeze(
300 static HRESULT WINAPI
DataCache_SetAdvise(
304 IAdviseSink
* pAdvSink
);
305 static HRESULT WINAPI
DataCache_GetAdvise(
309 IAdviseSink
** ppAdvSink
);
310 static HRESULT WINAPI
DataCache_GetExtent(
318 * Prototypes for the methods of the DataCache class
319 * that implement IOleCache2 methods.
321 static HRESULT WINAPI
DataCache_IOleCache2_QueryInterface(
325 static ULONG WINAPI
DataCache_IOleCache2_AddRef(
327 static ULONG WINAPI
DataCache_IOleCache2_Release(
329 static HRESULT WINAPI
DataCache_Cache(
331 FORMATETC
* pformatetc
,
333 DWORD
* pdwConnection
);
334 static HRESULT WINAPI
DataCache_Uncache(
337 static HRESULT WINAPI
DataCache_EnumCache(
339 IEnumSTATDATA
** ppenumSTATDATA
);
340 static HRESULT WINAPI
DataCache_InitCache(
342 IDataObject
* pDataObject
);
343 static HRESULT WINAPI
DataCache_IOleCache2_SetData(
345 FORMATETC
* pformatetc
,
348 static HRESULT WINAPI
DataCache_UpdateCache(
350 LPDATAOBJECT pDataObject
,
353 static HRESULT WINAPI
DataCache_DiscardCache(
355 DWORD dwDiscardOptions
);
358 * Prototypes for the methods of the DataCache class
359 * that implement IOleCacheControl methods.
361 static HRESULT WINAPI
DataCache_IOleCacheControl_QueryInterface(
362 IOleCacheControl
* iface
,
365 static ULONG WINAPI
DataCache_IOleCacheControl_AddRef(
366 IOleCacheControl
* iface
);
367 static ULONG WINAPI
DataCache_IOleCacheControl_Release(
368 IOleCacheControl
* iface
);
369 static HRESULT WINAPI
DataCache_OnRun(
370 IOleCacheControl
* iface
,
371 LPDATAOBJECT pDataObject
);
372 static HRESULT WINAPI
DataCache_OnStop(
373 IOleCacheControl
* iface
);
376 * Virtual function tables for the DataCache class.
378 static IUnknownVtbl DataCache_NDIUnknown_VTable
=
380 DataCache_NDIUnknown_QueryInterface
,
381 DataCache_NDIUnknown_AddRef
,
382 DataCache_NDIUnknown_Release
385 static IDataObjectVtbl DataCache_IDataObject_VTable
=
387 DataCache_IDataObject_QueryInterface
,
388 DataCache_IDataObject_AddRef
,
389 DataCache_IDataObject_Release
,
391 DataCache_GetDataHere
,
392 DataCache_QueryGetData
,
393 DataCache_GetCanonicalFormatEtc
,
394 DataCache_IDataObject_SetData
,
395 DataCache_EnumFormatEtc
,
398 DataCache_EnumDAdvise
401 static IPersistStorageVtbl DataCache_IPersistStorage_VTable
=
403 DataCache_IPersistStorage_QueryInterface
,
404 DataCache_IPersistStorage_AddRef
,
405 DataCache_IPersistStorage_Release
,
406 DataCache_GetClassID
,
411 DataCache_SaveCompleted
,
412 DataCache_HandsOffStorage
415 static IViewObject2Vtbl DataCache_IViewObject2_VTable
=
417 DataCache_IViewObject2_QueryInterface
,
418 DataCache_IViewObject2_AddRef
,
419 DataCache_IViewObject2_Release
,
421 DataCache_GetColorSet
,
429 static IOleCache2Vtbl DataCache_IOleCache2_VTable
=
431 DataCache_IOleCache2_QueryInterface
,
432 DataCache_IOleCache2_AddRef
,
433 DataCache_IOleCache2_Release
,
438 DataCache_IOleCache2_SetData
,
439 DataCache_UpdateCache
,
440 DataCache_DiscardCache
443 static IOleCacheControlVtbl DataCache_IOleCacheControl_VTable
=
445 DataCache_IOleCacheControl_QueryInterface
,
446 DataCache_IOleCacheControl_AddRef
,
447 DataCache_IOleCacheControl_Release
,
452 /******************************************************************************
453 * CreateDataCache [OLE32.@]
455 HRESULT WINAPI
CreateDataCache(
461 DataCache
* newCache
= NULL
;
464 TRACE("(%s, %p, %s, %p)\n", debugstr_guid(rclsid
), pUnkOuter
, debugstr_guid(riid
), ppvObj
);
475 * If this cache is constructed for aggregation, make sure
476 * the caller is requesting the IUnknown interface.
477 * This is necessary because it's the only time the non-delegating
478 * IUnknown pointer can be returned to the outside.
480 if ( (pUnkOuter
!=NULL
) &&
481 (memcmp(&IID_IUnknown
, riid
, sizeof(IID_IUnknown
)) != 0) )
482 return CLASS_E_NOAGGREGATION
;
485 * Try to construct a new instance of the class.
487 newCache
= DataCache_Construct(rclsid
,
491 return E_OUTOFMEMORY
;
494 * Make sure it supports the interface required by the caller.
496 hr
= IUnknown_QueryInterface((IUnknown
*)&(newCache
->lpvtbl2
), riid
, ppvObj
);
499 * Release the reference obtained in the constructor. If
500 * the QueryInterface was unsuccessful, it will free the class.
502 IUnknown_Release((IUnknown
*)&(newCache
->lpvtbl2
));
507 /*********************************************************
508 * Method implementation for DataCache class.
510 static DataCache
* DataCache_Construct(
514 DataCache
* newObject
= 0;
517 * Allocate space for the object.
519 newObject
= HeapAlloc(GetProcessHeap(), 0, sizeof(DataCache
));
525 * Initialize the virtual function table.
527 newObject
->lpvtbl1
= &DataCache_IDataObject_VTable
;
528 newObject
->lpvtbl2
= &DataCache_NDIUnknown_VTable
;
529 newObject
->lpvtbl3
= &DataCache_IPersistStorage_VTable
;
530 newObject
->lpvtbl4
= &DataCache_IViewObject2_VTable
;
531 newObject
->lpvtbl5
= &DataCache_IOleCache2_VTable
;
532 newObject
->lpvtbl6
= &DataCache_IOleCacheControl_VTable
;
535 * Start with one reference count. The caller of this function
536 * must release the interface pointer when it is done.
541 * Initialize the outer unknown
542 * We don't keep a reference on the outer unknown since, the way
543 * aggregation works, our lifetime is at least as large as it's
547 pUnkOuter
= (IUnknown
*)&(newObject
->lpvtbl2
);
549 newObject
->outerUnknown
= pUnkOuter
;
552 * Initialize the other members of the structure.
554 newObject
->presentationStorage
= NULL
;
555 newObject
->sinkAspects
= 0;
556 newObject
->sinkAdviseFlag
= 0;
557 newObject
->sinkInterface
= 0;
562 static void DataCache_Destroy(
563 DataCache
* ptrToDestroy
)
567 if (ptrToDestroy
->sinkInterface
!= NULL
)
569 IAdviseSink_Release(ptrToDestroy
->sinkInterface
);
570 ptrToDestroy
->sinkInterface
= NULL
;
573 if (ptrToDestroy
->presentationStorage
!= NULL
)
575 IStorage_Release(ptrToDestroy
->presentationStorage
);
576 ptrToDestroy
->presentationStorage
= NULL
;
580 * Free the datacache pointer.
582 HeapFree(GetProcessHeap(), 0, ptrToDestroy
);
585 /************************************************************************
586 * DataCache_ReadPresentationData
588 * This method will read information for the requested presentation
589 * into the given structure.
592 * this - Pointer to the DataCache object
593 * drawAspect - The aspect of the object that we wish to draw.
594 * header - The structure containing information about this
595 * aspect of the object.
597 static HRESULT
DataCache_ReadPresentationData(
600 PresentationDataHeader
* header
)
602 IStream
* presStream
= NULL
;
606 * Open the presentation stream.
608 hres
= DataCache_OpenPresStream(
623 sizeof(PresentationDataHeader
),
629 IStream_Release(presStream
);
632 * We don't want to propagate any other error
633 * code than a failure.
641 /************************************************************************
642 * DataCache_FireOnViewChange
644 * This method will fire an OnViewChange notification to the advise
645 * sink registered with the datacache.
647 * See IAdviseSink::OnViewChange for more details.
649 static void DataCache_FireOnViewChange(
654 TRACE("(%p, %lx, %ld)\n", this, aspect
, lindex
);
657 * The sink supplies a filter when it registers
658 * we make sure we only send the notifications when that
661 if ((this->sinkAspects
& aspect
) != 0)
663 if (this->sinkInterface
!= NULL
)
665 IAdviseSink_OnViewChange(this->sinkInterface
,
670 * Some sinks want to be unregistered automatically when
671 * the first notification goes out.
673 if ( (this->sinkAdviseFlag
& ADVF_ONLYONCE
) != 0)
675 IAdviseSink_Release(this->sinkInterface
);
677 this->sinkInterface
= NULL
;
678 this->sinkAspects
= 0;
679 this->sinkAdviseFlag
= 0;
685 /* Helper for DataCache_OpenPresStream */
686 static BOOL
DataCache_IsPresentationStream(const STATSTG
*elem
)
688 /* The presentation streams have names of the form "\002OlePresXXX",
689 * where XXX goes from 000 to 999. */
690 static const WCHAR OlePres
[] = { 2,'O','l','e','P','r','e','s' };
692 LPCWSTR name
= elem
->pwcsName
;
694 return (elem
->type
== STGTY_STREAM
)
695 && (elem
->cbSize
.u
.LowPart
>= sizeof(PresentationDataHeader
))
696 && (strlenW(name
) == 11)
697 && (strncmpW(name
, OlePres
, 8) == 0)
698 && (name
[8] >= '0') && (name
[8] <= '9')
699 && (name
[9] >= '0') && (name
[9] <= '9')
700 && (name
[10] >= '0') && (name
[10] <= '9');
703 /************************************************************************
704 * DataCache_OpenPresStream
706 * This method will find the stream for the given presentation. It makes
707 * no attempt at fallback.
710 * this - Pointer to the DataCache object
711 * drawAspect - The aspect of the object that we wish to draw.
712 * pStm - A returned stream. It points to the beginning of the
713 * - presentation data, including the header.
716 * S_OK The requested stream has been opened.
717 * OLE_E_BLANK The requested stream could not be found.
718 * Quite a few others I'm too lazy to map correctly.
721 * Algorithm: Scan the elements of the presentation storage, looking
722 * for presentation streams. For each presentation stream,
723 * load the header and check to see if the aspect maches.
725 * If a fallback is desired, just opening the first presentation stream
728 static HRESULT
DataCache_OpenPresStream(
737 if (!ppStm
) return E_POINTER
;
739 hr
= IStorage_EnumElements(this->presentationStorage
, 0, NULL
, 0, &pEnum
);
740 if (FAILED(hr
)) return hr
;
742 while ((hr
= IEnumSTATSTG_Next(pEnum
, 1, &elem
, NULL
)) == S_OK
)
744 if (DataCache_IsPresentationStream(&elem
))
748 hr
= IStorage_OpenStream(this->presentationStorage
, elem
.pwcsName
,
749 NULL
, STGM_READ
| STGM_SHARE_EXCLUSIVE
, 0,
753 PresentationDataHeader header
;
756 hr
= IStream_Read(pStm
, &header
, sizeof(header
), &actual_read
);
758 /* can't use SUCCEEDED(hr): S_FALSE counts as an error */
759 if (hr
== S_OK
&& actual_read
== sizeof(header
)
760 && header
.dvAspect
== drawAspect
)
762 /* Rewind the stream before returning it. */
763 LARGE_INTEGER offset
;
764 offset
.u
.LowPart
= 0;
765 offset
.u
.HighPart
= 0;
766 IStream_Seek(pStm
, offset
, STREAM_SEEK_SET
, NULL
);
770 CoTaskMemFree(elem
.pwcsName
);
771 IEnumSTATSTG_Release(pEnum
);
776 IStream_Release(pStm
);
780 CoTaskMemFree(elem
.pwcsName
);
783 IEnumSTATSTG_Release(pEnum
);
785 return (hr
== S_FALSE
? OLE_E_BLANK
: hr
);
788 /************************************************************************
789 * DataCache_ReadPresentationData
791 * This method will read information for the requested presentation
792 * into the given structure.
795 * this - Pointer to the DataCache object
796 * drawAspect - The aspect of the object that we wish to draw.
799 * This method returns a metafile handle if it is successful.
800 * it will return 0 if not.
802 static HMETAFILE
DataCache_ReadPresMetafile(
806 LARGE_INTEGER offset
;
807 IStream
* presStream
= NULL
;
811 HMETAFILE newMetafile
= 0;
814 * Open the presentation stream.
816 hres
= DataCache_OpenPresStream(
822 return (HMETAFILE
)hres
;
825 * Get the size of the stream.
827 hres
= IStream_Stat(presStream
,
834 offset
.u
.HighPart
= 0;
835 offset
.u
.LowPart
= sizeof(PresentationDataHeader
);
843 streamInfo
.cbSize
.u
.LowPart
-= offset
.u
.LowPart
;
846 * Allocate a buffer for the metafile bits.
848 metafileBits
= HeapAlloc(GetProcessHeap(),
850 streamInfo
.cbSize
.u
.LowPart
);
853 * Read the metafile bits.
858 streamInfo
.cbSize
.u
.LowPart
,
862 * Create a metafile with those bits.
866 newMetafile
= SetMetaFileBitsEx(streamInfo
.cbSize
.u
.LowPart
, metafileBits
);
872 HeapFree(GetProcessHeap(), 0, metafileBits
);
873 IStream_Release(presStream
);
881 /*********************************************************
882 * Method implementation for the non delegating IUnknown
883 * part of the DataCache class.
886 /************************************************************************
887 * DataCache_NDIUnknown_QueryInterface (IUnknown)
889 * See Windows documentation for more details on IUnknown methods.
891 * This version of QueryInterface will not delegate it's implementation
892 * to the outer unknown.
894 static HRESULT WINAPI
DataCache_NDIUnknown_QueryInterface(
899 _ICOM_THIS_From_NDIUnknown(DataCache
, iface
);
902 * Perform a sanity check on the parameters.
904 if ( (this==0) || (ppvObject
==0) )
908 * Initialize the return parameter.
913 * Compare the riid with the interface IDs implemented by this object.
915 if (memcmp(&IID_IUnknown
, riid
, sizeof(IID_IUnknown
)) == 0)
919 else if (memcmp(&IID_IDataObject
, riid
, sizeof(IID_IDataObject
)) == 0)
921 *ppvObject
= (IDataObject
*)&(this->lpvtbl1
);
923 else if ( (memcmp(&IID_IPersistStorage
, riid
, sizeof(IID_IPersistStorage
)) == 0) ||
924 (memcmp(&IID_IPersist
, riid
, sizeof(IID_IPersist
)) == 0) )
926 *ppvObject
= (IPersistStorage
*)&(this->lpvtbl3
);
928 else if ( (memcmp(&IID_IViewObject
, riid
, sizeof(IID_IViewObject
)) == 0) ||
929 (memcmp(&IID_IViewObject2
, riid
, sizeof(IID_IViewObject2
)) == 0) )
931 *ppvObject
= (IViewObject2
*)&(this->lpvtbl4
);
933 else if ( (memcmp(&IID_IOleCache
, riid
, sizeof(IID_IOleCache
)) == 0) ||
934 (memcmp(&IID_IOleCache2
, riid
, sizeof(IID_IOleCache2
)) == 0) )
936 *ppvObject
= (IOleCache2
*)&(this->lpvtbl5
);
938 else if (memcmp(&IID_IOleCacheControl
, riid
, sizeof(IID_IOleCacheControl
)) == 0)
940 *ppvObject
= (IOleCacheControl
*)&(this->lpvtbl6
);
944 * Check that we obtained an interface.
948 WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid
));
949 return E_NOINTERFACE
;
953 * Query Interface always increases the reference count by one when it is
956 IUnknown_AddRef((IUnknown
*)*ppvObject
);
961 /************************************************************************
962 * DataCache_NDIUnknown_AddRef (IUnknown)
964 * See Windows documentation for more details on IUnknown methods.
966 * This version of QueryInterface will not delegate it's implementation
967 * to the outer unknown.
969 static ULONG WINAPI
DataCache_NDIUnknown_AddRef(
972 _ICOM_THIS_From_NDIUnknown(DataCache
, iface
);
973 return InterlockedIncrement(&this->ref
);
976 /************************************************************************
977 * DataCache_NDIUnknown_Release (IUnknown)
979 * See Windows documentation for more details on IUnknown methods.
981 * This version of QueryInterface will not delegate it's implementation
982 * to the outer unknown.
984 static ULONG WINAPI
DataCache_NDIUnknown_Release(
987 _ICOM_THIS_From_NDIUnknown(DataCache
, iface
);
991 * Decrease the reference count on this object.
993 ref
= InterlockedDecrement(&this->ref
);
996 * If the reference count goes down to 0, perform suicide.
998 if (ref
== 0) DataCache_Destroy(this);
1003 /*********************************************************
1004 * Method implementation for the IDataObject
1005 * part of the DataCache class.
1008 /************************************************************************
1009 * DataCache_IDataObject_QueryInterface (IUnknown)
1011 * See Windows documentation for more details on IUnknown methods.
1013 static HRESULT WINAPI
DataCache_IDataObject_QueryInterface(
1018 _ICOM_THIS_From_IDataObject(DataCache
, iface
);
1020 return IUnknown_QueryInterface(this->outerUnknown
, riid
, ppvObject
);
1023 /************************************************************************
1024 * DataCache_IDataObject_AddRef (IUnknown)
1026 * See Windows documentation for more details on IUnknown methods.
1028 static ULONG WINAPI
DataCache_IDataObject_AddRef(
1031 _ICOM_THIS_From_IDataObject(DataCache
, iface
);
1033 return IUnknown_AddRef(this->outerUnknown
);
1036 /************************************************************************
1037 * DataCache_IDataObject_Release (IUnknown)
1039 * See Windows documentation for more details on IUnknown methods.
1041 static ULONG WINAPI
DataCache_IDataObject_Release(
1044 _ICOM_THIS_From_IDataObject(DataCache
, iface
);
1046 return IUnknown_Release(this->outerUnknown
);
1049 /************************************************************************
1052 * Get Data from a source dataobject using format pformatetcIn->cfFormat
1053 * See Windows documentation for more details on GetData.
1054 * TODO: Currently only CF_METAFILEPICT is implemented
1056 static HRESULT WINAPI
DataCache_GetData(
1058 LPFORMATETC pformatetcIn
,
1062 HRESULT hrRet
= E_UNEXPECTED
;
1063 IPersistStorage
*pPersistStorage
= 0;
1064 IStorage
*pStorage
= 0;
1065 IStream
*pStream
= 0;
1066 OLECHAR name
[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
1067 HGLOBAL hGlobalMF
= 0;
1069 PresentationDataHeader pdh
;
1070 METAFILEPICT
*mfPict
;
1071 HMETAFILE hMetaFile
= 0;
1073 if (pformatetcIn
->cfFormat
== CF_METAFILEPICT
)
1075 /* Get the Persist Storage */
1077 hr
= IDataObject_QueryInterface(iface
, &IID_IPersistStorage
, (void**)&pPersistStorage
);
1082 /* Create a doc file to copy the doc to a storage */
1084 hr
= StgCreateDocfile(NULL
, STGM_CREATE
| STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, &pStorage
);
1089 /* Save it to storage */
1091 hr
= OleSave(pPersistStorage
, pStorage
, FALSE
);
1096 /* Open the Presentation data srteam */
1098 hr
= IStorage_OpenStream(pStorage
, name
, 0, STGM_CREATE
|STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, 0, &pStream
);
1103 /* Read the presentation header */
1105 hr
= IStream_Read(pStream
, &pdh
, sizeof(PresentationDataHeader
), NULL
);
1110 mfBits
= HeapAlloc(GetProcessHeap(), 0, pdh
.dwSize
);
1112 /* Read the Metafile bits */
1114 hr
= IStream_Read(pStream
, mfBits
, pdh
.dwSize
, NULL
);
1119 /* Create the metafile and place it in the STGMEDIUM structure */
1121 hMetaFile
= SetMetaFileBitsEx(pdh
.dwSize
, mfBits
);
1123 hGlobalMF
= GlobalAlloc(GMEM_SHARE
|GMEM_MOVEABLE
, sizeof(METAFILEPICT
));
1124 mfPict
= (METAFILEPICT
*)GlobalLock(hGlobalMF
);
1125 mfPict
->hMF
= hMetaFile
;
1127 GlobalUnlock(hGlobalMF
);
1129 pmedium
->u
.hGlobal
= hGlobalMF
;
1130 pmedium
->tymed
= TYMED_MFPICT
;
1136 HeapFree(GetProcessHeap(), 0, mfBits
);
1139 IStream_Release(pStream
);
1142 IStorage_Release(pStorage
);
1144 if (pPersistStorage
)
1145 IPersistStorage_Release(pPersistStorage
);
1150 /* TODO: Other formats are not implemented */
1155 static HRESULT WINAPI
DataCache_GetDataHere(
1157 LPFORMATETC pformatetc
,
1164 static HRESULT WINAPI
DataCache_QueryGetData(
1166 LPFORMATETC pformatetc
)
1172 /************************************************************************
1173 * DataCache_EnumFormatEtc (IDataObject)
1175 * The data cache doesn't implement this method.
1177 * See Windows documentation for more details on IDataObject methods.
1179 static HRESULT WINAPI
DataCache_GetCanonicalFormatEtc(
1181 LPFORMATETC pformatectIn
,
1182 LPFORMATETC pformatetcOut
)
1188 /************************************************************************
1189 * DataCache_IDataObject_SetData (IDataObject)
1191 * This method is delegated to the IOleCache2 implementation.
1193 * See Windows documentation for more details on IDataObject methods.
1195 static HRESULT WINAPI
DataCache_IDataObject_SetData(
1197 LPFORMATETC pformatetc
,
1201 IOleCache2
* oleCache
= NULL
;
1204 TRACE("(%p, %p, %p, %d)\n", iface
, pformatetc
, pmedium
, fRelease
);
1206 hres
= IDataObject_QueryInterface(iface
, &IID_IOleCache2
, (void**)&oleCache
);
1209 return E_UNEXPECTED
;
1211 hres
= IOleCache2_SetData(oleCache
, pformatetc
, pmedium
, fRelease
);
1213 IOleCache2_Release(oleCache
);
1218 /************************************************************************
1219 * DataCache_EnumFormatEtc (IDataObject)
1221 * The data cache doesn't implement this method.
1223 * See Windows documentation for more details on IDataObject methods.
1225 static HRESULT WINAPI
DataCache_EnumFormatEtc(
1228 IEnumFORMATETC
** ppenumFormatEtc
)
1234 /************************************************************************
1235 * DataCache_DAdvise (IDataObject)
1237 * The data cache doesn't support connections.
1239 * See Windows documentation for more details on IDataObject methods.
1241 static HRESULT WINAPI
DataCache_DAdvise(
1243 FORMATETC
* pformatetc
,
1245 IAdviseSink
* pAdvSink
,
1246 DWORD
* pdwConnection
)
1249 return OLE_E_ADVISENOTSUPPORTED
;
1252 /************************************************************************
1253 * DataCache_DUnadvise (IDataObject)
1255 * The data cache doesn't support connections.
1257 * See Windows documentation for more details on IDataObject methods.
1259 static HRESULT WINAPI
DataCache_DUnadvise(
1264 return OLE_E_NOCONNECTION
;
1267 /************************************************************************
1268 * DataCache_EnumDAdvise (IDataObject)
1270 * The data cache doesn't support connections.
1272 * See Windows documentation for more details on IDataObject methods.
1274 static HRESULT WINAPI
DataCache_EnumDAdvise(
1276 IEnumSTATDATA
** ppenumAdvise
)
1279 return OLE_E_ADVISENOTSUPPORTED
;
1282 /*********************************************************
1283 * Method implementation for the IDataObject
1284 * part of the DataCache class.
1287 /************************************************************************
1288 * DataCache_IPersistStorage_QueryInterface (IUnknown)
1290 * See Windows documentation for more details on IUnknown methods.
1292 static HRESULT WINAPI
DataCache_IPersistStorage_QueryInterface(
1293 IPersistStorage
* iface
,
1297 _ICOM_THIS_From_IPersistStorage(DataCache
, iface
);
1299 return IUnknown_QueryInterface(this->outerUnknown
, riid
, ppvObject
);
1302 /************************************************************************
1303 * DataCache_IPersistStorage_AddRef (IUnknown)
1305 * See Windows documentation for more details on IUnknown methods.
1307 static ULONG WINAPI
DataCache_IPersistStorage_AddRef(
1308 IPersistStorage
* iface
)
1310 _ICOM_THIS_From_IPersistStorage(DataCache
, iface
);
1312 return IUnknown_AddRef(this->outerUnknown
);
1315 /************************************************************************
1316 * DataCache_IPersistStorage_Release (IUnknown)
1318 * See Windows documentation for more details on IUnknown methods.
1320 static ULONG WINAPI
DataCache_IPersistStorage_Release(
1321 IPersistStorage
* iface
)
1323 _ICOM_THIS_From_IPersistStorage(DataCache
, iface
);
1325 return IUnknown_Release(this->outerUnknown
);
1328 /************************************************************************
1329 * DataCache_GetClassID (IPersistStorage)
1331 * The data cache doesn't implement this method.
1333 * See Windows documentation for more details on IPersistStorage methods.
1335 static HRESULT WINAPI
DataCache_GetClassID(
1336 IPersistStorage
* iface
,
1339 TRACE("(%p, %p)\n", iface
, pClassID
);
1343 /************************************************************************
1344 * DataCache_IsDirty (IPersistStorage)
1346 * Until we actully connect to a running object and retrieve new
1347 * information to it, we never get dirty.
1349 * See Windows documentation for more details on IPersistStorage methods.
1351 static HRESULT WINAPI
DataCache_IsDirty(
1352 IPersistStorage
* iface
)
1354 TRACE("(%p)\n", iface
);
1359 /************************************************************************
1360 * DataCache_InitNew (IPersistStorage)
1362 * The data cache implementation of IPersistStorage_InitNew simply stores
1363 * the storage pointer.
1365 * See Windows documentation for more details on IPersistStorage methods.
1367 static HRESULT WINAPI
DataCache_InitNew(
1368 IPersistStorage
* iface
,
1371 TRACE("(%p, %p)\n", iface
, pStg
);
1373 return DataCache_Load(iface
, pStg
);
1376 /************************************************************************
1377 * DataCache_Load (IPersistStorage)
1379 * The data cache implementation of IPersistStorage_Load doesn't
1380 * actually load anything. Instead, it holds on to the storage pointer
1381 * and it will load the presentation information when the
1382 * IDataObject_GetData or IViewObject2_Draw methods are called.
1384 * See Windows documentation for more details on IPersistStorage methods.
1386 static HRESULT WINAPI
DataCache_Load(
1387 IPersistStorage
* iface
,
1390 _ICOM_THIS_From_IPersistStorage(DataCache
, iface
);
1392 TRACE("(%p, %p)\n", iface
, pStg
);
1394 if (this->presentationStorage
!= NULL
)
1396 IStorage_Release(this->presentationStorage
);
1399 this->presentationStorage
= pStg
;
1401 if (this->presentationStorage
!= NULL
)
1403 IStorage_AddRef(this->presentationStorage
);
1408 /************************************************************************
1409 * DataCache_Save (IPersistStorage)
1411 * Until we actully connect to a running object and retrieve new
1412 * information to it, we never have to save anything. However, it is
1413 * our responsability to copy the information when saving to a new
1416 * See Windows documentation for more details on IPersistStorage methods.
1418 static HRESULT WINAPI
DataCache_Save(
1419 IPersistStorage
* iface
,
1423 _ICOM_THIS_From_IPersistStorage(DataCache
, iface
);
1425 TRACE("(%p, %p, %d)\n", iface
, pStg
, fSameAsLoad
);
1427 if ( (!fSameAsLoad
) &&
1428 (this->presentationStorage
!=NULL
) )
1430 return IStorage_CopyTo(this->presentationStorage
,
1440 /************************************************************************
1441 * DataCache_SaveCompleted (IPersistStorage)
1443 * This method is called to tell the cache to release the storage
1444 * pointer it's currentlu holding.
1446 * See Windows documentation for more details on IPersistStorage methods.
1448 static HRESULT WINAPI
DataCache_SaveCompleted(
1449 IPersistStorage
* iface
,
1452 TRACE("(%p, %p)\n", iface
, pStgNew
);
1457 * First, make sure we get our hands off any storage we have.
1460 DataCache_HandsOffStorage(iface
);
1463 * Then, attach to the new storage.
1466 DataCache_Load(iface
, pStgNew
);
1472 /************************************************************************
1473 * DataCache_HandsOffStorage (IPersistStorage)
1475 * This method is called to tell the cache to release the storage
1476 * pointer it's currentlu holding.
1478 * See Windows documentation for more details on IPersistStorage methods.
1480 static HRESULT WINAPI
DataCache_HandsOffStorage(
1481 IPersistStorage
* iface
)
1483 _ICOM_THIS_From_IPersistStorage(DataCache
, iface
);
1485 TRACE("(%p)\n", iface
);
1487 if (this->presentationStorage
!= NULL
)
1489 IStorage_Release(this->presentationStorage
);
1490 this->presentationStorage
= NULL
;
1496 /*********************************************************
1497 * Method implementation for the IViewObject2
1498 * part of the DataCache class.
1501 /************************************************************************
1502 * DataCache_IViewObject2_QueryInterface (IUnknown)
1504 * See Windows documentation for more details on IUnknown methods.
1506 static HRESULT WINAPI
DataCache_IViewObject2_QueryInterface(
1507 IViewObject2
* iface
,
1511 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1513 return IUnknown_QueryInterface(this->outerUnknown
, riid
, ppvObject
);
1516 /************************************************************************
1517 * DataCache_IViewObject2_AddRef (IUnknown)
1519 * See Windows documentation for more details on IUnknown methods.
1521 static ULONG WINAPI
DataCache_IViewObject2_AddRef(
1522 IViewObject2
* iface
)
1524 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1526 return IUnknown_AddRef(this->outerUnknown
);
1529 /************************************************************************
1530 * DataCache_IViewObject2_Release (IUnknown)
1532 * See Windows documentation for more details on IUnknown methods.
1534 static ULONG WINAPI
DataCache_IViewObject2_Release(
1535 IViewObject2
* iface
)
1537 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1539 return IUnknown_Release(this->outerUnknown
);
1542 /************************************************************************
1543 * DataCache_Draw (IViewObject2)
1545 * This method will draw the cached representation of the object
1546 * to the given device context.
1548 * See Windows documentation for more details on IViewObject2 methods.
1550 static HRESULT WINAPI
DataCache_Draw(
1551 IViewObject2
* iface
,
1555 DVTARGETDEVICE
* ptd
,
1558 LPCRECTL lprcBounds
,
1559 LPCRECTL lprcWBounds
,
1560 BOOL (CALLBACK
*pfnContinue
)(ULONG_PTR dwContinue
),
1561 ULONG_PTR dwContinue
)
1563 PresentationDataHeader presData
;
1564 HMETAFILE presMetafile
= 0;
1567 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1569 TRACE("(%p, %lx, %ld, %p, %p, %p, %p, %p, %p, %lx)\n",
1584 if (lprcBounds
==NULL
)
1585 return E_INVALIDARG
;
1588 * First, we need to retrieve the dimensions of the
1589 * image in the metafile.
1591 hres
= DataCache_ReadPresentationData(this,
1599 * Then, we can extract the metafile itself from the cached
1602 * FIXME Unless it isn't a metafile. I think it could be any CF_XXX type,
1603 * particularly CF_DIB.
1605 presMetafile
= DataCache_ReadPresMetafile(this,
1609 * If we have a metafile, just draw baby...
1610 * We have to be careful not to modify the state of the
1613 if (presMetafile
!=0)
1615 INT prevMapMode
= SetMapMode(hdcDraw
, MM_ANISOTROPIC
);
1617 SIZE oldViewportExt
;
1618 POINT oldViewportOrg
;
1620 SetWindowExtEx(hdcDraw
,
1621 presData
.dwObjectExtentX
,
1622 presData
.dwObjectExtentY
,
1625 SetViewportExtEx(hdcDraw
,
1626 lprcBounds
->right
- lprcBounds
->left
,
1627 lprcBounds
->bottom
- lprcBounds
->top
,
1630 SetViewportOrgEx(hdcDraw
,
1635 PlayMetaFile(hdcDraw
, presMetafile
);
1637 SetWindowExtEx(hdcDraw
,
1642 SetViewportExtEx(hdcDraw
,
1647 SetViewportOrgEx(hdcDraw
,
1652 SetMapMode(hdcDraw
, prevMapMode
);
1654 DeleteMetaFile(presMetafile
);
1660 static HRESULT WINAPI
DataCache_GetColorSet(
1661 IViewObject2
* iface
,
1665 DVTARGETDEVICE
* ptd
,
1666 HDC hicTargetDevice
,
1667 LOGPALETTE
** ppColorSet
)
1673 static HRESULT WINAPI
DataCache_Freeze(
1674 IViewObject2
* iface
,
1684 static HRESULT WINAPI
DataCache_Unfreeze(
1685 IViewObject2
* iface
,
1692 /************************************************************************
1693 * DataCache_SetAdvise (IViewObject2)
1695 * This sets-up an advisory sink with the data cache. When the object's
1696 * view changes, this sink is called.
1698 * See Windows documentation for more details on IViewObject2 methods.
1700 static HRESULT WINAPI
DataCache_SetAdvise(
1701 IViewObject2
* iface
,
1704 IAdviseSink
* pAdvSink
)
1706 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1708 TRACE("(%p, %lx, %lx, %p)\n", iface
, aspects
, advf
, pAdvSink
);
1711 * A call to this function removes the previous sink
1713 if (this->sinkInterface
!= NULL
)
1715 IAdviseSink_Release(this->sinkInterface
);
1716 this->sinkInterface
= NULL
;
1717 this->sinkAspects
= 0;
1718 this->sinkAdviseFlag
= 0;
1722 * Now, setup the new one.
1726 this->sinkInterface
= pAdvSink
;
1727 this->sinkAspects
= aspects
;
1728 this->sinkAdviseFlag
= advf
;
1730 IAdviseSink_AddRef(this->sinkInterface
);
1734 * When the ADVF_PRIMEFIRST flag is set, we have to advise the
1737 if (advf
& ADVF_PRIMEFIRST
)
1739 DataCache_FireOnViewChange(this,
1747 /************************************************************************
1748 * DataCache_GetAdvise (IViewObject2)
1750 * This method queries the current state of the advise sink
1751 * installed on the data cache.
1753 * See Windows documentation for more details on IViewObject2 methods.
1755 static HRESULT WINAPI
DataCache_GetAdvise(
1756 IViewObject2
* iface
,
1759 IAdviseSink
** ppAdvSink
)
1761 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1763 TRACE("(%p, %p, %p, %p)\n", iface
, pAspects
, pAdvf
, ppAdvSink
);
1766 * Just copy all the requested values.
1769 *pAspects
= this->sinkAspects
;
1772 *pAdvf
= this->sinkAdviseFlag
;
1774 if (ppAdvSink
!=NULL
)
1776 IAdviseSink_QueryInterface(this->sinkInterface
,
1784 /************************************************************************
1785 * DataCache_GetExtent (IViewObject2)
1787 * This method retrieves the "natural" size of this cached object.
1789 * See Windows documentation for more details on IViewObject2 methods.
1791 static HRESULT WINAPI
DataCache_GetExtent(
1792 IViewObject2
* iface
,
1795 DVTARGETDEVICE
* ptd
,
1798 PresentationDataHeader presData
;
1799 HRESULT hres
= E_FAIL
;
1801 _ICOM_THIS_From_IViewObject2(DataCache
, iface
);
1803 TRACE("(%p, %lx, %ld, %p, %p)\n",
1804 iface
, dwDrawAspect
, lindex
, ptd
, lpsizel
);
1813 * Initialize the out parameter.
1819 * This flag should be set to -1.
1822 FIXME("Unimplemented flag lindex = %ld\n", lindex
);
1825 * Right now, we support only the callback from
1826 * the default handler.
1829 FIXME("Unimplemented ptd = %p\n", ptd
);
1832 * Get the presentation information from the
1835 hres
= DataCache_ReadPresentationData(this,
1839 if (SUCCEEDED(hres
))
1841 lpsizel
->cx
= presData
.dwObjectExtentX
;
1842 lpsizel
->cy
= presData
.dwObjectExtentY
;
1846 * This method returns OLE_E_BLANK when it fails.
1855 /*********************************************************
1856 * Method implementation for the IOleCache2
1857 * part of the DataCache class.
1860 /************************************************************************
1861 * DataCache_IOleCache2_QueryInterface (IUnknown)
1863 * See Windows documentation for more details on IUnknown methods.
1865 static HRESULT WINAPI
DataCache_IOleCache2_QueryInterface(
1870 _ICOM_THIS_From_IOleCache2(DataCache
, iface
);
1872 return IUnknown_QueryInterface(this->outerUnknown
, riid
, ppvObject
);
1875 /************************************************************************
1876 * DataCache_IOleCache2_AddRef (IUnknown)
1878 * See Windows documentation for more details on IUnknown methods.
1880 static ULONG WINAPI
DataCache_IOleCache2_AddRef(
1883 _ICOM_THIS_From_IOleCache2(DataCache
, iface
);
1885 return IUnknown_AddRef(this->outerUnknown
);
1888 /************************************************************************
1889 * DataCache_IOleCache2_Release (IUnknown)
1891 * See Windows documentation for more details on IUnknown methods.
1893 static ULONG WINAPI
DataCache_IOleCache2_Release(
1896 _ICOM_THIS_From_IOleCache2(DataCache
, iface
);
1898 return IUnknown_Release(this->outerUnknown
);
1901 static HRESULT WINAPI
DataCache_Cache(
1903 FORMATETC
* pformatetc
,
1905 DWORD
* pdwConnection
)
1911 static HRESULT WINAPI
DataCache_Uncache(
1919 static HRESULT WINAPI
DataCache_EnumCache(
1921 IEnumSTATDATA
** ppenumSTATDATA
)
1927 static HRESULT WINAPI
DataCache_InitCache(
1929 IDataObject
* pDataObject
)
1935 static HRESULT WINAPI
DataCache_IOleCache2_SetData(
1937 FORMATETC
* pformatetc
,
1945 static HRESULT WINAPI
DataCache_UpdateCache(
1947 LPDATAOBJECT pDataObject
,
1955 static HRESULT WINAPI
DataCache_DiscardCache(
1957 DWORD dwDiscardOptions
)
1964 /*********************************************************
1965 * Method implementation for the IOleCacheControl
1966 * part of the DataCache class.
1969 /************************************************************************
1970 * DataCache_IOleCacheControl_QueryInterface (IUnknown)
1972 * See Windows documentation for more details on IUnknown methods.
1974 static HRESULT WINAPI
DataCache_IOleCacheControl_QueryInterface(
1975 IOleCacheControl
* iface
,
1979 _ICOM_THIS_From_IOleCacheControl(DataCache
, iface
);
1981 return IUnknown_QueryInterface(this->outerUnknown
, riid
, ppvObject
);
1984 /************************************************************************
1985 * DataCache_IOleCacheControl_AddRef (IUnknown)
1987 * See Windows documentation for more details on IUnknown methods.
1989 static ULONG WINAPI
DataCache_IOleCacheControl_AddRef(
1990 IOleCacheControl
* iface
)
1992 _ICOM_THIS_From_IOleCacheControl(DataCache
, iface
);
1994 return IUnknown_AddRef(this->outerUnknown
);
1997 /************************************************************************
1998 * DataCache_IOleCacheControl_Release (IUnknown)
2000 * See Windows documentation for more details on IUnknown methods.
2002 static ULONG WINAPI
DataCache_IOleCacheControl_Release(
2003 IOleCacheControl
* iface
)
2005 _ICOM_THIS_From_IOleCacheControl(DataCache
, iface
);
2007 return IUnknown_Release(this->outerUnknown
);
2010 static HRESULT WINAPI
DataCache_OnRun(
2011 IOleCacheControl
* iface
,
2012 LPDATAOBJECT pDataObject
)
2018 static HRESULT WINAPI
DataCache_OnStop(
2019 IOleCacheControl
* iface
)