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 const IDataObjectVtbl
* lpVtbl
;
97 const IUnknownVtbl
* lpvtblNDIUnknown
;
98 const IPersistStorageVtbl
* lpvtblIPersistStorage
;
99 const IViewObject2Vtbl
* lpvtblIViewObject
;
100 const IOleCache2Vtbl
* lpvtblIOleCache2
;
101 const IOleCacheControlVtbl
* lpvtblIOleCacheControl
;
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
140 static inline DataCache
*impl_from_IDataObject( IDataObject
*iface
)
142 return (DataCache
*)((char*)iface
- FIELD_OFFSET(DataCache
, lpVtbl
));
145 static inline DataCache
*impl_from_NDIUnknown( IUnknown
*iface
)
147 return (DataCache
*)((char*)iface
- FIELD_OFFSET(DataCache
, lpvtblNDIUnknown
));
150 static inline DataCache
*impl_from_IPersistStorage( IPersistStorage
*iface
)
152 return (DataCache
*)((char*)iface
- FIELD_OFFSET(DataCache
, lpvtblIPersistStorage
));
155 static inline DataCache
*impl_from_IViewObject2( IViewObject2
*iface
)
157 return (DataCache
*)((char*)iface
- FIELD_OFFSET(DataCache
, lpvtblIViewObject
));
160 static inline DataCache
*impl_from_IOleCache2( IOleCache2
*iface
)
162 return (DataCache
*)((char*)iface
- FIELD_OFFSET(DataCache
, lpvtblIOleCache2
));
165 static inline DataCache
*impl_from_IOleCacheControl( IOleCacheControl
*iface
)
167 return (DataCache
*)((char*)iface
- FIELD_OFFSET(DataCache
, lpvtblIOleCacheControl
));
172 * Prototypes for the methods of the DataCache class.
174 static DataCache
* DataCache_Construct(REFCLSID clsid
,
175 LPUNKNOWN pUnkOuter
);
176 static HRESULT
DataCache_OpenPresStream(DataCache
*this,
180 static void DataCache_Destroy(
181 DataCache
* ptrToDestroy
)
185 if (ptrToDestroy
->sinkInterface
!= NULL
)
187 IAdviseSink_Release(ptrToDestroy
->sinkInterface
);
188 ptrToDestroy
->sinkInterface
= NULL
;
191 if (ptrToDestroy
->presentationStorage
!= NULL
)
193 IStorage_Release(ptrToDestroy
->presentationStorage
);
194 ptrToDestroy
->presentationStorage
= NULL
;
198 * Free the datacache pointer.
200 HeapFree(GetProcessHeap(), 0, ptrToDestroy
);
203 /************************************************************************
204 * DataCache_ReadPresentationData
206 * This method will read information for the requested presentation
207 * into the given structure.
210 * this - Pointer to the DataCache object
211 * drawAspect - The aspect of the object that we wish to draw.
212 * header - The structure containing information about this
213 * aspect of the object.
215 static HRESULT
DataCache_ReadPresentationData(
218 PresentationDataHeader
* header
)
220 IStream
* presStream
= NULL
;
224 * Open the presentation stream.
226 hres
= DataCache_OpenPresStream(
241 sizeof(PresentationDataHeader
),
247 IStream_Release(presStream
);
250 * We don't want to propagate any other error
251 * code than a failure.
259 /************************************************************************
260 * DataCache_FireOnViewChange
262 * This method will fire an OnViewChange notification to the advise
263 * sink registered with the datacache.
265 * See IAdviseSink::OnViewChange for more details.
267 static void DataCache_FireOnViewChange(
272 TRACE("(%p, %lx, %ld)\n", this, aspect
, lindex
);
275 * The sink supplies a filter when it registers
276 * we make sure we only send the notifications when that
279 if ((this->sinkAspects
& aspect
) != 0)
281 if (this->sinkInterface
!= NULL
)
283 IAdviseSink_OnViewChange(this->sinkInterface
,
288 * Some sinks want to be unregistered automatically when
289 * the first notification goes out.
291 if ( (this->sinkAdviseFlag
& ADVF_ONLYONCE
) != 0)
293 IAdviseSink_Release(this->sinkInterface
);
295 this->sinkInterface
= NULL
;
296 this->sinkAspects
= 0;
297 this->sinkAdviseFlag
= 0;
303 /* Helper for DataCache_OpenPresStream */
304 static BOOL
DataCache_IsPresentationStream(const STATSTG
*elem
)
306 /* The presentation streams have names of the form "\002OlePresXXX",
307 * where XXX goes from 000 to 999. */
308 static const WCHAR OlePres
[] = { 2,'O','l','e','P','r','e','s' };
310 LPCWSTR name
= elem
->pwcsName
;
312 return (elem
->type
== STGTY_STREAM
)
313 && (elem
->cbSize
.u
.LowPart
>= sizeof(PresentationDataHeader
))
314 && (strlenW(name
) == 11)
315 && (strncmpW(name
, OlePres
, 8) == 0)
316 && (name
[8] >= '0') && (name
[8] <= '9')
317 && (name
[9] >= '0') && (name
[9] <= '9')
318 && (name
[10] >= '0') && (name
[10] <= '9');
321 /************************************************************************
322 * DataCache_OpenPresStream
324 * This method will find the stream for the given presentation. It makes
325 * no attempt at fallback.
328 * this - Pointer to the DataCache object
329 * drawAspect - The aspect of the object that we wish to draw.
330 * pStm - A returned stream. It points to the beginning of the
331 * - presentation data, including the header.
334 * S_OK The requested stream has been opened.
335 * OLE_E_BLANK The requested stream could not be found.
336 * Quite a few others I'm too lazy to map correctly.
339 * Algorithm: Scan the elements of the presentation storage, looking
340 * for presentation streams. For each presentation stream,
341 * load the header and check to see if the aspect maches.
343 * If a fallback is desired, just opening the first presentation stream
346 static HRESULT
DataCache_OpenPresStream(
355 if (!ppStm
) return E_POINTER
;
357 hr
= IStorage_EnumElements(this->presentationStorage
, 0, NULL
, 0, &pEnum
);
358 if (FAILED(hr
)) return hr
;
360 while ((hr
= IEnumSTATSTG_Next(pEnum
, 1, &elem
, NULL
)) == S_OK
)
362 if (DataCache_IsPresentationStream(&elem
))
366 hr
= IStorage_OpenStream(this->presentationStorage
, elem
.pwcsName
,
367 NULL
, STGM_READ
| STGM_SHARE_EXCLUSIVE
, 0,
371 PresentationDataHeader header
;
374 hr
= IStream_Read(pStm
, &header
, sizeof(header
), &actual_read
);
376 /* can't use SUCCEEDED(hr): S_FALSE counts as an error */
377 if (hr
== S_OK
&& actual_read
== sizeof(header
)
378 && header
.dvAspect
== drawAspect
)
380 /* Rewind the stream before returning it. */
381 LARGE_INTEGER offset
;
382 offset
.u
.LowPart
= 0;
383 offset
.u
.HighPart
= 0;
384 IStream_Seek(pStm
, offset
, STREAM_SEEK_SET
, NULL
);
388 CoTaskMemFree(elem
.pwcsName
);
389 IEnumSTATSTG_Release(pEnum
);
394 IStream_Release(pStm
);
398 CoTaskMemFree(elem
.pwcsName
);
401 IEnumSTATSTG_Release(pEnum
);
403 return (hr
== S_FALSE
? OLE_E_BLANK
: hr
);
406 /************************************************************************
407 * DataCache_ReadPresentationData
409 * This method will read information for the requested presentation
410 * into the given structure.
413 * this - Pointer to the DataCache object
414 * drawAspect - The aspect of the object that we wish to draw.
417 * This method returns a metafile handle if it is successful.
418 * it will return 0 if not.
420 static HMETAFILE
DataCache_ReadPresMetafile(
424 LARGE_INTEGER offset
;
425 IStream
* presStream
= NULL
;
429 HMETAFILE newMetafile
= 0;
432 * Open the presentation stream.
434 hres
= DataCache_OpenPresStream(
440 return (HMETAFILE
)hres
;
443 * Get the size of the stream.
445 hres
= IStream_Stat(presStream
,
452 offset
.u
.HighPart
= 0;
453 offset
.u
.LowPart
= sizeof(PresentationDataHeader
);
461 streamInfo
.cbSize
.u
.LowPart
-= offset
.u
.LowPart
;
464 * Allocate a buffer for the metafile bits.
466 metafileBits
= HeapAlloc(GetProcessHeap(),
468 streamInfo
.cbSize
.u
.LowPart
);
471 * Read the metafile bits.
476 streamInfo
.cbSize
.u
.LowPart
,
480 * Create a metafile with those bits.
484 newMetafile
= SetMetaFileBitsEx(streamInfo
.cbSize
.u
.LowPart
, metafileBits
);
490 HeapFree(GetProcessHeap(), 0, metafileBits
);
491 IStream_Release(presStream
);
499 /*********************************************************
500 * Method implementation for the non delegating IUnknown
501 * part of the DataCache class.
504 /************************************************************************
505 * DataCache_NDIUnknown_QueryInterface (IUnknown)
507 * See Windows documentation for more details on IUnknown methods.
509 * This version of QueryInterface will not delegate it's implementation
510 * to the outer unknown.
512 static HRESULT WINAPI
DataCache_NDIUnknown_QueryInterface(
517 DataCache
*this = impl_from_NDIUnknown(iface
);
520 * Perform a sanity check on the parameters.
522 if ( (this==0) || (ppvObject
==0) )
526 * Initialize the return parameter.
531 * Compare the riid with the interface IDs implemented by this object.
533 if (memcmp(&IID_IUnknown
, riid
, sizeof(IID_IUnknown
)) == 0)
537 else if (memcmp(&IID_IDataObject
, riid
, sizeof(IID_IDataObject
)) == 0)
539 *ppvObject
= (IDataObject
*)&(this->lpVtbl
);
541 else if ( (memcmp(&IID_IPersistStorage
, riid
, sizeof(IID_IPersistStorage
)) == 0) ||
542 (memcmp(&IID_IPersist
, riid
, sizeof(IID_IPersist
)) == 0) )
544 *ppvObject
= (IPersistStorage
*)&(this->lpvtblIPersistStorage
);
546 else if ( (memcmp(&IID_IViewObject
, riid
, sizeof(IID_IViewObject
)) == 0) ||
547 (memcmp(&IID_IViewObject2
, riid
, sizeof(IID_IViewObject2
)) == 0) )
549 *ppvObject
= (IViewObject2
*)&(this->lpvtblIViewObject
);
551 else if ( (memcmp(&IID_IOleCache
, riid
, sizeof(IID_IOleCache
)) == 0) ||
552 (memcmp(&IID_IOleCache2
, riid
, sizeof(IID_IOleCache2
)) == 0) )
554 *ppvObject
= (IOleCache2
*)&(this->lpvtblIOleCache2
);
556 else if (memcmp(&IID_IOleCacheControl
, riid
, sizeof(IID_IOleCacheControl
)) == 0)
558 *ppvObject
= (IOleCacheControl
*)&(this->lpvtblIOleCacheControl
);
562 * Check that we obtained an interface.
566 WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid
));
567 return E_NOINTERFACE
;
571 * Query Interface always increases the reference count by one when it is
574 IUnknown_AddRef((IUnknown
*)*ppvObject
);
579 /************************************************************************
580 * DataCache_NDIUnknown_AddRef (IUnknown)
582 * See Windows documentation for more details on IUnknown methods.
584 * This version of QueryInterface will not delegate it's implementation
585 * to the outer unknown.
587 static ULONG WINAPI
DataCache_NDIUnknown_AddRef(
590 DataCache
*this = impl_from_NDIUnknown(iface
);
591 return InterlockedIncrement(&this->ref
);
594 /************************************************************************
595 * DataCache_NDIUnknown_Release (IUnknown)
597 * See Windows documentation for more details on IUnknown methods.
599 * This version of QueryInterface will not delegate it's implementation
600 * to the outer unknown.
602 static ULONG WINAPI
DataCache_NDIUnknown_Release(
605 DataCache
*this = impl_from_NDIUnknown(iface
);
609 * Decrease the reference count on this object.
611 ref
= InterlockedDecrement(&this->ref
);
614 * If the reference count goes down to 0, perform suicide.
616 if (ref
== 0) DataCache_Destroy(this);
621 /*********************************************************
622 * Method implementation for the IDataObject
623 * part of the DataCache class.
626 /************************************************************************
627 * DataCache_IDataObject_QueryInterface (IUnknown)
629 * See Windows documentation for more details on IUnknown methods.
631 static HRESULT WINAPI
DataCache_IDataObject_QueryInterface(
636 DataCache
*this = impl_from_IDataObject(iface
);
638 return IUnknown_QueryInterface(this->outerUnknown
, riid
, ppvObject
);
641 /************************************************************************
642 * DataCache_IDataObject_AddRef (IUnknown)
644 * See Windows documentation for more details on IUnknown methods.
646 static ULONG WINAPI
DataCache_IDataObject_AddRef(
649 DataCache
*this = impl_from_IDataObject(iface
);
651 return IUnknown_AddRef(this->outerUnknown
);
654 /************************************************************************
655 * DataCache_IDataObject_Release (IUnknown)
657 * See Windows documentation for more details on IUnknown methods.
659 static ULONG WINAPI
DataCache_IDataObject_Release(
662 DataCache
*this = impl_from_IDataObject(iface
);
664 return IUnknown_Release(this->outerUnknown
);
667 /************************************************************************
670 * Get Data from a source dataobject using format pformatetcIn->cfFormat
671 * See Windows documentation for more details on GetData.
672 * TODO: Currently only CF_METAFILEPICT is implemented
674 static HRESULT WINAPI
DataCache_GetData(
676 LPFORMATETC pformatetcIn
,
680 HRESULT hrRet
= E_UNEXPECTED
;
681 IPersistStorage
*pPersistStorage
= 0;
682 IStorage
*pStorage
= 0;
683 IStream
*pStream
= 0;
684 OLECHAR name
[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
685 HGLOBAL hGlobalMF
= 0;
687 PresentationDataHeader pdh
;
688 METAFILEPICT
*mfPict
;
689 HMETAFILE hMetaFile
= 0;
691 if (pformatetcIn
->cfFormat
== CF_METAFILEPICT
)
693 /* Get the Persist Storage */
695 hr
= IDataObject_QueryInterface(iface
, &IID_IPersistStorage
, (void**)&pPersistStorage
);
700 /* Create a doc file to copy the doc to a storage */
702 hr
= StgCreateDocfile(NULL
, STGM_CREATE
| STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, &pStorage
);
707 /* Save it to storage */
709 hr
= OleSave(pPersistStorage
, pStorage
, FALSE
);
714 /* Open the Presentation data srteam */
716 hr
= IStorage_OpenStream(pStorage
, name
, 0, STGM_CREATE
|STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, 0, &pStream
);
721 /* Read the presentation header */
723 hr
= IStream_Read(pStream
, &pdh
, sizeof(PresentationDataHeader
), NULL
);
728 mfBits
= HeapAlloc(GetProcessHeap(), 0, pdh
.dwSize
);
730 /* Read the Metafile bits */
732 hr
= IStream_Read(pStream
, mfBits
, pdh
.dwSize
, NULL
);
737 /* Create the metafile and place it in the STGMEDIUM structure */
739 hMetaFile
= SetMetaFileBitsEx(pdh
.dwSize
, mfBits
);
741 hGlobalMF
= GlobalAlloc(GMEM_SHARE
|GMEM_MOVEABLE
, sizeof(METAFILEPICT
));
742 mfPict
= (METAFILEPICT
*)GlobalLock(hGlobalMF
);
743 mfPict
->hMF
= hMetaFile
;
745 GlobalUnlock(hGlobalMF
);
747 pmedium
->u
.hGlobal
= hGlobalMF
;
748 pmedium
->tymed
= TYMED_MFPICT
;
753 HeapFree(GetProcessHeap(), 0, mfBits
);
756 IStream_Release(pStream
);
759 IStorage_Release(pStorage
);
762 IPersistStorage_Release(pPersistStorage
);
767 /* TODO: Other formats are not implemented */
772 static HRESULT WINAPI
DataCache_GetDataHere(
774 LPFORMATETC pformatetc
,
781 static HRESULT WINAPI
DataCache_QueryGetData(
783 LPFORMATETC pformatetc
)
789 /************************************************************************
790 * DataCache_EnumFormatEtc (IDataObject)
792 * The data cache doesn't implement this method.
794 * See Windows documentation for more details on IDataObject methods.
796 static HRESULT WINAPI
DataCache_GetCanonicalFormatEtc(
798 LPFORMATETC pformatectIn
,
799 LPFORMATETC pformatetcOut
)
805 /************************************************************************
806 * DataCache_IDataObject_SetData (IDataObject)
808 * This method is delegated to the IOleCache2 implementation.
810 * See Windows documentation for more details on IDataObject methods.
812 static HRESULT WINAPI
DataCache_IDataObject_SetData(
814 LPFORMATETC pformatetc
,
818 IOleCache2
* oleCache
= NULL
;
821 TRACE("(%p, %p, %p, %d)\n", iface
, pformatetc
, pmedium
, fRelease
);
823 hres
= IDataObject_QueryInterface(iface
, &IID_IOleCache2
, (void**)&oleCache
);
828 hres
= IOleCache2_SetData(oleCache
, pformatetc
, pmedium
, fRelease
);
830 IOleCache2_Release(oleCache
);
835 /************************************************************************
836 * DataCache_EnumFormatEtc (IDataObject)
838 * The data cache doesn't implement this method.
840 * See Windows documentation for more details on IDataObject methods.
842 static HRESULT WINAPI
DataCache_EnumFormatEtc(
845 IEnumFORMATETC
** ppenumFormatEtc
)
851 /************************************************************************
852 * DataCache_DAdvise (IDataObject)
854 * The data cache doesn't support connections.
856 * See Windows documentation for more details on IDataObject methods.
858 static HRESULT WINAPI
DataCache_DAdvise(
860 FORMATETC
* pformatetc
,
862 IAdviseSink
* pAdvSink
,
863 DWORD
* pdwConnection
)
866 return OLE_E_ADVISENOTSUPPORTED
;
869 /************************************************************************
870 * DataCache_DUnadvise (IDataObject)
872 * The data cache doesn't support connections.
874 * See Windows documentation for more details on IDataObject methods.
876 static HRESULT WINAPI
DataCache_DUnadvise(
881 return OLE_E_NOCONNECTION
;
884 /************************************************************************
885 * DataCache_EnumDAdvise (IDataObject)
887 * The data cache doesn't support connections.
889 * See Windows documentation for more details on IDataObject methods.
891 static HRESULT WINAPI
DataCache_EnumDAdvise(
893 IEnumSTATDATA
** ppenumAdvise
)
896 return OLE_E_ADVISENOTSUPPORTED
;
899 /*********************************************************
900 * Method implementation for the IDataObject
901 * part of the DataCache class.
904 /************************************************************************
905 * DataCache_IPersistStorage_QueryInterface (IUnknown)
907 * See Windows documentation for more details on IUnknown methods.
909 static HRESULT WINAPI
DataCache_IPersistStorage_QueryInterface(
910 IPersistStorage
* iface
,
914 DataCache
*this = impl_from_IPersistStorage(iface
);
916 return IUnknown_QueryInterface(this->outerUnknown
, riid
, ppvObject
);
919 /************************************************************************
920 * DataCache_IPersistStorage_AddRef (IUnknown)
922 * See Windows documentation for more details on IUnknown methods.
924 static ULONG WINAPI
DataCache_IPersistStorage_AddRef(
925 IPersistStorage
* iface
)
927 DataCache
*this = impl_from_IPersistStorage(iface
);
929 return IUnknown_AddRef(this->outerUnknown
);
932 /************************************************************************
933 * DataCache_IPersistStorage_Release (IUnknown)
935 * See Windows documentation for more details on IUnknown methods.
937 static ULONG WINAPI
DataCache_IPersistStorage_Release(
938 IPersistStorage
* iface
)
940 DataCache
*this = impl_from_IPersistStorage(iface
);
942 return IUnknown_Release(this->outerUnknown
);
945 /************************************************************************
946 * DataCache_GetClassID (IPersistStorage)
948 * The data cache doesn't implement this method.
950 * See Windows documentation for more details on IPersistStorage methods.
952 static HRESULT WINAPI
DataCache_GetClassID(
953 IPersistStorage
* iface
,
956 TRACE("(%p, %p)\n", iface
, pClassID
);
960 /************************************************************************
961 * DataCache_IsDirty (IPersistStorage)
963 * Until we actully connect to a running object and retrieve new
964 * information to it, we never get dirty.
966 * See Windows documentation for more details on IPersistStorage methods.
968 static HRESULT WINAPI
DataCache_IsDirty(
969 IPersistStorage
* iface
)
971 TRACE("(%p)\n", iface
);
976 /************************************************************************
977 * DataCache_InitNew (IPersistStorage)
979 * The data cache implementation of IPersistStorage_InitNew simply stores
980 * the storage pointer.
982 * See Windows documentation for more details on IPersistStorage methods.
984 static HRESULT WINAPI
DataCache_InitNew(
985 IPersistStorage
* iface
,
988 TRACE("(%p, %p)\n", iface
, pStg
);
990 return IPersistStorage_Load(iface
, pStg
);
993 /************************************************************************
994 * DataCache_Load (IPersistStorage)
996 * The data cache implementation of IPersistStorage_Load doesn't
997 * actually load anything. Instead, it holds on to the storage pointer
998 * and it will load the presentation information when the
999 * IDataObject_GetData or IViewObject2_Draw methods are called.
1001 * See Windows documentation for more details on IPersistStorage methods.
1003 static HRESULT WINAPI
DataCache_Load(
1004 IPersistStorage
* iface
,
1007 DataCache
*this = impl_from_IPersistStorage(iface
);
1009 TRACE("(%p, %p)\n", iface
, pStg
);
1011 if (this->presentationStorage
!= NULL
)
1013 IStorage_Release(this->presentationStorage
);
1016 this->presentationStorage
= pStg
;
1018 if (this->presentationStorage
!= NULL
)
1020 IStorage_AddRef(this->presentationStorage
);
1025 /************************************************************************
1026 * DataCache_Save (IPersistStorage)
1028 * Until we actully connect to a running object and retrieve new
1029 * information to it, we never have to save anything. However, it is
1030 * our responsability to copy the information when saving to a new
1033 * See Windows documentation for more details on IPersistStorage methods.
1035 static HRESULT WINAPI
DataCache_Save(
1036 IPersistStorage
* iface
,
1040 DataCache
*this = impl_from_IPersistStorage(iface
);
1042 TRACE("(%p, %p, %d)\n", iface
, pStg
, fSameAsLoad
);
1044 if ( (!fSameAsLoad
) &&
1045 (this->presentationStorage
!=NULL
) )
1047 return IStorage_CopyTo(this->presentationStorage
,
1057 /************************************************************************
1058 * DataCache_SaveCompleted (IPersistStorage)
1060 * This method is called to tell the cache to release the storage
1061 * pointer it's currentlu holding.
1063 * See Windows documentation for more details on IPersistStorage methods.
1065 static HRESULT WINAPI
DataCache_SaveCompleted(
1066 IPersistStorage
* iface
,
1069 TRACE("(%p, %p)\n", iface
, pStgNew
);
1074 * First, make sure we get our hands off any storage we have.
1077 IPersistStorage_HandsOffStorage(iface
);
1080 * Then, attach to the new storage.
1083 DataCache_Load(iface
, pStgNew
);
1089 /************************************************************************
1090 * DataCache_HandsOffStorage (IPersistStorage)
1092 * This method is called to tell the cache to release the storage
1093 * pointer it's currentlu holding.
1095 * See Windows documentation for more details on IPersistStorage methods.
1097 static HRESULT WINAPI
DataCache_HandsOffStorage(
1098 IPersistStorage
* iface
)
1100 DataCache
*this = impl_from_IPersistStorage(iface
);
1102 TRACE("(%p)\n", iface
);
1104 if (this->presentationStorage
!= NULL
)
1106 IStorage_Release(this->presentationStorage
);
1107 this->presentationStorage
= NULL
;
1113 /*********************************************************
1114 * Method implementation for the IViewObject2
1115 * part of the DataCache class.
1118 /************************************************************************
1119 * DataCache_IViewObject2_QueryInterface (IUnknown)
1121 * See Windows documentation for more details on IUnknown methods.
1123 static HRESULT WINAPI
DataCache_IViewObject2_QueryInterface(
1124 IViewObject2
* iface
,
1128 DataCache
*this = impl_from_IViewObject2(iface
);
1130 return IUnknown_QueryInterface(this->outerUnknown
, riid
, ppvObject
);
1133 /************************************************************************
1134 * DataCache_IViewObject2_AddRef (IUnknown)
1136 * See Windows documentation for more details on IUnknown methods.
1138 static ULONG WINAPI
DataCache_IViewObject2_AddRef(
1139 IViewObject2
* iface
)
1141 DataCache
*this = impl_from_IViewObject2(iface
);
1143 return IUnknown_AddRef(this->outerUnknown
);
1146 /************************************************************************
1147 * DataCache_IViewObject2_Release (IUnknown)
1149 * See Windows documentation for more details on IUnknown methods.
1151 static ULONG WINAPI
DataCache_IViewObject2_Release(
1152 IViewObject2
* iface
)
1154 DataCache
*this = impl_from_IViewObject2(iface
);
1156 return IUnknown_Release(this->outerUnknown
);
1159 /************************************************************************
1160 * DataCache_Draw (IViewObject2)
1162 * This method will draw the cached representation of the object
1163 * to the given device context.
1165 * See Windows documentation for more details on IViewObject2 methods.
1167 static HRESULT WINAPI
DataCache_Draw(
1168 IViewObject2
* iface
,
1172 DVTARGETDEVICE
* ptd
,
1175 LPCRECTL lprcBounds
,
1176 LPCRECTL lprcWBounds
,
1177 BOOL (CALLBACK
*pfnContinue
)(ULONG_PTR dwContinue
),
1178 ULONG_PTR dwContinue
)
1180 PresentationDataHeader presData
;
1181 HMETAFILE presMetafile
= 0;
1184 DataCache
*this = impl_from_IViewObject2(iface
);
1186 TRACE("(%p, %lx, %ld, %p, %p, %p, %p, %p, %p, %lx)\n",
1201 if (lprcBounds
==NULL
)
1202 return E_INVALIDARG
;
1205 * First, we need to retrieve the dimensions of the
1206 * image in the metafile.
1208 hres
= DataCache_ReadPresentationData(this,
1216 * Then, we can extract the metafile itself from the cached
1219 * FIXME Unless it isn't a metafile. I think it could be any CF_XXX type,
1220 * particularly CF_DIB.
1222 presMetafile
= DataCache_ReadPresMetafile(this,
1226 * If we have a metafile, just draw baby...
1227 * We have to be careful not to modify the state of the
1230 if (presMetafile
!=0)
1232 INT prevMapMode
= SetMapMode(hdcDraw
, MM_ANISOTROPIC
);
1234 SIZE oldViewportExt
;
1235 POINT oldViewportOrg
;
1237 SetWindowExtEx(hdcDraw
,
1238 presData
.dwObjectExtentX
,
1239 presData
.dwObjectExtentY
,
1242 SetViewportExtEx(hdcDraw
,
1243 lprcBounds
->right
- lprcBounds
->left
,
1244 lprcBounds
->bottom
- lprcBounds
->top
,
1247 SetViewportOrgEx(hdcDraw
,
1252 PlayMetaFile(hdcDraw
, presMetafile
);
1254 SetWindowExtEx(hdcDraw
,
1259 SetViewportExtEx(hdcDraw
,
1264 SetViewportOrgEx(hdcDraw
,
1269 SetMapMode(hdcDraw
, prevMapMode
);
1271 DeleteMetaFile(presMetafile
);
1277 static HRESULT WINAPI
DataCache_GetColorSet(
1278 IViewObject2
* iface
,
1282 DVTARGETDEVICE
* ptd
,
1283 HDC hicTargetDevice
,
1284 LOGPALETTE
** ppColorSet
)
1290 static HRESULT WINAPI
DataCache_Freeze(
1291 IViewObject2
* iface
,
1301 static HRESULT WINAPI
DataCache_Unfreeze(
1302 IViewObject2
* iface
,
1309 /************************************************************************
1310 * DataCache_SetAdvise (IViewObject2)
1312 * This sets-up an advisory sink with the data cache. When the object's
1313 * view changes, this sink is called.
1315 * See Windows documentation for more details on IViewObject2 methods.
1317 static HRESULT WINAPI
DataCache_SetAdvise(
1318 IViewObject2
* iface
,
1321 IAdviseSink
* pAdvSink
)
1323 DataCache
*this = impl_from_IViewObject2(iface
);
1325 TRACE("(%p, %lx, %lx, %p)\n", iface
, aspects
, advf
, pAdvSink
);
1328 * A call to this function removes the previous sink
1330 if (this->sinkInterface
!= NULL
)
1332 IAdviseSink_Release(this->sinkInterface
);
1333 this->sinkInterface
= NULL
;
1334 this->sinkAspects
= 0;
1335 this->sinkAdviseFlag
= 0;
1339 * Now, setup the new one.
1343 this->sinkInterface
= pAdvSink
;
1344 this->sinkAspects
= aspects
;
1345 this->sinkAdviseFlag
= advf
;
1347 IAdviseSink_AddRef(this->sinkInterface
);
1351 * When the ADVF_PRIMEFIRST flag is set, we have to advise the
1354 if (advf
& ADVF_PRIMEFIRST
)
1356 DataCache_FireOnViewChange(this,
1364 /************************************************************************
1365 * DataCache_GetAdvise (IViewObject2)
1367 * This method queries the current state of the advise sink
1368 * installed on the data cache.
1370 * See Windows documentation for more details on IViewObject2 methods.
1372 static HRESULT WINAPI
DataCache_GetAdvise(
1373 IViewObject2
* iface
,
1376 IAdviseSink
** ppAdvSink
)
1378 DataCache
*this = impl_from_IViewObject2(iface
);
1380 TRACE("(%p, %p, %p, %p)\n", iface
, pAspects
, pAdvf
, ppAdvSink
);
1383 * Just copy all the requested values.
1386 *pAspects
= this->sinkAspects
;
1389 *pAdvf
= this->sinkAdviseFlag
;
1391 if (ppAdvSink
!=NULL
)
1393 if (this->sinkInterface
!= NULL
)
1394 IAdviseSink_QueryInterface(this->sinkInterface
,
1397 else *ppAdvSink
= NULL
;
1403 /************************************************************************
1404 * DataCache_GetExtent (IViewObject2)
1406 * This method retrieves the "natural" size of this cached object.
1408 * See Windows documentation for more details on IViewObject2 methods.
1410 static HRESULT WINAPI
DataCache_GetExtent(
1411 IViewObject2
* iface
,
1414 DVTARGETDEVICE
* ptd
,
1417 PresentationDataHeader presData
;
1418 HRESULT hres
= E_FAIL
;
1420 DataCache
*this = impl_from_IViewObject2(iface
);
1422 TRACE("(%p, %lx, %ld, %p, %p)\n",
1423 iface
, dwDrawAspect
, lindex
, ptd
, lpsizel
);
1432 * Initialize the out parameter.
1438 * This flag should be set to -1.
1441 FIXME("Unimplemented flag lindex = %ld\n", lindex
);
1444 * Right now, we support only the callback from
1445 * the default handler.
1448 FIXME("Unimplemented ptd = %p\n", ptd
);
1451 * Get the presentation information from the
1454 hres
= DataCache_ReadPresentationData(this,
1458 if (SUCCEEDED(hres
))
1460 lpsizel
->cx
= presData
.dwObjectExtentX
;
1461 lpsizel
->cy
= presData
.dwObjectExtentY
;
1465 * This method returns OLE_E_BLANK when it fails.
1474 /*********************************************************
1475 * Method implementation for the IOleCache2
1476 * part of the DataCache class.
1479 /************************************************************************
1480 * DataCache_IOleCache2_QueryInterface (IUnknown)
1482 * See Windows documentation for more details on IUnknown methods.
1484 static HRESULT WINAPI
DataCache_IOleCache2_QueryInterface(
1489 DataCache
*this = impl_from_IOleCache2(iface
);
1491 return IUnknown_QueryInterface(this->outerUnknown
, riid
, ppvObject
);
1494 /************************************************************************
1495 * DataCache_IOleCache2_AddRef (IUnknown)
1497 * See Windows documentation for more details on IUnknown methods.
1499 static ULONG WINAPI
DataCache_IOleCache2_AddRef(
1502 DataCache
*this = impl_from_IOleCache2(iface
);
1504 return IUnknown_AddRef(this->outerUnknown
);
1507 /************************************************************************
1508 * DataCache_IOleCache2_Release (IUnknown)
1510 * See Windows documentation for more details on IUnknown methods.
1512 static ULONG WINAPI
DataCache_IOleCache2_Release(
1515 DataCache
*this = impl_from_IOleCache2(iface
);
1517 return IUnknown_Release(this->outerUnknown
);
1520 static HRESULT WINAPI
DataCache_Cache(
1522 FORMATETC
* pformatetc
,
1524 DWORD
* pdwConnection
)
1530 static HRESULT WINAPI
DataCache_Uncache(
1538 static HRESULT WINAPI
DataCache_EnumCache(
1540 IEnumSTATDATA
** ppenumSTATDATA
)
1546 static HRESULT WINAPI
DataCache_InitCache(
1548 IDataObject
* pDataObject
)
1554 static HRESULT WINAPI
DataCache_IOleCache2_SetData(
1556 FORMATETC
* pformatetc
,
1564 static HRESULT WINAPI
DataCache_UpdateCache(
1566 LPDATAOBJECT pDataObject
,
1574 static HRESULT WINAPI
DataCache_DiscardCache(
1576 DWORD dwDiscardOptions
)
1583 /*********************************************************
1584 * Method implementation for the IOleCacheControl
1585 * part of the DataCache class.
1588 /************************************************************************
1589 * DataCache_IOleCacheControl_QueryInterface (IUnknown)
1591 * See Windows documentation for more details on IUnknown methods.
1593 static HRESULT WINAPI
DataCache_IOleCacheControl_QueryInterface(
1594 IOleCacheControl
* iface
,
1598 DataCache
*this = impl_from_IOleCacheControl(iface
);
1600 return IUnknown_QueryInterface(this->outerUnknown
, riid
, ppvObject
);
1603 /************************************************************************
1604 * DataCache_IOleCacheControl_AddRef (IUnknown)
1606 * See Windows documentation for more details on IUnknown methods.
1608 static ULONG WINAPI
DataCache_IOleCacheControl_AddRef(
1609 IOleCacheControl
* iface
)
1611 DataCache
*this = impl_from_IOleCacheControl(iface
);
1613 return IUnknown_AddRef(this->outerUnknown
);
1616 /************************************************************************
1617 * DataCache_IOleCacheControl_Release (IUnknown)
1619 * See Windows documentation for more details on IUnknown methods.
1621 static ULONG WINAPI
DataCache_IOleCacheControl_Release(
1622 IOleCacheControl
* iface
)
1624 DataCache
*this = impl_from_IOleCacheControl(iface
);
1626 return IUnknown_Release(this->outerUnknown
);
1629 static HRESULT WINAPI
DataCache_OnRun(
1630 IOleCacheControl
* iface
,
1631 LPDATAOBJECT pDataObject
)
1637 static HRESULT WINAPI
DataCache_OnStop(
1638 IOleCacheControl
* iface
)
1645 * Virtual function tables for the DataCache class.
1647 static const IUnknownVtbl DataCache_NDIUnknown_VTable
=
1649 DataCache_NDIUnknown_QueryInterface
,
1650 DataCache_NDIUnknown_AddRef
,
1651 DataCache_NDIUnknown_Release
1654 static const IDataObjectVtbl DataCache_IDataObject_VTable
=
1656 DataCache_IDataObject_QueryInterface
,
1657 DataCache_IDataObject_AddRef
,
1658 DataCache_IDataObject_Release
,
1660 DataCache_GetDataHere
,
1661 DataCache_QueryGetData
,
1662 DataCache_GetCanonicalFormatEtc
,
1663 DataCache_IDataObject_SetData
,
1664 DataCache_EnumFormatEtc
,
1666 DataCache_DUnadvise
,
1667 DataCache_EnumDAdvise
1670 static const IPersistStorageVtbl DataCache_IPersistStorage_VTable
=
1672 DataCache_IPersistStorage_QueryInterface
,
1673 DataCache_IPersistStorage_AddRef
,
1674 DataCache_IPersistStorage_Release
,
1675 DataCache_GetClassID
,
1680 DataCache_SaveCompleted
,
1681 DataCache_HandsOffStorage
1684 static const IViewObject2Vtbl DataCache_IViewObject2_VTable
=
1686 DataCache_IViewObject2_QueryInterface
,
1687 DataCache_IViewObject2_AddRef
,
1688 DataCache_IViewObject2_Release
,
1690 DataCache_GetColorSet
,
1693 DataCache_SetAdvise
,
1694 DataCache_GetAdvise
,
1698 static const IOleCache2Vtbl DataCache_IOleCache2_VTable
=
1700 DataCache_IOleCache2_QueryInterface
,
1701 DataCache_IOleCache2_AddRef
,
1702 DataCache_IOleCache2_Release
,
1705 DataCache_EnumCache
,
1706 DataCache_InitCache
,
1707 DataCache_IOleCache2_SetData
,
1708 DataCache_UpdateCache
,
1709 DataCache_DiscardCache
1712 static const IOleCacheControlVtbl DataCache_IOleCacheControl_VTable
=
1714 DataCache_IOleCacheControl_QueryInterface
,
1715 DataCache_IOleCacheControl_AddRef
,
1716 DataCache_IOleCacheControl_Release
,
1721 /******************************************************************************
1722 * CreateDataCache [OLE32.@]
1724 HRESULT WINAPI
CreateDataCache(
1725 LPUNKNOWN pUnkOuter
,
1730 DataCache
* newCache
= NULL
;
1733 TRACE("(%s, %p, %s, %p)\n", debugstr_guid(rclsid
), pUnkOuter
, debugstr_guid(riid
), ppvObj
);
1744 * If this cache is constructed for aggregation, make sure
1745 * the caller is requesting the IUnknown interface.
1746 * This is necessary because it's the only time the non-delegating
1747 * IUnknown pointer can be returned to the outside.
1749 if ( (pUnkOuter
!=NULL
) &&
1750 (memcmp(&IID_IUnknown
, riid
, sizeof(IID_IUnknown
)) != 0) )
1751 return CLASS_E_NOAGGREGATION
;
1754 * Try to construct a new instance of the class.
1756 newCache
= DataCache_Construct(rclsid
,
1760 return E_OUTOFMEMORY
;
1763 * Make sure it supports the interface required by the caller.
1765 hr
= IUnknown_QueryInterface((IUnknown
*)&(newCache
->lpvtblNDIUnknown
), riid
, ppvObj
);
1768 * Release the reference obtained in the constructor. If
1769 * the QueryInterface was unsuccessful, it will free the class.
1771 IUnknown_Release((IUnknown
*)&(newCache
->lpvtblNDIUnknown
));
1776 /*********************************************************
1777 * Method implementation for DataCache class.
1779 static DataCache
* DataCache_Construct(
1781 LPUNKNOWN pUnkOuter
)
1783 DataCache
* newObject
= 0;
1786 * Allocate space for the object.
1788 newObject
= HeapAlloc(GetProcessHeap(), 0, sizeof(DataCache
));
1794 * Initialize the virtual function table.
1796 newObject
->lpVtbl
= &DataCache_IDataObject_VTable
;
1797 newObject
->lpvtblNDIUnknown
= &DataCache_NDIUnknown_VTable
;
1798 newObject
->lpvtblIPersistStorage
= &DataCache_IPersistStorage_VTable
;
1799 newObject
->lpvtblIViewObject
= &DataCache_IViewObject2_VTable
;
1800 newObject
->lpvtblIOleCache2
= &DataCache_IOleCache2_VTable
;
1801 newObject
->lpvtblIOleCacheControl
= &DataCache_IOleCacheControl_VTable
;
1804 * Start with one reference count. The caller of this function
1805 * must release the interface pointer when it is done.
1810 * Initialize the outer unknown
1811 * We don't keep a reference on the outer unknown since, the way
1812 * aggregation works, our lifetime is at least as large as it's
1815 if (pUnkOuter
==NULL
)
1816 pUnkOuter
= (IUnknown
*)&(newObject
->lpvtblNDIUnknown
);
1818 newObject
->outerUnknown
= pUnkOuter
;
1821 * Initialize the other members of the structure.
1823 newObject
->presentationStorage
= NULL
;
1824 newObject
->sinkAspects
= 0;
1825 newObject
->sinkAdviseFlag
= 0;
1826 newObject
->sinkInterface
= 0;