Use the Unicode string functions from wine/unicode.h instead of the
[wine.git] / dlls / ole32 / datacache.c
blob2c6f541150120c56df2c58f09e83a64ff391f1d9
1 /*
2 * OLE 2 Data cache
4 * Copyright 1999 Francis Beaudet
5 * Copyright 2000 Abey George
7 * NOTES:
8 * The OLE2 data cache supports a whole whack of
9 * interfaces including:
10 * IDataObject, IPersistStorage, IViewObject2,
11 * IOleCache2 and IOleCacheControl.
13 * Most of the implementation details are taken from: Inside OLE
14 * second edition by Kraig Brockschmidt,
16 * NOTES
17 * - This implementation of the datacache will let your application
18 * load documents that have embedded OLE objects in them and it will
19 * also retrieve the metafile representation of those objects.
20 * - This implementation of the datacache will also allow your
21 * application to save new documents with OLE objects in them.
22 * - The main thing that it doesn't do is allow you to activate
23 * or modify the OLE objects in any way.
24 * - I haven't found any good documentation on the real usage of
25 * the streams created by the data cache. In particular, How to
26 * determine what the XXX stands for in the stream name
27 * "\002OlePresXXX". It appears to just be a counter.
28 * - Also, I don't know the real content of the presentation stream
29 * header. I was able to figure-out where the extent of the object
30 * was stored and the aspect, but that's about it.
32 #include <assert.h>
33 #include "windef.h"
34 #include "winbase.h"
35 #include "wingdi.h"
36 #include "winuser.h"
37 #include "winerror.h"
38 #include "crtdll.h"
39 #include "wine/obj_oleview.h"
40 #include "wine/obj_cache.h"
41 #include "wine/unicode.h"
42 #include "ole2.h"
43 #include "debugtools.h"
45 DEFAULT_DEBUG_CHANNEL(ole);
47 /****************************************************************************
48 * PresentationDataHeader
50 * This structure represents the header of the \002OlePresXXX stream in
51 * the OLE object strorage.
53 * Most fields are still unknown.
55 typedef struct PresentationDataHeader
57 DWORD unknown1; /* -1 */
58 DWORD unknown2; /* 3, possibly CF_METAFILEPICT */
59 DWORD unknown3; /* 4, possibly TYMED_ISTREAM */
60 DVASPECT dvAspect;
61 DWORD unknown5; /* -1 */
63 DWORD unknown6;
64 DWORD unknown7; /* 0 */
65 DWORD dwObjectExtentX;
66 DWORD dwObjectExtentY;
67 DWORD dwSize;
68 } PresentationDataHeader;
70 /****************************************************************************
71 * DataCache
73 struct DataCache
76 * List all interface VTables here
78 ICOM_VTABLE(IDataObject)* lpvtbl1;
79 ICOM_VTABLE(IUnknown)* lpvtbl2;
80 ICOM_VTABLE(IPersistStorage)* lpvtbl3;
81 ICOM_VTABLE(IViewObject2)* lpvtbl4;
82 ICOM_VTABLE(IOleCache2)* lpvtbl5;
83 ICOM_VTABLE(IOleCacheControl)* lpvtbl6;
86 * Reference count of this object
88 ULONG ref;
91 * IUnknown implementation of the outer object.
93 IUnknown* outerUnknown;
96 * This storage pointer is set through a call to
97 * IPersistStorage_Load. This is where the visual
98 * representation of the object is stored.
100 IStorage* presentationStorage;
103 * The user of this object can setup ONE advise sink
104 * connection with the object. These parameters describe
105 * that connection.
107 DWORD sinkAspects;
108 DWORD sinkAdviseFlag;
109 IAdviseSink* sinkInterface;
113 typedef struct DataCache DataCache;
116 * Here, I define utility macros to help with the casting of the
117 * "this" parameter.
118 * There is a version to accomodate all of the VTables implemented
119 * by this object.
121 #define _ICOM_THIS_From_IDataObject(class,name) class* this = (class*)name;
122 #define _ICOM_THIS_From_NDIUnknown(class, name) class* this = (class*)(((char*)name)-sizeof(void*));
123 #define _ICOM_THIS_From_IPersistStorage(class, name) class* this = (class*)(((char*)name)-2*sizeof(void*));
124 #define _ICOM_THIS_From_IViewObject2(class, name) class* this = (class*)(((char*)name)-3*sizeof(void*));
125 #define _ICOM_THIS_From_IOleCache2(class, name) class* this = (class*)(((char*)name)-4*sizeof(void*));
126 #define _ICOM_THIS_From_IOleCacheControl(class, name) class* this = (class*)(((char*)name)-5*sizeof(void*));
129 * Prototypes for the methods of the DataCache class.
131 static DataCache* DataCache_Construct(REFCLSID clsid,
132 LPUNKNOWN pUnkOuter);
133 static void DataCache_Destroy(DataCache* ptrToDestroy);
134 static HRESULT DataCache_ReadPresentationData(DataCache* this,
135 DWORD drawAspect,
136 PresentationDataHeader* header);
137 static HRESULT DataCache_OpenPresStream(DataCache *this,
138 DWORD drawAspect,
139 IStream **pStm);
140 static HMETAFILE DataCache_ReadPresMetafile(DataCache* this,
141 DWORD drawAspect);
142 static void DataCache_FireOnViewChange(DataCache* this,
143 DWORD aspect,
144 LONG lindex);
147 * Prototypes for the methods of the DataCache class
148 * that implement non delegating IUnknown methods.
150 static HRESULT WINAPI DataCache_NDIUnknown_QueryInterface(
151 IUnknown* iface,
152 REFIID riid,
153 void** ppvObject);
154 static ULONG WINAPI DataCache_NDIUnknown_AddRef(
155 IUnknown* iface);
156 static ULONG WINAPI DataCache_NDIUnknown_Release(
157 IUnknown* iface);
160 * Prototypes for the methods of the DataCache class
161 * that implement IDataObject methods.
163 static HRESULT WINAPI DataCache_IDataObject_QueryInterface(
164 IDataObject* iface,
165 REFIID riid,
166 void** ppvObject);
167 static ULONG WINAPI DataCache_IDataObject_AddRef(
168 IDataObject* iface);
169 static ULONG WINAPI DataCache_IDataObject_Release(
170 IDataObject* iface);
171 static HRESULT WINAPI DataCache_GetData(
172 IDataObject* iface,
173 LPFORMATETC pformatetcIn,
174 STGMEDIUM* pmedium);
175 static HRESULT WINAPI DataCache_GetDataHere(
176 IDataObject* iface,
177 LPFORMATETC pformatetc,
178 STGMEDIUM* pmedium);
179 static HRESULT WINAPI DataCache_QueryGetData(
180 IDataObject* iface,
181 LPFORMATETC pformatetc);
182 static HRESULT WINAPI DataCache_GetCanonicalFormatEtc(
183 IDataObject* iface,
184 LPFORMATETC pformatectIn,
185 LPFORMATETC pformatetcOut);
186 static HRESULT WINAPI DataCache_IDataObject_SetData(
187 IDataObject* iface,
188 LPFORMATETC pformatetc,
189 STGMEDIUM* pmedium,
190 BOOL fRelease);
191 static HRESULT WINAPI DataCache_EnumFormatEtc(
192 IDataObject* iface,
193 DWORD dwDirection,
194 IEnumFORMATETC** ppenumFormatEtc);
195 static HRESULT WINAPI DataCache_DAdvise(
196 IDataObject* iface,
197 FORMATETC* pformatetc,
198 DWORD advf,
199 IAdviseSink* pAdvSink,
200 DWORD* pdwConnection);
201 static HRESULT WINAPI DataCache_DUnadvise(
202 IDataObject* iface,
203 DWORD dwConnection);
204 static HRESULT WINAPI DataCache_EnumDAdvise(
205 IDataObject* iface,
206 IEnumSTATDATA** ppenumAdvise);
209 * Prototypes for the methods of the DataCache class
210 * that implement IPersistStorage methods.
212 static HRESULT WINAPI DataCache_IPersistStorage_QueryInterface(
213 IPersistStorage* iface,
214 REFIID riid,
215 void** ppvObject);
216 static ULONG WINAPI DataCache_IPersistStorage_AddRef(
217 IPersistStorage* iface);
218 static ULONG WINAPI DataCache_IPersistStorage_Release(
219 IPersistStorage* iface);
220 static HRESULT WINAPI DataCache_GetClassID(
221 IPersistStorage* iface,
222 CLSID* pClassID);
223 static HRESULT WINAPI DataCache_IsDirty(
224 IPersistStorage* iface);
225 static HRESULT WINAPI DataCache_InitNew(
226 IPersistStorage* iface,
227 IStorage* pStg);
228 static HRESULT WINAPI DataCache_Load(
229 IPersistStorage* iface,
230 IStorage* pStg);
231 static HRESULT WINAPI DataCache_Save(
232 IPersistStorage* iface,
233 IStorage* pStg,
234 BOOL fSameAsLoad);
235 static HRESULT WINAPI DataCache_SaveCompleted(
236 IPersistStorage* iface,
237 IStorage* pStgNew);
238 static HRESULT WINAPI DataCache_HandsOffStorage(
239 IPersistStorage* iface);
242 * Prototypes for the methods of the DataCache class
243 * that implement IViewObject2 methods.
245 static HRESULT WINAPI DataCache_IViewObject2_QueryInterface(
246 IViewObject2* iface,
247 REFIID riid,
248 void** ppvObject);
249 static ULONG WINAPI DataCache_IViewObject2_AddRef(
250 IViewObject2* iface);
251 static ULONG WINAPI DataCache_IViewObject2_Release(
252 IViewObject2* iface);
253 static HRESULT WINAPI DataCache_Draw(
254 IViewObject2* iface,
255 DWORD dwDrawAspect,
256 LONG lindex,
257 void* pvAspect,
258 DVTARGETDEVICE* ptd,
259 HDC hdcTargetDev,
260 HDC hdcDraw,
261 LPCRECTL lprcBounds,
262 LPCRECTL lprcWBounds,
263 IVO_ContCallback pfnContinue,
264 DWORD dwContinue);
265 static HRESULT WINAPI DataCache_GetColorSet(
266 IViewObject2* iface,
267 DWORD dwDrawAspect,
268 LONG lindex,
269 void* pvAspect,
270 DVTARGETDEVICE* ptd,
271 HDC hicTargetDevice,
272 LOGPALETTE** ppColorSet);
273 static HRESULT WINAPI DataCache_Freeze(
274 IViewObject2* iface,
275 DWORD dwDrawAspect,
276 LONG lindex,
277 void* pvAspect,
278 DWORD* pdwFreeze);
279 static HRESULT WINAPI DataCache_Unfreeze(
280 IViewObject2* iface,
281 DWORD dwFreeze);
282 static HRESULT WINAPI DataCache_SetAdvise(
283 IViewObject2* iface,
284 DWORD aspects,
285 DWORD advf,
286 IAdviseSink* pAdvSink);
287 static HRESULT WINAPI DataCache_GetAdvise(
288 IViewObject2* iface,
289 DWORD* pAspects,
290 DWORD* pAdvf,
291 IAdviseSink** ppAdvSink);
292 static HRESULT WINAPI DataCache_GetExtent(
293 IViewObject2* iface,
294 DWORD dwDrawAspect,
295 LONG lindex,
296 DVTARGETDEVICE* ptd,
297 LPSIZEL lpsizel);
300 * Prototypes for the methods of the DataCache class
301 * that implement IOleCache2 methods.
303 static HRESULT WINAPI DataCache_IOleCache2_QueryInterface(
304 IOleCache2* iface,
305 REFIID riid,
306 void** ppvObject);
307 static ULONG WINAPI DataCache_IOleCache2_AddRef(
308 IOleCache2* iface);
309 static ULONG WINAPI DataCache_IOleCache2_Release(
310 IOleCache2* iface);
311 static HRESULT WINAPI DataCache_Cache(
312 IOleCache2* iface,
313 FORMATETC* pformatetc,
314 DWORD advf,
315 DWORD* pdwConnection);
316 static HRESULT WINAPI DataCache_Uncache(
317 IOleCache2* iface,
318 DWORD dwConnection);
319 static HRESULT WINAPI DataCache_EnumCache(
320 IOleCache2* iface,
321 IEnumSTATDATA** ppenumSTATDATA);
322 static HRESULT WINAPI DataCache_InitCache(
323 IOleCache2* iface,
324 IDataObject* pDataObject);
325 static HRESULT WINAPI DataCache_IOleCache2_SetData(
326 IOleCache2* iface,
327 FORMATETC* pformatetc,
328 STGMEDIUM* pmedium,
329 BOOL fRelease);
330 static HRESULT WINAPI DataCache_UpdateCache(
331 IOleCache2* iface,
332 LPDATAOBJECT pDataObject,
333 DWORD grfUpdf,
334 LPVOID pReserved);
335 static HRESULT WINAPI DataCache_DiscardCache(
336 IOleCache2* iface,
337 DWORD dwDiscardOptions);
340 * Prototypes for the methods of the DataCache class
341 * that implement IOleCacheControl methods.
343 static HRESULT WINAPI DataCache_IOleCacheControl_QueryInterface(
344 IOleCacheControl* iface,
345 REFIID riid,
346 void** ppvObject);
347 static ULONG WINAPI DataCache_IOleCacheControl_AddRef(
348 IOleCacheControl* iface);
349 static ULONG WINAPI DataCache_IOleCacheControl_Release(
350 IOleCacheControl* iface);
351 static HRESULT WINAPI DataCache_OnRun(
352 IOleCacheControl* iface,
353 LPDATAOBJECT pDataObject);
354 static HRESULT WINAPI DataCache_OnStop(
355 IOleCacheControl* iface);
358 * Virtual function tables for the DataCache class.
360 static ICOM_VTABLE(IUnknown) DataCache_NDIUnknown_VTable =
362 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
363 DataCache_NDIUnknown_QueryInterface,
364 DataCache_NDIUnknown_AddRef,
365 DataCache_NDIUnknown_Release
368 static ICOM_VTABLE(IDataObject) DataCache_IDataObject_VTable =
370 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
371 DataCache_IDataObject_QueryInterface,
372 DataCache_IDataObject_AddRef,
373 DataCache_IDataObject_Release,
374 DataCache_GetData,
375 DataCache_GetDataHere,
376 DataCache_QueryGetData,
377 DataCache_GetCanonicalFormatEtc,
378 DataCache_IDataObject_SetData,
379 DataCache_EnumFormatEtc,
380 DataCache_DAdvise,
381 DataCache_DUnadvise,
382 DataCache_EnumDAdvise
385 static ICOM_VTABLE(IPersistStorage) DataCache_IPersistStorage_VTable =
387 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
388 DataCache_IPersistStorage_QueryInterface,
389 DataCache_IPersistStorage_AddRef,
390 DataCache_IPersistStorage_Release,
391 DataCache_GetClassID,
392 DataCache_IsDirty,
393 DataCache_InitNew,
394 DataCache_Load,
395 DataCache_Save,
396 DataCache_SaveCompleted,
397 DataCache_HandsOffStorage
400 static ICOM_VTABLE(IViewObject2) DataCache_IViewObject2_VTable =
402 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
403 DataCache_IViewObject2_QueryInterface,
404 DataCache_IViewObject2_AddRef,
405 DataCache_IViewObject2_Release,
406 DataCache_Draw,
407 DataCache_GetColorSet,
408 DataCache_Freeze,
409 DataCache_Unfreeze,
410 DataCache_SetAdvise,
411 DataCache_GetAdvise,
412 DataCache_GetExtent
415 static ICOM_VTABLE(IOleCache2) DataCache_IOleCache2_VTable =
417 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
418 DataCache_IOleCache2_QueryInterface,
419 DataCache_IOleCache2_AddRef,
420 DataCache_IOleCache2_Release,
421 DataCache_Cache,
422 DataCache_Uncache,
423 DataCache_EnumCache,
424 DataCache_InitCache,
425 DataCache_IOleCache2_SetData,
426 DataCache_UpdateCache,
427 DataCache_DiscardCache
430 static ICOM_VTABLE(IOleCacheControl) DataCache_IOleCacheControl_VTable =
432 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
433 DataCache_IOleCacheControl_QueryInterface,
434 DataCache_IOleCacheControl_AddRef,
435 DataCache_IOleCacheControl_Release,
436 DataCache_OnRun,
437 DataCache_OnStop
440 /******************************************************************************
441 * CreateDataCache [OLE32.54]
443 HRESULT WINAPI CreateDataCache(
444 LPUNKNOWN pUnkOuter,
445 REFCLSID rclsid,
446 REFIID riid,
447 LPVOID* ppvObj)
449 DataCache* newCache = NULL;
450 HRESULT hr = S_OK;
452 TRACE("(%s, %p, %s, %p)\n", debugstr_guid(rclsid), pUnkOuter, debugstr_guid(riid), ppvObj);
455 * Sanity check
457 if (ppvObj==0)
458 return E_POINTER;
460 *ppvObj = 0;
463 * If this cache is constructed for aggregation, make sure
464 * the caller is requesting the IUnknown interface.
465 * This is necessary because it's the only time the non-delegating
466 * IUnknown pointer can be returned to the outside.
468 if ( (pUnkOuter!=NULL) &&
469 (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) != 0) )
470 return CLASS_E_NOAGGREGATION;
473 * Try to construct a new instance of the class.
475 newCache = DataCache_Construct(rclsid,
476 pUnkOuter);
478 if (newCache == 0)
479 return E_OUTOFMEMORY;
482 * Make sure it supports the interface required by the caller.
484 hr = IUnknown_QueryInterface((IUnknown*)&(newCache->lpvtbl2), riid, ppvObj);
487 * Release the reference obtained in the constructor. If
488 * the QueryInterface was unsuccessful, it will free the class.
490 IUnknown_Release((IUnknown*)&(newCache->lpvtbl2));
492 return hr;
495 /*********************************************************
496 * Method implementation for DataCache class.
498 static DataCache* DataCache_Construct(
499 REFCLSID clsid,
500 LPUNKNOWN pUnkOuter)
502 DataCache* newObject = 0;
505 * Allocate space for the object.
507 newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(DataCache));
509 if (newObject==0)
510 return newObject;
513 * Initialize the virtual function table.
515 newObject->lpvtbl1 = &DataCache_IDataObject_VTable;
516 newObject->lpvtbl2 = &DataCache_NDIUnknown_VTable;
517 newObject->lpvtbl3 = &DataCache_IPersistStorage_VTable;
518 newObject->lpvtbl4 = &DataCache_IViewObject2_VTable;
519 newObject->lpvtbl5 = &DataCache_IOleCache2_VTable;
520 newObject->lpvtbl6 = &DataCache_IOleCacheControl_VTable;
523 * Start with one reference count. The caller of this function
524 * must release the interface pointer when it is done.
526 newObject->ref = 1;
529 * Initialize the outer unknown
530 * We don't keep a reference on the outer unknown since, the way
531 * aggregation works, our lifetime is at least as large as it's
532 * lifetime.
534 if (pUnkOuter==NULL)
535 pUnkOuter = (IUnknown*)&(newObject->lpvtbl2);
537 newObject->outerUnknown = pUnkOuter;
540 * Initialize the other members of the structure.
542 newObject->presentationStorage = NULL;
543 newObject->sinkAspects = 0;
544 newObject->sinkAdviseFlag = 0;
545 newObject->sinkInterface = 0;
547 return newObject;
550 static void DataCache_Destroy(
551 DataCache* ptrToDestroy)
553 TRACE("()\n");
555 if (ptrToDestroy->sinkInterface != NULL)
557 IAdviseSink_Release(ptrToDestroy->sinkInterface);
558 ptrToDestroy->sinkInterface = NULL;
561 if (ptrToDestroy->presentationStorage != NULL)
563 IStorage_Release(ptrToDestroy->presentationStorage);
564 ptrToDestroy->presentationStorage = NULL;
568 * Free the datacache pointer.
570 HeapFree(GetProcessHeap(), 0, ptrToDestroy);
573 /************************************************************************
574 * DataCache_ReadPresentationData
576 * This method will read information for the requested presentation
577 * into the given structure.
579 * Param:
580 * this - Pointer to the DataCache object
581 * drawAspect - The aspect of the object that we wish to draw.
582 * header - The structure containing information about this
583 * aspect of the object.
585 static HRESULT DataCache_ReadPresentationData(
586 DataCache* this,
587 DWORD drawAspect,
588 PresentationDataHeader* header)
590 IStream* presStream = NULL;
591 HRESULT hres;
594 * Open the presentation stream.
596 hres = DataCache_OpenPresStream(
597 this,
598 drawAspect,
599 &presStream);
601 if (FAILED(hres))
602 return hres;
605 * Read the header.
608 hres = IStream_Read(
609 presStream,
610 header,
611 sizeof(PresentationDataHeader),
612 NULL);
615 * Cleanup.
617 IStream_Release(presStream);
620 * We don't want to propagate any other error
621 * code than a failure.
623 if (hres!=S_OK)
624 hres = E_FAIL;
626 return hres;
629 /************************************************************************
630 * DataCache_FireOnViewChange
632 * This method will fire an OnViewChange notification to the advise
633 * sink registered with the datacache.
635 * See IAdviseSink::OnViewChange for more details.
637 static void DataCache_FireOnViewChange(
638 DataCache* this,
639 DWORD aspect,
640 LONG lindex)
642 TRACE("(%p, %lx, %ld)\n", this, aspect, lindex);
645 * The sink supplies a filter when it registers
646 * we make sure we only send the notifications when that
647 * filter matches.
649 if ((this->sinkAspects & aspect) != 0)
651 if (this->sinkInterface != NULL)
653 IAdviseSink_OnViewChange(this->sinkInterface,
654 aspect,
655 lindex);
658 * Some sinks want to be unregistered automatically when
659 * the first notification goes out.
661 if ( (this->sinkAdviseFlag & ADVF_ONLYONCE) != 0)
663 IAdviseSink_Release(this->sinkInterface);
665 this->sinkInterface = NULL;
666 this->sinkAspects = 0;
667 this->sinkAdviseFlag = 0;
673 /* Helper for DataCache_OpenPresStream */
674 static BOOL DataCache_IsPresentationStream(const STATSTG *elem)
676 /* The presentation streams have names of the form "\002OlePresXXX",
677 * where XXX goes from 000 to 999. */
678 static const WCHAR OlePres[] = { 2,'O','l','e','P','r','e','s' };
680 LPCWSTR name = elem->pwcsName;
682 return (elem->type == STGTY_STREAM)
683 && (elem->cbSize.s.LowPart >= sizeof(PresentationDataHeader))
684 && (strlenW(name) == 11)
685 && (strncmpW(name, OlePres, 8) == 0)
686 && CRTDLL_iswdigit(name[8])
687 && CRTDLL_iswdigit(name[9])
688 && CRTDLL_iswdigit(name[10]);
691 /************************************************************************
692 * DataCache_OpenPresStream
694 * This method will find the stream for the given presentation. It makes
695 * no attempt at fallback.
697 * Param:
698 * this - Pointer to the DataCache object
699 * drawAspect - The aspect of the object that we wish to draw.
700 * pStm - A returned stream. It points to the beginning of the
701 * - presentation data, including the header.
703 * Errors:
704 * S_OK The requested stream has been opened.
705 * OLE_E_BLANK The requested stream could not be found.
706 * Quite a few others I'm too lazy to map correctly.
708 * Notes:
709 * Algorithm: Scan the elements of the presentation storage, looking
710 * for presentation streams. For each presentation stream,
711 * load the header and check to see if the aspect maches.
713 * If a fallback is desired, just opening the first presentation stream
714 * is a possibility.
716 static HRESULT DataCache_OpenPresStream(
717 DataCache *this,
718 DWORD drawAspect,
719 IStream **ppStm)
721 STATSTG elem;
722 IEnumSTATSTG *pEnum;
723 HRESULT hr;
725 if (!ppStm) return E_POINTER;
727 hr = IStorage_EnumElements(this->presentationStorage, 0, NULL, 0, &pEnum);
728 if (FAILED(hr)) return hr;
730 while ((hr = IEnumSTATSTG_Next(pEnum, 1, &elem, NULL)) == S_OK)
732 if (DataCache_IsPresentationStream(&elem))
734 IStream *pStm;
736 hr = IStorage_OpenStream(this->presentationStorage, elem.pwcsName,
737 NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0,
738 &pStm);
739 if (SUCCEEDED(hr))
741 PresentationDataHeader header;
742 ULONG actual_read;
744 hr = IStream_Read(pStm, &header, sizeof(header), &actual_read);
746 /* can't use SUCCEEDED(hr): S_FALSE counts as an error */
747 if (hr == S_OK && actual_read == sizeof(header)
748 && header.dvAspect == drawAspect)
750 /* Rewind the stream before returning it. */
751 LARGE_INTEGER offset;
752 offset.s.LowPart = 0;
753 offset.s.HighPart = 0;
754 IStream_Seek(pStm, offset, STREAM_SEEK_SET, NULL);
756 *ppStm = pStm;
758 CoTaskMemFree(elem.pwcsName);
759 IEnumSTATSTG_Release(pEnum);
761 return S_OK;
764 IStream_Release(pStm);
768 CoTaskMemFree(elem.pwcsName);
771 IEnumSTATSTG_Release(pEnum);
773 return (hr == S_FALSE ? OLE_E_BLANK : hr);
776 /************************************************************************
777 * DataCache_ReadPresentationData
779 * This method will read information for the requested presentation
780 * into the given structure.
782 * Param:
783 * this - Pointer to the DataCache object
784 * drawAspect - The aspect of the object that we wish to draw.
786 * Returns:
787 * This method returns a metafile handle if it is successful.
788 * it will return 0 if not.
790 static HMETAFILE DataCache_ReadPresMetafile(
791 DataCache* this,
792 DWORD drawAspect)
794 LARGE_INTEGER offset;
795 IStream* presStream = NULL;
796 HRESULT hres;
797 void* metafileBits;
798 STATSTG streamInfo;
799 HMETAFILE newMetafile = 0;
802 * Open the presentation stream.
804 hres = DataCache_OpenPresStream(
805 this,
806 drawAspect,
807 &presStream);
809 if (FAILED(hres))
810 return hres;
813 * Get the size of the stream.
815 hres = IStream_Stat(presStream,
816 &streamInfo,
817 STATFLAG_NONAME);
820 * Skip the header
822 offset.s.HighPart = 0;
823 offset.s.LowPart = sizeof(PresentationDataHeader);
825 hres = IStream_Seek(
826 presStream,
827 offset,
828 STREAM_SEEK_SET,
829 NULL);
831 streamInfo.cbSize.s.LowPart -= offset.s.LowPart;
834 * Allocate a buffer for the metafile bits.
836 metafileBits = HeapAlloc(GetProcessHeap(),
838 streamInfo.cbSize.s.LowPart);
841 * Read the metafile bits.
843 hres = IStream_Read(
844 presStream,
845 metafileBits,
846 streamInfo.cbSize.s.LowPart,
847 NULL);
850 * Create a metafile with those bits.
852 if (SUCCEEDED(hres))
854 newMetafile = SetMetaFileBitsEx(streamInfo.cbSize.s.LowPart, metafileBits);
858 * Cleanup.
860 HeapFree(GetProcessHeap(), 0, metafileBits);
861 IStream_Release(presStream);
863 if (newMetafile==0)
864 hres = E_FAIL;
866 return newMetafile;
869 /*********************************************************
870 * Method implementation for the non delegating IUnknown
871 * part of the DataCache class.
874 /************************************************************************
875 * DataCache_NDIUnknown_QueryInterface (IUnknown)
877 * See Windows documentation for more details on IUnknown methods.
879 * This version of QueryInterface will not delegate it's implementation
880 * to the outer unknown.
882 static HRESULT WINAPI DataCache_NDIUnknown_QueryInterface(
883 IUnknown* iface,
884 REFIID riid,
885 void** ppvObject)
887 _ICOM_THIS_From_NDIUnknown(DataCache, iface);
890 * Perform a sanity check on the parameters.
892 if ( (this==0) || (ppvObject==0) )
893 return E_INVALIDARG;
896 * Initialize the return parameter.
898 *ppvObject = 0;
901 * Compare the riid with the interface IDs implemented by this object.
903 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
905 *ppvObject = iface;
907 else if (memcmp(&IID_IDataObject, riid, sizeof(IID_IDataObject)) == 0)
909 *ppvObject = (IDataObject*)&(this->lpvtbl1);
911 else if ( (memcmp(&IID_IPersistStorage, riid, sizeof(IID_IPersistStorage)) == 0) ||
912 (memcmp(&IID_IPersist, riid, sizeof(IID_IPersist)) == 0) )
914 *ppvObject = (IPersistStorage*)&(this->lpvtbl3);
916 else if ( (memcmp(&IID_IViewObject, riid, sizeof(IID_IViewObject)) == 0) ||
917 (memcmp(&IID_IViewObject2, riid, sizeof(IID_IViewObject2)) == 0) )
919 *ppvObject = (IViewObject2*)&(this->lpvtbl4);
921 else if ( (memcmp(&IID_IOleCache, riid, sizeof(IID_IOleCache)) == 0) ||
922 (memcmp(&IID_IOleCache2, riid, sizeof(IID_IOleCache2)) == 0) )
924 *ppvObject = (IOleCache2*)&(this->lpvtbl5);
926 else if (memcmp(&IID_IOleCacheControl, riid, sizeof(IID_IOleCacheControl)) == 0)
928 *ppvObject = (IOleCacheControl*)&(this->lpvtbl6);
932 * Check that we obtained an interface.
934 if ((*ppvObject)==0)
936 WARN( "() : asking for un supported interface %s\n", debugstr_guid(riid));
937 return E_NOINTERFACE;
941 * Query Interface always increases the reference count by one when it is
942 * successful.
944 IUnknown_AddRef((IUnknown*)*ppvObject);
946 return S_OK;;
949 /************************************************************************
950 * DataCache_NDIUnknown_AddRef (IUnknown)
952 * See Windows documentation for more details on IUnknown methods.
954 * This version of QueryInterface will not delegate it's implementation
955 * to the outer unknown.
957 static ULONG WINAPI DataCache_NDIUnknown_AddRef(
958 IUnknown* iface)
960 _ICOM_THIS_From_NDIUnknown(DataCache, iface);
962 this->ref++;
964 return this->ref;
967 /************************************************************************
968 * DataCache_NDIUnknown_Release (IUnknown)
970 * See Windows documentation for more details on IUnknown methods.
972 * This version of QueryInterface will not delegate it's implementation
973 * to the outer unknown.
975 static ULONG WINAPI DataCache_NDIUnknown_Release(
976 IUnknown* iface)
978 _ICOM_THIS_From_NDIUnknown(DataCache, iface);
981 * Decrease the reference count on this object.
983 this->ref--;
986 * If the reference count goes down to 0, perform suicide.
988 if (this->ref==0)
990 DataCache_Destroy(this);
992 return 0;
995 return this->ref;
998 /*********************************************************
999 * Method implementation for the IDataObject
1000 * part of the DataCache class.
1003 /************************************************************************
1004 * DataCache_IDataObject_QueryInterface (IUnknown)
1006 * See Windows documentation for more details on IUnknown methods.
1008 static HRESULT WINAPI DataCache_IDataObject_QueryInterface(
1009 IDataObject* iface,
1010 REFIID riid,
1011 void** ppvObject)
1013 _ICOM_THIS_From_IDataObject(DataCache, iface);
1015 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1018 /************************************************************************
1019 * DataCache_IDataObject_AddRef (IUnknown)
1021 * See Windows documentation for more details on IUnknown methods.
1023 static ULONG WINAPI DataCache_IDataObject_AddRef(
1024 IDataObject* iface)
1026 _ICOM_THIS_From_IDataObject(DataCache, iface);
1028 return IUnknown_AddRef(this->outerUnknown);
1031 /************************************************************************
1032 * DataCache_IDataObject_Release (IUnknown)
1034 * See Windows documentation for more details on IUnknown methods.
1036 static ULONG WINAPI DataCache_IDataObject_Release(
1037 IDataObject* iface)
1039 _ICOM_THIS_From_IDataObject(DataCache, iface);
1041 return IUnknown_Release(this->outerUnknown);
1044 /************************************************************************
1045 * DataCache_GetData
1047 * Get Data from a source dataobject using format pformatetcIn->cfFormat
1048 * See Windows documentation for more details on GetData.
1049 * TODO: Currently only CF_METAFILEPICT is implemented
1051 static HRESULT WINAPI DataCache_GetData(
1052 IDataObject* iface,
1053 LPFORMATETC pformatetcIn,
1054 STGMEDIUM* pmedium)
1056 HRESULT hr = 0;
1057 HRESULT hrRet = E_UNEXPECTED;
1058 IPersistStorage *pPersistStorage = 0;
1059 IStorage *pStorage = 0;
1060 IStream *pStream = 0;
1061 OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
1062 HGLOBAL hGlobalMF = 0;
1063 void *mfBits = 0;
1064 PresentationDataHeader pdh;
1065 METAFILEPICT *mfPict;
1066 HMETAFILE hMetaFile = 0;
1068 if (pformatetcIn->cfFormat == CF_METAFILEPICT)
1070 /* Get the Persist Storage */
1072 hr = IDataObject_QueryInterface(iface, &IID_IPersistStorage, (void**)&pPersistStorage);
1074 if (hr != S_OK)
1075 goto cleanup;
1077 /* Create a doc file to copy the doc to a storage */
1079 hr = StgCreateDocfile(NULL, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &pStorage);
1081 if (hr != S_OK)
1082 goto cleanup;
1084 /* Save it to storage */
1086 hr = OleSave(pPersistStorage, pStorage, FALSE);
1088 if (hr != S_OK)
1089 goto cleanup;
1091 /* Open the Presentation data srteam */
1093 hr = IStorage_OpenStream(pStorage, name, 0, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &pStream);
1095 if (hr != S_OK)
1096 goto cleanup;
1098 /* Read the presentation header */
1100 hr = IStream_Read(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
1102 if (hr != S_OK)
1103 goto cleanup;
1105 mfBits = HeapAlloc(GetProcessHeap(), 0, pdh.dwSize);
1107 /* Read the Metafile bits */
1109 hr = IStream_Read(pStream, mfBits, pdh.dwSize, NULL);
1111 if (hr != S_OK)
1112 goto cleanup;
1114 /* Create the metafile and place it in the STGMEDIUM structure */
1116 hMetaFile = SetMetaFileBitsEx(pdh.dwSize, mfBits);
1118 hGlobalMF = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, sizeof(METAFILEPICT));
1119 mfPict = (METAFILEPICT *)GlobalLock(hGlobalMF);
1120 mfPict->hMF = hMetaFile;
1122 GlobalUnlock(hGlobalMF);
1124 pmedium->u.hGlobal = hGlobalMF;
1125 pmedium->tymed = TYMED_MFPICT;
1126 hrRet = S_OK;
1128 cleanup:
1130 if (mfBits)
1131 HeapFree(GetProcessHeap(), 0, mfBits);
1133 if (pStream)
1134 IStream_Release(pStream);
1136 if (pStorage)
1137 IStorage_Release(pStorage);
1139 if (pPersistStorage)
1140 IPersistStorage_Release(pPersistStorage);
1142 return hrRet;
1145 /* TODO: Other formats are not implemented */
1147 return E_NOTIMPL;
1150 static HRESULT WINAPI DataCache_GetDataHere(
1151 IDataObject* iface,
1152 LPFORMATETC pformatetc,
1153 STGMEDIUM* pmedium)
1155 FIXME("stub\n");
1156 return E_NOTIMPL;
1159 static HRESULT WINAPI DataCache_QueryGetData(
1160 IDataObject* iface,
1161 LPFORMATETC pformatetc)
1163 FIXME("stub\n");
1164 return E_NOTIMPL;
1167 /************************************************************************
1168 * DataCache_EnumFormatEtc (IDataObject)
1170 * The data cache doesn't implement this method.
1172 * See Windows documentation for more details on IDataObject methods.
1174 static HRESULT WINAPI DataCache_GetCanonicalFormatEtc(
1175 IDataObject* iface,
1176 LPFORMATETC pformatectIn,
1177 LPFORMATETC pformatetcOut)
1179 TRACE("()\n");
1180 return E_NOTIMPL;
1183 /************************************************************************
1184 * DataCache_IDataObject_SetData (IDataObject)
1186 * This method is delegated to the IOleCache2 implementation.
1188 * See Windows documentation for more details on IDataObject methods.
1190 static HRESULT WINAPI DataCache_IDataObject_SetData(
1191 IDataObject* iface,
1192 LPFORMATETC pformatetc,
1193 STGMEDIUM* pmedium,
1194 BOOL fRelease)
1196 IOleCache2* oleCache = NULL;
1197 HRESULT hres;
1199 TRACE("(%p, %p, %p, %d)\n", iface, pformatetc, pmedium, fRelease);
1201 hres = IDataObject_QueryInterface(iface, &IID_IOleCache2, (void**)&oleCache);
1203 if (FAILED(hres))
1204 return E_UNEXPECTED;
1206 hres = IOleCache2_SetData(oleCache, pformatetc, pmedium, fRelease);
1208 IOleCache2_Release(oleCache);
1210 return hres;;
1213 /************************************************************************
1214 * DataCache_EnumFormatEtc (IDataObject)
1216 * The data cache doesn't implement this method.
1218 * See Windows documentation for more details on IDataObject methods.
1220 static HRESULT WINAPI DataCache_EnumFormatEtc(
1221 IDataObject* iface,
1222 DWORD dwDirection,
1223 IEnumFORMATETC** ppenumFormatEtc)
1225 TRACE("()\n");
1226 return E_NOTIMPL;
1229 /************************************************************************
1230 * DataCache_DAdvise (IDataObject)
1232 * The data cache doesn't support connections.
1234 * See Windows documentation for more details on IDataObject methods.
1236 static HRESULT WINAPI DataCache_DAdvise(
1237 IDataObject* iface,
1238 FORMATETC* pformatetc,
1239 DWORD advf,
1240 IAdviseSink* pAdvSink,
1241 DWORD* pdwConnection)
1243 TRACE("()\n");
1244 return OLE_E_ADVISENOTSUPPORTED;
1247 /************************************************************************
1248 * DataCache_DUnadvise (IDataObject)
1250 * The data cache doesn't support connections.
1252 * See Windows documentation for more details on IDataObject methods.
1254 static HRESULT WINAPI DataCache_DUnadvise(
1255 IDataObject* iface,
1256 DWORD dwConnection)
1258 TRACE("()\n");
1259 return OLE_E_NOCONNECTION;
1262 /************************************************************************
1263 * DataCache_EnumDAdvise (IDataObject)
1265 * The data cache doesn't support connections.
1267 * See Windows documentation for more details on IDataObject methods.
1269 static HRESULT WINAPI DataCache_EnumDAdvise(
1270 IDataObject* iface,
1271 IEnumSTATDATA** ppenumAdvise)
1273 TRACE("()\n");
1274 return OLE_E_ADVISENOTSUPPORTED;
1277 /*********************************************************
1278 * Method implementation for the IDataObject
1279 * part of the DataCache class.
1282 /************************************************************************
1283 * DataCache_IPersistStorage_QueryInterface (IUnknown)
1285 * See Windows documentation for more details on IUnknown methods.
1287 static HRESULT WINAPI DataCache_IPersistStorage_QueryInterface(
1288 IPersistStorage* iface,
1289 REFIID riid,
1290 void** ppvObject)
1292 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1294 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1297 /************************************************************************
1298 * DataCache_IPersistStorage_AddRef (IUnknown)
1300 * See Windows documentation for more details on IUnknown methods.
1302 static ULONG WINAPI DataCache_IPersistStorage_AddRef(
1303 IPersistStorage* iface)
1305 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1307 return IUnknown_AddRef(this->outerUnknown);
1310 /************************************************************************
1311 * DataCache_IPersistStorage_Release (IUnknown)
1313 * See Windows documentation for more details on IUnknown methods.
1315 static ULONG WINAPI DataCache_IPersistStorage_Release(
1316 IPersistStorage* iface)
1318 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1320 return IUnknown_Release(this->outerUnknown);
1323 /************************************************************************
1324 * DataCache_GetClassID (IPersistStorage)
1326 * The data cache doesn't implement this method.
1328 * See Windows documentation for more details on IPersistStorage methods.
1330 static HRESULT WINAPI DataCache_GetClassID(
1331 IPersistStorage* iface,
1332 CLSID* pClassID)
1334 TRACE("(%p, %p)\n", iface, pClassID);
1335 return E_NOTIMPL;
1338 /************************************************************************
1339 * DataCache_IsDirty (IPersistStorage)
1341 * Until we actully connect to a running object and retrieve new
1342 * information to it, we never get dirty.
1344 * See Windows documentation for more details on IPersistStorage methods.
1346 static HRESULT WINAPI DataCache_IsDirty(
1347 IPersistStorage* iface)
1349 TRACE("(%p)\n", iface);
1351 return S_FALSE;
1354 /************************************************************************
1355 * DataCache_InitNew (IPersistStorage)
1357 * The data cache implementation of IPersistStorage_InitNew simply stores
1358 * the storage pointer.
1360 * See Windows documentation for more details on IPersistStorage methods.
1362 static HRESULT WINAPI DataCache_InitNew(
1363 IPersistStorage* iface,
1364 IStorage* pStg)
1366 TRACE("(%p, %p)\n", iface, pStg);
1368 return DataCache_Load(iface, pStg);
1371 /************************************************************************
1372 * DataCache_Load (IPersistStorage)
1374 * The data cache implementation of IPersistStorage_Load doesn't
1375 * actually load anything. Instead, it holds on to the storage pointer
1376 * and it will load the presentation information when the
1377 * IDataObject_GetData or IViewObject2_Draw methods are called.
1379 * See Windows documentation for more details on IPersistStorage methods.
1381 static HRESULT WINAPI DataCache_Load(
1382 IPersistStorage* iface,
1383 IStorage* pStg)
1385 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1387 TRACE("(%p, %p)\n", iface, pStg);
1389 if (this->presentationStorage != NULL)
1391 IStorage_Release(this->presentationStorage);
1394 this->presentationStorage = pStg;
1396 if (this->presentationStorage != NULL)
1398 IStorage_AddRef(this->presentationStorage);
1400 return S_OK;
1403 /************************************************************************
1404 * DataCache_Save (IPersistStorage)
1406 * Until we actully connect to a running object and retrieve new
1407 * information to it, we never have to save anything. However, it is
1408 * our responsability to copy the information when saving to a new
1409 * storage.
1411 * See Windows documentation for more details on IPersistStorage methods.
1413 static HRESULT WINAPI DataCache_Save(
1414 IPersistStorage* iface,
1415 IStorage* pStg,
1416 BOOL fSameAsLoad)
1418 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1420 TRACE("(%p, %p, %d)\n", iface, pStg, fSameAsLoad);
1422 if ( (!fSameAsLoad) &&
1423 (this->presentationStorage!=NULL) )
1425 return IStorage_CopyTo(this->presentationStorage,
1427 NULL,
1428 NULL,
1429 pStg);
1432 return S_OK;
1435 /************************************************************************
1436 * DataCache_SaveCompleted (IPersistStorage)
1438 * This method is called to tell the cache to release the storage
1439 * pointer it's currentlu holding.
1441 * See Windows documentation for more details on IPersistStorage methods.
1443 static HRESULT WINAPI DataCache_SaveCompleted(
1444 IPersistStorage* iface,
1445 IStorage* pStgNew)
1447 TRACE("(%p, %p)\n", iface, pStgNew);
1449 if (pStgNew)
1452 * First, make sure we get our hands off any storage we have.
1455 DataCache_HandsOffStorage(iface);
1458 * Then, attach to the new storage.
1461 DataCache_Load(iface, pStgNew);
1464 return S_OK;
1467 /************************************************************************
1468 * DataCache_HandsOffStorage (IPersistStorage)
1470 * This method is called to tell the cache to release the storage
1471 * pointer it's currentlu holding.
1473 * See Windows documentation for more details on IPersistStorage methods.
1475 static HRESULT WINAPI DataCache_HandsOffStorage(
1476 IPersistStorage* iface)
1478 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1480 TRACE("(%p)\n", iface);
1482 if (this->presentationStorage != NULL)
1484 IStorage_Release(this->presentationStorage);
1485 this->presentationStorage = NULL;
1488 return S_OK;
1491 /*********************************************************
1492 * Method implementation for the IViewObject2
1493 * part of the DataCache class.
1496 /************************************************************************
1497 * DataCache_IViewObject2_QueryInterface (IUnknown)
1499 * See Windows documentation for more details on IUnknown methods.
1501 static HRESULT WINAPI DataCache_IViewObject2_QueryInterface(
1502 IViewObject2* iface,
1503 REFIID riid,
1504 void** ppvObject)
1506 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1508 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1511 /************************************************************************
1512 * DataCache_IViewObject2_AddRef (IUnknown)
1514 * See Windows documentation for more details on IUnknown methods.
1516 static ULONG WINAPI DataCache_IViewObject2_AddRef(
1517 IViewObject2* iface)
1519 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1521 return IUnknown_AddRef(this->outerUnknown);
1524 /************************************************************************
1525 * DataCache_IViewObject2_Release (IUnknown)
1527 * See Windows documentation for more details on IUnknown methods.
1529 static ULONG WINAPI DataCache_IViewObject2_Release(
1530 IViewObject2* iface)
1532 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1534 return IUnknown_Release(this->outerUnknown);
1537 /************************************************************************
1538 * DataCache_Draw (IViewObject2)
1540 * This method will draw the cached representation of the object
1541 * to the given device context.
1543 * See Windows documentation for more details on IViewObject2 methods.
1545 static HRESULT WINAPI DataCache_Draw(
1546 IViewObject2* iface,
1547 DWORD dwDrawAspect,
1548 LONG lindex,
1549 void* pvAspect,
1550 DVTARGETDEVICE* ptd,
1551 HDC hdcTargetDev,
1552 HDC hdcDraw,
1553 LPCRECTL lprcBounds,
1554 LPCRECTL lprcWBounds,
1555 IVO_ContCallback pfnContinue,
1556 DWORD dwContinue)
1558 PresentationDataHeader presData;
1559 HMETAFILE presMetafile = 0;
1560 HRESULT hres;
1562 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1564 TRACE("(%p, %lx, %ld, %p, %x, %x, %p, %p, %p, %lx)\n",
1565 iface,
1566 dwDrawAspect,
1567 lindex,
1568 pvAspect,
1569 hdcTargetDev,
1570 hdcDraw,
1571 lprcBounds,
1572 lprcWBounds,
1573 pfnContinue,
1574 dwContinue);
1577 * Sanity check
1579 if (lprcBounds==NULL)
1580 return E_INVALIDARG;
1583 * First, we need to retrieve the dimensions of the
1584 * image in the metafile.
1586 hres = DataCache_ReadPresentationData(this,
1587 dwDrawAspect,
1588 &presData);
1590 if (FAILED(hres))
1591 return hres;
1594 * Then, we can extract the metafile itself from the cached
1595 * data.
1597 * FIXME Unless it isn't a metafile. I think it could be any CF_XXX type,
1598 * particularly CF_DIB.
1600 presMetafile = DataCache_ReadPresMetafile(this,
1601 dwDrawAspect);
1604 * If we have a metafile, just draw baby...
1605 * We have to be careful not to modify the state of the
1606 * DC.
1608 if (presMetafile!=0)
1610 INT prevMapMode = SetMapMode(hdcDraw, MM_ANISOTROPIC);
1611 SIZE oldWindowExt;
1612 SIZE oldViewportExt;
1613 POINT oldViewportOrg;
1615 SetWindowExtEx(hdcDraw,
1616 presData.dwObjectExtentX,
1617 presData.dwObjectExtentY,
1618 &oldWindowExt);
1620 SetViewportExtEx(hdcDraw,
1621 lprcBounds->right - lprcBounds->left,
1622 lprcBounds->bottom - lprcBounds->top,
1623 &oldViewportExt);
1625 SetViewportOrgEx(hdcDraw,
1626 lprcBounds->left,
1627 lprcBounds->top,
1628 &oldViewportOrg);
1630 PlayMetaFile(hdcDraw, presMetafile);
1632 SetWindowExtEx(hdcDraw,
1633 oldWindowExt.cx,
1634 oldWindowExt.cy,
1635 NULL);
1637 SetViewportExtEx(hdcDraw,
1638 oldViewportExt.cx,
1639 oldViewportExt.cy,
1640 NULL);
1642 SetViewportOrgEx(hdcDraw,
1643 oldViewportOrg.x,
1644 oldViewportOrg.y,
1645 NULL);
1647 SetMapMode(hdcDraw, prevMapMode);
1649 DeleteMetaFile(presMetafile);
1652 return S_OK;
1655 static HRESULT WINAPI DataCache_GetColorSet(
1656 IViewObject2* iface,
1657 DWORD dwDrawAspect,
1658 LONG lindex,
1659 void* pvAspect,
1660 DVTARGETDEVICE* ptd,
1661 HDC hicTargetDevice,
1662 LOGPALETTE** ppColorSet)
1664 FIXME("stub\n");
1665 return E_NOTIMPL;
1668 static HRESULT WINAPI DataCache_Freeze(
1669 IViewObject2* iface,
1670 DWORD dwDrawAspect,
1671 LONG lindex,
1672 void* pvAspect,
1673 DWORD* pdwFreeze)
1675 FIXME("stub\n");
1676 return E_NOTIMPL;
1679 static HRESULT WINAPI DataCache_Unfreeze(
1680 IViewObject2* iface,
1681 DWORD dwFreeze)
1683 FIXME("stub\n");
1684 return E_NOTIMPL;
1687 /************************************************************************
1688 * DataCache_SetAdvise (IViewObject2)
1690 * This sets-up an advisory sink with the data cache. When the object's
1691 * view changes, this sink is called.
1693 * See Windows documentation for more details on IViewObject2 methods.
1695 static HRESULT WINAPI DataCache_SetAdvise(
1696 IViewObject2* iface,
1697 DWORD aspects,
1698 DWORD advf,
1699 IAdviseSink* pAdvSink)
1701 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1703 TRACE("(%p, %lx, %lx, %p)\n", iface, aspects, advf, pAdvSink);
1706 * A call to this function removes the previous sink
1708 if (this->sinkInterface != NULL)
1710 IAdviseSink_Release(this->sinkInterface);
1711 this->sinkInterface = NULL;
1712 this->sinkAspects = 0;
1713 this->sinkAdviseFlag = 0;
1717 * Now, setup the new one.
1719 if (pAdvSink!=NULL)
1721 this->sinkInterface = pAdvSink;
1722 this->sinkAspects = aspects;
1723 this->sinkAdviseFlag = advf;
1725 IAdviseSink_AddRef(this->sinkInterface);
1729 * When the ADVF_PRIMEFIRST flag is set, we have to advise the
1730 * sink immediately.
1732 if (advf & ADVF_PRIMEFIRST)
1734 DataCache_FireOnViewChange(this,
1735 DVASPECT_CONTENT,
1736 -1);
1739 return S_OK;
1742 /************************************************************************
1743 * DataCache_GetAdvise (IViewObject2)
1745 * This method queries the current state of the advise sink
1746 * installed on the data cache.
1748 * See Windows documentation for more details on IViewObject2 methods.
1750 static HRESULT WINAPI DataCache_GetAdvise(
1751 IViewObject2* iface,
1752 DWORD* pAspects,
1753 DWORD* pAdvf,
1754 IAdviseSink** ppAdvSink)
1756 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1758 TRACE("(%p, %p, %p, %p)\n", iface, pAspects, pAdvf, ppAdvSink);
1761 * Just copy all the requested values.
1763 if (pAspects!=NULL)
1764 *pAspects = this->sinkAspects;
1766 if (pAdvf!=NULL)
1767 *pAdvf = this->sinkAdviseFlag;
1769 if (ppAdvSink!=NULL)
1771 IAdviseSink_QueryInterface(this->sinkInterface,
1772 &IID_IAdviseSink,
1773 (void**)ppAdvSink);
1776 return S_OK;
1779 /************************************************************************
1780 * DataCache_GetExtent (IViewObject2)
1782 * This method retrieves the "natural" size of this cached object.
1784 * See Windows documentation for more details on IViewObject2 methods.
1786 static HRESULT WINAPI DataCache_GetExtent(
1787 IViewObject2* iface,
1788 DWORD dwDrawAspect,
1789 LONG lindex,
1790 DVTARGETDEVICE* ptd,
1791 LPSIZEL lpsizel)
1793 PresentationDataHeader presData;
1794 HRESULT hres = E_FAIL;
1796 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1798 TRACE("(%p, %lx, %ld, %p, %p)\n",
1799 iface, dwDrawAspect, lindex, ptd, lpsizel);
1802 * Sanity check
1804 if (lpsizel==NULL)
1805 return E_POINTER;
1808 * Initialize the out parameter.
1810 lpsizel->cx = 0;
1811 lpsizel->cy = 0;
1814 * This flag should be set to -1.
1816 if (lindex!=-1)
1817 FIXME("Unimplemented flag lindex = %ld\n", lindex);
1820 * Right now, we suport only the callback from
1821 * the default handler.
1823 if (ptd!=NULL)
1824 FIXME("Unimplemented ptd = %p\n", ptd);
1827 * Get the presentation information from the
1828 * cache.
1830 hres = DataCache_ReadPresentationData(this,
1831 dwDrawAspect,
1832 &presData);
1834 if (SUCCEEDED(hres))
1836 lpsizel->cx = presData.dwObjectExtentX;
1837 lpsizel->cy = presData.dwObjectExtentY;
1841 * This method returns OLE_E_BLANK when it fails.
1843 if (FAILED(hres))
1844 hres = OLE_E_BLANK;
1846 return hres;
1850 /*********************************************************
1851 * Method implementation for the IOleCache2
1852 * part of the DataCache class.
1855 /************************************************************************
1856 * DataCache_IOleCache2_QueryInterface (IUnknown)
1858 * See Windows documentation for more details on IUnknown methods.
1860 static HRESULT WINAPI DataCache_IOleCache2_QueryInterface(
1861 IOleCache2* iface,
1862 REFIID riid,
1863 void** ppvObject)
1865 _ICOM_THIS_From_IOleCache2(DataCache, iface);
1867 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1870 /************************************************************************
1871 * DataCache_IOleCache2_AddRef (IUnknown)
1873 * See Windows documentation for more details on IUnknown methods.
1875 static ULONG WINAPI DataCache_IOleCache2_AddRef(
1876 IOleCache2* iface)
1878 _ICOM_THIS_From_IOleCache2(DataCache, iface);
1880 return IUnknown_AddRef(this->outerUnknown);
1883 /************************************************************************
1884 * DataCache_IOleCache2_Release (IUnknown)
1886 * See Windows documentation for more details on IUnknown methods.
1888 static ULONG WINAPI DataCache_IOleCache2_Release(
1889 IOleCache2* iface)
1891 _ICOM_THIS_From_IOleCache2(DataCache, iface);
1893 return IUnknown_Release(this->outerUnknown);
1896 static HRESULT WINAPI DataCache_Cache(
1897 IOleCache2* iface,
1898 FORMATETC* pformatetc,
1899 DWORD advf,
1900 DWORD* pdwConnection)
1902 FIXME("stub\n");
1903 return E_NOTIMPL;
1906 static HRESULT WINAPI DataCache_Uncache(
1907 IOleCache2* iface,
1908 DWORD dwConnection)
1910 FIXME("stub\n");
1911 return E_NOTIMPL;
1914 static HRESULT WINAPI DataCache_EnumCache(
1915 IOleCache2* iface,
1916 IEnumSTATDATA** ppenumSTATDATA)
1918 FIXME("stub\n");
1919 return E_NOTIMPL;
1922 static HRESULT WINAPI DataCache_InitCache(
1923 IOleCache2* iface,
1924 IDataObject* pDataObject)
1926 FIXME("stub\n");
1927 return E_NOTIMPL;
1930 static HRESULT WINAPI DataCache_IOleCache2_SetData(
1931 IOleCache2* iface,
1932 FORMATETC* pformatetc,
1933 STGMEDIUM* pmedium,
1934 BOOL fRelease)
1936 FIXME("stub\n");
1937 return E_NOTIMPL;
1940 static HRESULT WINAPI DataCache_UpdateCache(
1941 IOleCache2* iface,
1942 LPDATAOBJECT pDataObject,
1943 DWORD grfUpdf,
1944 LPVOID pReserved)
1946 FIXME("stub\n");
1947 return E_NOTIMPL;
1950 static HRESULT WINAPI DataCache_DiscardCache(
1951 IOleCache2* iface,
1952 DWORD dwDiscardOptions)
1954 FIXME("stub\n");
1955 return E_NOTIMPL;
1959 /*********************************************************
1960 * Method implementation for the IOleCacheControl
1961 * part of the DataCache class.
1964 /************************************************************************
1965 * DataCache_IOleCacheControl_QueryInterface (IUnknown)
1967 * See Windows documentation for more details on IUnknown methods.
1969 static HRESULT WINAPI DataCache_IOleCacheControl_QueryInterface(
1970 IOleCacheControl* iface,
1971 REFIID riid,
1972 void** ppvObject)
1974 _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
1976 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1979 /************************************************************************
1980 * DataCache_IOleCacheControl_AddRef (IUnknown)
1982 * See Windows documentation for more details on IUnknown methods.
1984 static ULONG WINAPI DataCache_IOleCacheControl_AddRef(
1985 IOleCacheControl* iface)
1987 _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
1989 return IUnknown_AddRef(this->outerUnknown);
1992 /************************************************************************
1993 * DataCache_IOleCacheControl_Release (IUnknown)
1995 * See Windows documentation for more details on IUnknown methods.
1997 static ULONG WINAPI DataCache_IOleCacheControl_Release(
1998 IOleCacheControl* iface)
2000 _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
2002 return IUnknown_Release(this->outerUnknown);
2005 static HRESULT WINAPI DataCache_OnRun(
2006 IOleCacheControl* iface,
2007 LPDATAOBJECT pDataObject)
2009 FIXME("stub\n");
2010 return E_NOTIMPL;
2013 static HRESULT WINAPI DataCache_OnStop(
2014 IOleCacheControl* iface)
2016 FIXME("stub\n");
2017 return E_NOTIMPL;