Get rid of the no longer used ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
[wine/multimedia.git] / dlls / ole32 / datacache.c
bloba5e2d7b3642526e25298b8dcf7e897e3a90aee22
1 /*
2 * OLE 2 Data cache
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
21 * NOTES:
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,
30 * NOTES
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.
46 #include <assert.h>
47 #include <stdarg.h>
48 #include <string.h>
50 #define NONAMELESSUNION
51 #define NONAMELESSSTRUCT
52 #include "windef.h"
53 #include "winbase.h"
54 #include "wingdi.h"
55 #include "winuser.h"
56 #include "winerror.h"
57 #include "wine/unicode.h"
58 #include "ole2.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 */
76 DVASPECT dvAspect;
77 DWORD unknown5; /* -1 */
79 DWORD unknown6;
80 DWORD unknown7; /* 0 */
81 DWORD dwObjectExtentX;
82 DWORD dwObjectExtentY;
83 DWORD dwSize;
84 } PresentationDataHeader;
86 /****************************************************************************
87 * DataCache
89 struct DataCache
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
104 ULONG ref;
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
121 * that connection.
123 DWORD sinkAspects;
124 DWORD sinkAdviseFlag;
125 IAdviseSink* sinkInterface;
129 typedef struct DataCache DataCache;
132 * Here, I define utility macros to help with the casting of the
133 * "this" parameter.
134 * There is a version to accomodate all of the VTables implemented
135 * by this object.
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,
151 DWORD drawAspect,
152 PresentationDataHeader* header);
153 static HRESULT DataCache_OpenPresStream(DataCache *this,
154 DWORD drawAspect,
155 IStream **pStm);
156 static HMETAFILE DataCache_ReadPresMetafile(DataCache* this,
157 DWORD drawAspect);
158 static void DataCache_FireOnViewChange(DataCache* this,
159 DWORD aspect,
160 LONG lindex);
163 * Prototypes for the methods of the DataCache class
164 * that implement non delegating IUnknown methods.
166 static HRESULT WINAPI DataCache_NDIUnknown_QueryInterface(
167 IUnknown* iface,
168 REFIID riid,
169 void** ppvObject);
170 static ULONG WINAPI DataCache_NDIUnknown_AddRef(
171 IUnknown* iface);
172 static ULONG WINAPI DataCache_NDIUnknown_Release(
173 IUnknown* iface);
176 * Prototypes for the methods of the DataCache class
177 * that implement IDataObject methods.
179 static HRESULT WINAPI DataCache_IDataObject_QueryInterface(
180 IDataObject* iface,
181 REFIID riid,
182 void** ppvObject);
183 static ULONG WINAPI DataCache_IDataObject_AddRef(
184 IDataObject* iface);
185 static ULONG WINAPI DataCache_IDataObject_Release(
186 IDataObject* iface);
187 static HRESULT WINAPI DataCache_GetData(
188 IDataObject* iface,
189 LPFORMATETC pformatetcIn,
190 STGMEDIUM* pmedium);
191 static HRESULT WINAPI DataCache_GetDataHere(
192 IDataObject* iface,
193 LPFORMATETC pformatetc,
194 STGMEDIUM* pmedium);
195 static HRESULT WINAPI DataCache_QueryGetData(
196 IDataObject* iface,
197 LPFORMATETC pformatetc);
198 static HRESULT WINAPI DataCache_GetCanonicalFormatEtc(
199 IDataObject* iface,
200 LPFORMATETC pformatectIn,
201 LPFORMATETC pformatetcOut);
202 static HRESULT WINAPI DataCache_IDataObject_SetData(
203 IDataObject* iface,
204 LPFORMATETC pformatetc,
205 STGMEDIUM* pmedium,
206 BOOL fRelease);
207 static HRESULT WINAPI DataCache_EnumFormatEtc(
208 IDataObject* iface,
209 DWORD dwDirection,
210 IEnumFORMATETC** ppenumFormatEtc);
211 static HRESULT WINAPI DataCache_DAdvise(
212 IDataObject* iface,
213 FORMATETC* pformatetc,
214 DWORD advf,
215 IAdviseSink* pAdvSink,
216 DWORD* pdwConnection);
217 static HRESULT WINAPI DataCache_DUnadvise(
218 IDataObject* iface,
219 DWORD dwConnection);
220 static HRESULT WINAPI DataCache_EnumDAdvise(
221 IDataObject* iface,
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,
230 REFIID riid,
231 void** ppvObject);
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,
238 CLSID* pClassID);
239 static HRESULT WINAPI DataCache_IsDirty(
240 IPersistStorage* iface);
241 static HRESULT WINAPI DataCache_InitNew(
242 IPersistStorage* iface,
243 IStorage* pStg);
244 static HRESULT WINAPI DataCache_Load(
245 IPersistStorage* iface,
246 IStorage* pStg);
247 static HRESULT WINAPI DataCache_Save(
248 IPersistStorage* iface,
249 IStorage* pStg,
250 BOOL fSameAsLoad);
251 static HRESULT WINAPI DataCache_SaveCompleted(
252 IPersistStorage* iface,
253 IStorage* pStgNew);
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(
262 IViewObject2* iface,
263 REFIID riid,
264 void** ppvObject);
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(
270 IViewObject2* iface,
271 DWORD dwDrawAspect,
272 LONG lindex,
273 void* pvAspect,
274 DVTARGETDEVICE* ptd,
275 HDC hdcTargetDev,
276 HDC hdcDraw,
277 LPCRECTL lprcBounds,
278 LPCRECTL lprcWBounds,
279 BOOL (CALLBACK *pfnContinue)(ULONG_PTR dwContinue),
280 DWORD dwContinue);
281 static HRESULT WINAPI DataCache_GetColorSet(
282 IViewObject2* iface,
283 DWORD dwDrawAspect,
284 LONG lindex,
285 void* pvAspect,
286 DVTARGETDEVICE* ptd,
287 HDC hicTargetDevice,
288 LOGPALETTE** ppColorSet);
289 static HRESULT WINAPI DataCache_Freeze(
290 IViewObject2* iface,
291 DWORD dwDrawAspect,
292 LONG lindex,
293 void* pvAspect,
294 DWORD* pdwFreeze);
295 static HRESULT WINAPI DataCache_Unfreeze(
296 IViewObject2* iface,
297 DWORD dwFreeze);
298 static HRESULT WINAPI DataCache_SetAdvise(
299 IViewObject2* iface,
300 DWORD aspects,
301 DWORD advf,
302 IAdviseSink* pAdvSink);
303 static HRESULT WINAPI DataCache_GetAdvise(
304 IViewObject2* iface,
305 DWORD* pAspects,
306 DWORD* pAdvf,
307 IAdviseSink** ppAdvSink);
308 static HRESULT WINAPI DataCache_GetExtent(
309 IViewObject2* iface,
310 DWORD dwDrawAspect,
311 LONG lindex,
312 DVTARGETDEVICE* ptd,
313 LPSIZEL lpsizel);
316 * Prototypes for the methods of the DataCache class
317 * that implement IOleCache2 methods.
319 static HRESULT WINAPI DataCache_IOleCache2_QueryInterface(
320 IOleCache2* iface,
321 REFIID riid,
322 void** ppvObject);
323 static ULONG WINAPI DataCache_IOleCache2_AddRef(
324 IOleCache2* iface);
325 static ULONG WINAPI DataCache_IOleCache2_Release(
326 IOleCache2* iface);
327 static HRESULT WINAPI DataCache_Cache(
328 IOleCache2* iface,
329 FORMATETC* pformatetc,
330 DWORD advf,
331 DWORD* pdwConnection);
332 static HRESULT WINAPI DataCache_Uncache(
333 IOleCache2* iface,
334 DWORD dwConnection);
335 static HRESULT WINAPI DataCache_EnumCache(
336 IOleCache2* iface,
337 IEnumSTATDATA** ppenumSTATDATA);
338 static HRESULT WINAPI DataCache_InitCache(
339 IOleCache2* iface,
340 IDataObject* pDataObject);
341 static HRESULT WINAPI DataCache_IOleCache2_SetData(
342 IOleCache2* iface,
343 FORMATETC* pformatetc,
344 STGMEDIUM* pmedium,
345 BOOL fRelease);
346 static HRESULT WINAPI DataCache_UpdateCache(
347 IOleCache2* iface,
348 LPDATAOBJECT pDataObject,
349 DWORD grfUpdf,
350 LPVOID pReserved);
351 static HRESULT WINAPI DataCache_DiscardCache(
352 IOleCache2* iface,
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,
361 REFIID riid,
362 void** ppvObject);
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,
388 DataCache_GetData,
389 DataCache_GetDataHere,
390 DataCache_QueryGetData,
391 DataCache_GetCanonicalFormatEtc,
392 DataCache_IDataObject_SetData,
393 DataCache_EnumFormatEtc,
394 DataCache_DAdvise,
395 DataCache_DUnadvise,
396 DataCache_EnumDAdvise
399 static IPersistStorageVtbl DataCache_IPersistStorage_VTable =
401 DataCache_IPersistStorage_QueryInterface,
402 DataCache_IPersistStorage_AddRef,
403 DataCache_IPersistStorage_Release,
404 DataCache_GetClassID,
405 DataCache_IsDirty,
406 DataCache_InitNew,
407 DataCache_Load,
408 DataCache_Save,
409 DataCache_SaveCompleted,
410 DataCache_HandsOffStorage
413 static IViewObject2Vtbl DataCache_IViewObject2_VTable =
415 DataCache_IViewObject2_QueryInterface,
416 DataCache_IViewObject2_AddRef,
417 DataCache_IViewObject2_Release,
418 DataCache_Draw,
419 DataCache_GetColorSet,
420 DataCache_Freeze,
421 DataCache_Unfreeze,
422 DataCache_SetAdvise,
423 DataCache_GetAdvise,
424 DataCache_GetExtent
427 static IOleCache2Vtbl DataCache_IOleCache2_VTable =
429 DataCache_IOleCache2_QueryInterface,
430 DataCache_IOleCache2_AddRef,
431 DataCache_IOleCache2_Release,
432 DataCache_Cache,
433 DataCache_Uncache,
434 DataCache_EnumCache,
435 DataCache_InitCache,
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,
446 DataCache_OnRun,
447 DataCache_OnStop
450 /******************************************************************************
451 * CreateDataCache [OLE32.@]
453 HRESULT WINAPI CreateDataCache(
454 LPUNKNOWN pUnkOuter,
455 REFCLSID rclsid,
456 REFIID riid,
457 LPVOID* ppvObj)
459 DataCache* newCache = NULL;
460 HRESULT hr = S_OK;
462 TRACE("(%s, %p, %s, %p)\n", debugstr_guid(rclsid), pUnkOuter, debugstr_guid(riid), ppvObj);
465 * Sanity check
467 if (ppvObj==0)
468 return E_POINTER;
470 *ppvObj = 0;
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,
486 pUnkOuter);
488 if (newCache == 0)
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));
502 return hr;
505 /*********************************************************
506 * Method implementation for DataCache class.
508 static DataCache* DataCache_Construct(
509 REFCLSID clsid,
510 LPUNKNOWN pUnkOuter)
512 DataCache* newObject = 0;
515 * Allocate space for the object.
517 newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(DataCache));
519 if (newObject==0)
520 return newObject;
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.
536 newObject->ref = 1;
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
542 * lifetime.
544 if (pUnkOuter==NULL)
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;
557 return newObject;
560 static void DataCache_Destroy(
561 DataCache* ptrToDestroy)
563 TRACE("()\n");
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.
589 * Param:
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(
596 DataCache* this,
597 DWORD drawAspect,
598 PresentationDataHeader* header)
600 IStream* presStream = NULL;
601 HRESULT hres;
604 * Open the presentation stream.
606 hres = DataCache_OpenPresStream(
607 this,
608 drawAspect,
609 &presStream);
611 if (FAILED(hres))
612 return hres;
615 * Read the header.
618 hres = IStream_Read(
619 presStream,
620 header,
621 sizeof(PresentationDataHeader),
622 NULL);
625 * Cleanup.
627 IStream_Release(presStream);
630 * We don't want to propagate any other error
631 * code than a failure.
633 if (hres!=S_OK)
634 hres = E_FAIL;
636 return hres;
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(
648 DataCache* this,
649 DWORD aspect,
650 LONG lindex)
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
657 * filter matches.
659 if ((this->sinkAspects & aspect) != 0)
661 if (this->sinkInterface != NULL)
663 IAdviseSink_OnViewChange(this->sinkInterface,
664 aspect,
665 lindex);
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.
707 * Param:
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.
713 * Errors:
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.
718 * Notes:
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
724 * is a possibility.
726 static HRESULT DataCache_OpenPresStream(
727 DataCache *this,
728 DWORD drawAspect,
729 IStream **ppStm)
731 STATSTG elem;
732 IEnumSTATSTG *pEnum;
733 HRESULT hr;
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))
744 IStream *pStm;
746 hr = IStorage_OpenStream(this->presentationStorage, elem.pwcsName,
747 NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0,
748 &pStm);
749 if (SUCCEEDED(hr))
751 PresentationDataHeader header;
752 ULONG actual_read;
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);
766 *ppStm = pStm;
768 CoTaskMemFree(elem.pwcsName);
769 IEnumSTATSTG_Release(pEnum);
771 return S_OK;
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.
792 * Param:
793 * this - Pointer to the DataCache object
794 * drawAspect - The aspect of the object that we wish to draw.
796 * Returns:
797 * This method returns a metafile handle if it is successful.
798 * it will return 0 if not.
800 static HMETAFILE DataCache_ReadPresMetafile(
801 DataCache* this,
802 DWORD drawAspect)
804 LARGE_INTEGER offset;
805 IStream* presStream = NULL;
806 HRESULT hres;
807 void* metafileBits;
808 STATSTG streamInfo;
809 HMETAFILE newMetafile = 0;
812 * Open the presentation stream.
814 hres = DataCache_OpenPresStream(
815 this,
816 drawAspect,
817 &presStream);
819 if (FAILED(hres))
820 return (HMETAFILE)hres;
823 * Get the size of the stream.
825 hres = IStream_Stat(presStream,
826 &streamInfo,
827 STATFLAG_NONAME);
830 * Skip the header
832 offset.u.HighPart = 0;
833 offset.u.LowPart = sizeof(PresentationDataHeader);
835 hres = IStream_Seek(
836 presStream,
837 offset,
838 STREAM_SEEK_SET,
839 NULL);
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.
853 hres = IStream_Read(
854 presStream,
855 metafileBits,
856 streamInfo.cbSize.u.LowPart,
857 NULL);
860 * Create a metafile with those bits.
862 if (SUCCEEDED(hres))
864 newMetafile = SetMetaFileBitsEx(streamInfo.cbSize.u.LowPart, metafileBits);
868 * Cleanup.
870 HeapFree(GetProcessHeap(), 0, metafileBits);
871 IStream_Release(presStream);
873 if (newMetafile==0)
874 hres = E_FAIL;
876 return newMetafile;
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(
893 IUnknown* iface,
894 REFIID riid,
895 void** ppvObject)
897 _ICOM_THIS_From_NDIUnknown(DataCache, iface);
900 * Perform a sanity check on the parameters.
902 if ( (this==0) || (ppvObject==0) )
903 return E_INVALIDARG;
906 * Initialize the return parameter.
908 *ppvObject = 0;
911 * Compare the riid with the interface IDs implemented by this object.
913 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
915 *ppvObject = iface;
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.
944 if ((*ppvObject)==0)
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
952 * successful.
954 IUnknown_AddRef((IUnknown*)*ppvObject);
956 return S_OK;
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(
968 IUnknown* iface)
970 _ICOM_THIS_From_NDIUnknown(DataCache, iface);
972 this->ref++;
974 return this->ref;
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(
986 IUnknown* iface)
988 _ICOM_THIS_From_NDIUnknown(DataCache, iface);
991 * Decrease the reference count on this object.
993 this->ref--;
996 * If the reference count goes down to 0, perform suicide.
998 if (this->ref==0)
1000 DataCache_Destroy(this);
1002 return 0;
1005 return this->ref;
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(
1019 IDataObject* iface,
1020 REFIID riid,
1021 void** ppvObject)
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(
1034 IDataObject* iface)
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(
1047 IDataObject* iface)
1049 _ICOM_THIS_From_IDataObject(DataCache, iface);
1051 return IUnknown_Release(this->outerUnknown);
1054 /************************************************************************
1055 * DataCache_GetData
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(
1062 IDataObject* iface,
1063 LPFORMATETC pformatetcIn,
1064 STGMEDIUM* pmedium)
1066 HRESULT hr = 0;
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;
1073 void *mfBits = 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);
1084 if (hr != S_OK)
1085 goto cleanup;
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);
1091 if (hr != S_OK)
1092 goto cleanup;
1094 /* Save it to storage */
1096 hr = OleSave(pPersistStorage, pStorage, FALSE);
1098 if (hr != S_OK)
1099 goto cleanup;
1101 /* Open the Presentation data srteam */
1103 hr = IStorage_OpenStream(pStorage, name, 0, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &pStream);
1105 if (hr != S_OK)
1106 goto cleanup;
1108 /* Read the presentation header */
1110 hr = IStream_Read(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
1112 if (hr != S_OK)
1113 goto cleanup;
1115 mfBits = HeapAlloc(GetProcessHeap(), 0, pdh.dwSize);
1117 /* Read the Metafile bits */
1119 hr = IStream_Read(pStream, mfBits, pdh.dwSize, NULL);
1121 if (hr != S_OK)
1122 goto cleanup;
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;
1136 hrRet = S_OK;
1138 cleanup:
1140 if (mfBits)
1141 HeapFree(GetProcessHeap(), 0, mfBits);
1143 if (pStream)
1144 IStream_Release(pStream);
1146 if (pStorage)
1147 IStorage_Release(pStorage);
1149 if (pPersistStorage)
1150 IPersistStorage_Release(pPersistStorage);
1152 return hrRet;
1155 /* TODO: Other formats are not implemented */
1157 return E_NOTIMPL;
1160 static HRESULT WINAPI DataCache_GetDataHere(
1161 IDataObject* iface,
1162 LPFORMATETC pformatetc,
1163 STGMEDIUM* pmedium)
1165 FIXME("stub\n");
1166 return E_NOTIMPL;
1169 static HRESULT WINAPI DataCache_QueryGetData(
1170 IDataObject* iface,
1171 LPFORMATETC pformatetc)
1173 FIXME("stub\n");
1174 return E_NOTIMPL;
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(
1185 IDataObject* iface,
1186 LPFORMATETC pformatectIn,
1187 LPFORMATETC pformatetcOut)
1189 TRACE("()\n");
1190 return E_NOTIMPL;
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(
1201 IDataObject* iface,
1202 LPFORMATETC pformatetc,
1203 STGMEDIUM* pmedium,
1204 BOOL fRelease)
1206 IOleCache2* oleCache = NULL;
1207 HRESULT hres;
1209 TRACE("(%p, %p, %p, %d)\n", iface, pformatetc, pmedium, fRelease);
1211 hres = IDataObject_QueryInterface(iface, &IID_IOleCache2, (void**)&oleCache);
1213 if (FAILED(hres))
1214 return E_UNEXPECTED;
1216 hres = IOleCache2_SetData(oleCache, pformatetc, pmedium, fRelease);
1218 IOleCache2_Release(oleCache);
1220 return hres;
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(
1231 IDataObject* iface,
1232 DWORD dwDirection,
1233 IEnumFORMATETC** ppenumFormatEtc)
1235 TRACE("()\n");
1236 return E_NOTIMPL;
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(
1247 IDataObject* iface,
1248 FORMATETC* pformatetc,
1249 DWORD advf,
1250 IAdviseSink* pAdvSink,
1251 DWORD* pdwConnection)
1253 TRACE("()\n");
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(
1265 IDataObject* iface,
1266 DWORD dwConnection)
1268 TRACE("()\n");
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(
1280 IDataObject* iface,
1281 IEnumSTATDATA** ppenumAdvise)
1283 TRACE("()\n");
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,
1299 REFIID riid,
1300 void** ppvObject)
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,
1342 CLSID* pClassID)
1344 TRACE("(%p, %p)\n", iface, pClassID);
1345 return E_NOTIMPL;
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);
1361 return S_FALSE;
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,
1374 IStorage* pStg)
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,
1393 IStorage* pStg)
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);
1410 return S_OK;
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
1419 * storage.
1421 * See Windows documentation for more details on IPersistStorage methods.
1423 static HRESULT WINAPI DataCache_Save(
1424 IPersistStorage* iface,
1425 IStorage* pStg,
1426 BOOL fSameAsLoad)
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,
1437 NULL,
1438 NULL,
1439 pStg);
1442 return S_OK;
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,
1455 IStorage* pStgNew)
1457 TRACE("(%p, %p)\n", iface, pStgNew);
1459 if (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);
1474 return S_OK;
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;
1498 return S_OK;
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,
1513 REFIID riid,
1514 void** ppvObject)
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,
1557 DWORD dwDrawAspect,
1558 LONG lindex,
1559 void* pvAspect,
1560 DVTARGETDEVICE* ptd,
1561 HDC hdcTargetDev,
1562 HDC hdcDraw,
1563 LPCRECTL lprcBounds,
1564 LPCRECTL lprcWBounds,
1565 BOOL (CALLBACK *pfnContinue)(ULONG_PTR dwContinue),
1566 DWORD dwContinue)
1568 PresentationDataHeader presData;
1569 HMETAFILE presMetafile = 0;
1570 HRESULT hres;
1572 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1574 TRACE("(%p, %lx, %ld, %p, %p, %p, %p, %p, %p, %lx)\n",
1575 iface,
1576 dwDrawAspect,
1577 lindex,
1578 pvAspect,
1579 hdcTargetDev,
1580 hdcDraw,
1581 lprcBounds,
1582 lprcWBounds,
1583 pfnContinue,
1584 dwContinue);
1587 * Sanity check
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,
1597 dwDrawAspect,
1598 &presData);
1600 if (FAILED(hres))
1601 return hres;
1604 * Then, we can extract the metafile itself from the cached
1605 * data.
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,
1611 dwDrawAspect);
1614 * If we have a metafile, just draw baby...
1615 * We have to be careful not to modify the state of the
1616 * DC.
1618 if (presMetafile!=0)
1620 INT prevMapMode = SetMapMode(hdcDraw, MM_ANISOTROPIC);
1621 SIZE oldWindowExt;
1622 SIZE oldViewportExt;
1623 POINT oldViewportOrg;
1625 SetWindowExtEx(hdcDraw,
1626 presData.dwObjectExtentX,
1627 presData.dwObjectExtentY,
1628 &oldWindowExt);
1630 SetViewportExtEx(hdcDraw,
1631 lprcBounds->right - lprcBounds->left,
1632 lprcBounds->bottom - lprcBounds->top,
1633 &oldViewportExt);
1635 SetViewportOrgEx(hdcDraw,
1636 lprcBounds->left,
1637 lprcBounds->top,
1638 &oldViewportOrg);
1640 PlayMetaFile(hdcDraw, presMetafile);
1642 SetWindowExtEx(hdcDraw,
1643 oldWindowExt.cx,
1644 oldWindowExt.cy,
1645 NULL);
1647 SetViewportExtEx(hdcDraw,
1648 oldViewportExt.cx,
1649 oldViewportExt.cy,
1650 NULL);
1652 SetViewportOrgEx(hdcDraw,
1653 oldViewportOrg.x,
1654 oldViewportOrg.y,
1655 NULL);
1657 SetMapMode(hdcDraw, prevMapMode);
1659 DeleteMetaFile(presMetafile);
1662 return S_OK;
1665 static HRESULT WINAPI DataCache_GetColorSet(
1666 IViewObject2* iface,
1667 DWORD dwDrawAspect,
1668 LONG lindex,
1669 void* pvAspect,
1670 DVTARGETDEVICE* ptd,
1671 HDC hicTargetDevice,
1672 LOGPALETTE** ppColorSet)
1674 FIXME("stub\n");
1675 return E_NOTIMPL;
1678 static HRESULT WINAPI DataCache_Freeze(
1679 IViewObject2* iface,
1680 DWORD dwDrawAspect,
1681 LONG lindex,
1682 void* pvAspect,
1683 DWORD* pdwFreeze)
1685 FIXME("stub\n");
1686 return E_NOTIMPL;
1689 static HRESULT WINAPI DataCache_Unfreeze(
1690 IViewObject2* iface,
1691 DWORD dwFreeze)
1693 FIXME("stub\n");
1694 return E_NOTIMPL;
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,
1707 DWORD aspects,
1708 DWORD advf,
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.
1729 if (pAdvSink!=NULL)
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
1740 * sink immediately.
1742 if (advf & ADVF_PRIMEFIRST)
1744 DataCache_FireOnViewChange(this,
1745 DVASPECT_CONTENT,
1746 -1);
1749 return S_OK;
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,
1762 DWORD* pAspects,
1763 DWORD* pAdvf,
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.
1773 if (pAspects!=NULL)
1774 *pAspects = this->sinkAspects;
1776 if (pAdvf!=NULL)
1777 *pAdvf = this->sinkAdviseFlag;
1779 if (ppAdvSink!=NULL)
1781 IAdviseSink_QueryInterface(this->sinkInterface,
1782 &IID_IAdviseSink,
1783 (void**)ppAdvSink);
1786 return S_OK;
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,
1798 DWORD dwDrawAspect,
1799 LONG lindex,
1800 DVTARGETDEVICE* ptd,
1801 LPSIZEL lpsizel)
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);
1812 * Sanity check
1814 if (lpsizel==NULL)
1815 return E_POINTER;
1818 * Initialize the out parameter.
1820 lpsizel->cx = 0;
1821 lpsizel->cy = 0;
1824 * This flag should be set to -1.
1826 if (lindex!=-1)
1827 FIXME("Unimplemented flag lindex = %ld\n", lindex);
1830 * Right now, we support only the callback from
1831 * the default handler.
1833 if (ptd!=NULL)
1834 FIXME("Unimplemented ptd = %p\n", ptd);
1837 * Get the presentation information from the
1838 * cache.
1840 hres = DataCache_ReadPresentationData(this,
1841 dwDrawAspect,
1842 &presData);
1844 if (SUCCEEDED(hres))
1846 lpsizel->cx = presData.dwObjectExtentX;
1847 lpsizel->cy = presData.dwObjectExtentY;
1851 * This method returns OLE_E_BLANK when it fails.
1853 if (FAILED(hres))
1854 hres = OLE_E_BLANK;
1856 return hres;
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(
1871 IOleCache2* iface,
1872 REFIID riid,
1873 void** ppvObject)
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(
1886 IOleCache2* iface)
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(
1899 IOleCache2* iface)
1901 _ICOM_THIS_From_IOleCache2(DataCache, iface);
1903 return IUnknown_Release(this->outerUnknown);
1906 static HRESULT WINAPI DataCache_Cache(
1907 IOleCache2* iface,
1908 FORMATETC* pformatetc,
1909 DWORD advf,
1910 DWORD* pdwConnection)
1912 FIXME("stub\n");
1913 return E_NOTIMPL;
1916 static HRESULT WINAPI DataCache_Uncache(
1917 IOleCache2* iface,
1918 DWORD dwConnection)
1920 FIXME("stub\n");
1921 return E_NOTIMPL;
1924 static HRESULT WINAPI DataCache_EnumCache(
1925 IOleCache2* iface,
1926 IEnumSTATDATA** ppenumSTATDATA)
1928 FIXME("stub\n");
1929 return E_NOTIMPL;
1932 static HRESULT WINAPI DataCache_InitCache(
1933 IOleCache2* iface,
1934 IDataObject* pDataObject)
1936 FIXME("stub\n");
1937 return E_NOTIMPL;
1940 static HRESULT WINAPI DataCache_IOleCache2_SetData(
1941 IOleCache2* iface,
1942 FORMATETC* pformatetc,
1943 STGMEDIUM* pmedium,
1944 BOOL fRelease)
1946 FIXME("stub\n");
1947 return E_NOTIMPL;
1950 static HRESULT WINAPI DataCache_UpdateCache(
1951 IOleCache2* iface,
1952 LPDATAOBJECT pDataObject,
1953 DWORD grfUpdf,
1954 LPVOID pReserved)
1956 FIXME("stub\n");
1957 return E_NOTIMPL;
1960 static HRESULT WINAPI DataCache_DiscardCache(
1961 IOleCache2* iface,
1962 DWORD dwDiscardOptions)
1964 FIXME("stub\n");
1965 return E_NOTIMPL;
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,
1981 REFIID riid,
1982 void** ppvObject)
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)
2019 FIXME("stub\n");
2020 return E_NOTIMPL;
2023 static HRESULT WINAPI DataCache_OnStop(
2024 IOleCacheControl* iface)
2026 FIXME("stub\n");
2027 return E_NOTIMPL;