Added some missing definitions.
[wine/multimedia.git] / dlls / ole32 / datacache.c
blob3126edbf24a126da55e3156f73f425f8065d4b15
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 "wine/obj_base.h"
39 #include "wine/obj_misc.h"
40 #include "wine/obj_storage.h"
41 #include "wine/obj_moniker.h"
42 #include "wine/obj_dataobject.h"
43 #include "wine/obj_oleview.h"
44 #include "wine/obj_cache.h"
45 #include "wine/unicode.h"
46 #include "ole2.h"
47 #include "debugtools.h"
49 DEFAULT_DEBUG_CHANNEL(ole);
51 /****************************************************************************
52 * PresentationDataHeader
54 * This structure represents the header of the \002OlePresXXX stream in
55 * the OLE object strorage.
57 * Most fields are still unknown.
59 typedef struct PresentationDataHeader
61 DWORD unknown1; /* -1 */
62 DWORD unknown2; /* 3, possibly CF_METAFILEPICT */
63 DWORD unknown3; /* 4, possibly TYMED_ISTREAM */
64 DVASPECT dvAspect;
65 DWORD unknown5; /* -1 */
67 DWORD unknown6;
68 DWORD unknown7; /* 0 */
69 DWORD dwObjectExtentX;
70 DWORD dwObjectExtentY;
71 DWORD dwSize;
72 } PresentationDataHeader;
74 /****************************************************************************
75 * DataCache
77 struct DataCache
80 * List all interface VTables here
82 ICOM_VTABLE(IDataObject)* lpvtbl1;
83 ICOM_VTABLE(IUnknown)* lpvtbl2;
84 ICOM_VTABLE(IPersistStorage)* lpvtbl3;
85 ICOM_VTABLE(IViewObject2)* lpvtbl4;
86 ICOM_VTABLE(IOleCache2)* lpvtbl5;
87 ICOM_VTABLE(IOleCacheControl)* lpvtbl6;
90 * Reference count of this object
92 ULONG ref;
95 * IUnknown implementation of the outer object.
97 IUnknown* outerUnknown;
100 * This storage pointer is set through a call to
101 * IPersistStorage_Load. This is where the visual
102 * representation of the object is stored.
104 IStorage* presentationStorage;
107 * The user of this object can setup ONE advise sink
108 * connection with the object. These parameters describe
109 * that connection.
111 DWORD sinkAspects;
112 DWORD sinkAdviseFlag;
113 IAdviseSink* sinkInterface;
117 typedef struct DataCache DataCache;
120 * Here, I define utility macros to help with the casting of the
121 * "this" parameter.
122 * There is a version to accomodate all of the VTables implemented
123 * by this object.
125 #define _ICOM_THIS_From_IDataObject(class,name) class* this = (class*)name;
126 #define _ICOM_THIS_From_NDIUnknown(class, name) class* this = (class*)(((char*)name)-sizeof(void*));
127 #define _ICOM_THIS_From_IPersistStorage(class, name) class* this = (class*)(((char*)name)-2*sizeof(void*));
128 #define _ICOM_THIS_From_IViewObject2(class, name) class* this = (class*)(((char*)name)-3*sizeof(void*));
129 #define _ICOM_THIS_From_IOleCache2(class, name) class* this = (class*)(((char*)name)-4*sizeof(void*));
130 #define _ICOM_THIS_From_IOleCacheControl(class, name) class* this = (class*)(((char*)name)-5*sizeof(void*));
133 * Prototypes for the methods of the DataCache class.
135 static DataCache* DataCache_Construct(REFCLSID clsid,
136 LPUNKNOWN pUnkOuter);
137 static void DataCache_Destroy(DataCache* ptrToDestroy);
138 static HRESULT DataCache_ReadPresentationData(DataCache* this,
139 DWORD drawAspect,
140 PresentationDataHeader* header);
141 static HRESULT DataCache_OpenPresStream(DataCache *this,
142 DWORD drawAspect,
143 IStream **pStm);
144 static HMETAFILE DataCache_ReadPresMetafile(DataCache* this,
145 DWORD drawAspect);
146 static void DataCache_FireOnViewChange(DataCache* this,
147 DWORD aspect,
148 LONG lindex);
151 * Prototypes for the methods of the DataCache class
152 * that implement non delegating IUnknown methods.
154 static HRESULT WINAPI DataCache_NDIUnknown_QueryInterface(
155 IUnknown* iface,
156 REFIID riid,
157 void** ppvObject);
158 static ULONG WINAPI DataCache_NDIUnknown_AddRef(
159 IUnknown* iface);
160 static ULONG WINAPI DataCache_NDIUnknown_Release(
161 IUnknown* iface);
164 * Prototypes for the methods of the DataCache class
165 * that implement IDataObject methods.
167 static HRESULT WINAPI DataCache_IDataObject_QueryInterface(
168 IDataObject* iface,
169 REFIID riid,
170 void** ppvObject);
171 static ULONG WINAPI DataCache_IDataObject_AddRef(
172 IDataObject* iface);
173 static ULONG WINAPI DataCache_IDataObject_Release(
174 IDataObject* iface);
175 static HRESULT WINAPI DataCache_GetData(
176 IDataObject* iface,
177 LPFORMATETC pformatetcIn,
178 STGMEDIUM* pmedium);
179 static HRESULT WINAPI DataCache_GetDataHere(
180 IDataObject* iface,
181 LPFORMATETC pformatetc,
182 STGMEDIUM* pmedium);
183 static HRESULT WINAPI DataCache_QueryGetData(
184 IDataObject* iface,
185 LPFORMATETC pformatetc);
186 static HRESULT WINAPI DataCache_GetCanonicalFormatEtc(
187 IDataObject* iface,
188 LPFORMATETC pformatectIn,
189 LPFORMATETC pformatetcOut);
190 static HRESULT WINAPI DataCache_IDataObject_SetData(
191 IDataObject* iface,
192 LPFORMATETC pformatetc,
193 STGMEDIUM* pmedium,
194 BOOL fRelease);
195 static HRESULT WINAPI DataCache_EnumFormatEtc(
196 IDataObject* iface,
197 DWORD dwDirection,
198 IEnumFORMATETC** ppenumFormatEtc);
199 static HRESULT WINAPI DataCache_DAdvise(
200 IDataObject* iface,
201 FORMATETC* pformatetc,
202 DWORD advf,
203 IAdviseSink* pAdvSink,
204 DWORD* pdwConnection);
205 static HRESULT WINAPI DataCache_DUnadvise(
206 IDataObject* iface,
207 DWORD dwConnection);
208 static HRESULT WINAPI DataCache_EnumDAdvise(
209 IDataObject* iface,
210 IEnumSTATDATA** ppenumAdvise);
213 * Prototypes for the methods of the DataCache class
214 * that implement IPersistStorage methods.
216 static HRESULT WINAPI DataCache_IPersistStorage_QueryInterface(
217 IPersistStorage* iface,
218 REFIID riid,
219 void** ppvObject);
220 static ULONG WINAPI DataCache_IPersistStorage_AddRef(
221 IPersistStorage* iface);
222 static ULONG WINAPI DataCache_IPersistStorage_Release(
223 IPersistStorage* iface);
224 static HRESULT WINAPI DataCache_GetClassID(
225 IPersistStorage* iface,
226 CLSID* pClassID);
227 static HRESULT WINAPI DataCache_IsDirty(
228 IPersistStorage* iface);
229 static HRESULT WINAPI DataCache_InitNew(
230 IPersistStorage* iface,
231 IStorage* pStg);
232 static HRESULT WINAPI DataCache_Load(
233 IPersistStorage* iface,
234 IStorage* pStg);
235 static HRESULT WINAPI DataCache_Save(
236 IPersistStorage* iface,
237 IStorage* pStg,
238 BOOL fSameAsLoad);
239 static HRESULT WINAPI DataCache_SaveCompleted(
240 IPersistStorage* iface,
241 IStorage* pStgNew);
242 static HRESULT WINAPI DataCache_HandsOffStorage(
243 IPersistStorage* iface);
246 * Prototypes for the methods of the DataCache class
247 * that implement IViewObject2 methods.
249 static HRESULT WINAPI DataCache_IViewObject2_QueryInterface(
250 IViewObject2* iface,
251 REFIID riid,
252 void** ppvObject);
253 static ULONG WINAPI DataCache_IViewObject2_AddRef(
254 IViewObject2* iface);
255 static ULONG WINAPI DataCache_IViewObject2_Release(
256 IViewObject2* iface);
257 static HRESULT WINAPI DataCache_Draw(
258 IViewObject2* iface,
259 DWORD dwDrawAspect,
260 LONG lindex,
261 void* pvAspect,
262 DVTARGETDEVICE* ptd,
263 HDC hdcTargetDev,
264 HDC hdcDraw,
265 LPCRECTL lprcBounds,
266 LPCRECTL lprcWBounds,
267 IVO_ContCallback pfnContinue,
268 DWORD dwContinue);
269 static HRESULT WINAPI DataCache_GetColorSet(
270 IViewObject2* iface,
271 DWORD dwDrawAspect,
272 LONG lindex,
273 void* pvAspect,
274 DVTARGETDEVICE* ptd,
275 HDC hicTargetDevice,
276 LOGPALETTE** ppColorSet);
277 static HRESULT WINAPI DataCache_Freeze(
278 IViewObject2* iface,
279 DWORD dwDrawAspect,
280 LONG lindex,
281 void* pvAspect,
282 DWORD* pdwFreeze);
283 static HRESULT WINAPI DataCache_Unfreeze(
284 IViewObject2* iface,
285 DWORD dwFreeze);
286 static HRESULT WINAPI DataCache_SetAdvise(
287 IViewObject2* iface,
288 DWORD aspects,
289 DWORD advf,
290 IAdviseSink* pAdvSink);
291 static HRESULT WINAPI DataCache_GetAdvise(
292 IViewObject2* iface,
293 DWORD* pAspects,
294 DWORD* pAdvf,
295 IAdviseSink** ppAdvSink);
296 static HRESULT WINAPI DataCache_GetExtent(
297 IViewObject2* iface,
298 DWORD dwDrawAspect,
299 LONG lindex,
300 DVTARGETDEVICE* ptd,
301 LPSIZEL lpsizel);
304 * Prototypes for the methods of the DataCache class
305 * that implement IOleCache2 methods.
307 static HRESULT WINAPI DataCache_IOleCache2_QueryInterface(
308 IOleCache2* iface,
309 REFIID riid,
310 void** ppvObject);
311 static ULONG WINAPI DataCache_IOleCache2_AddRef(
312 IOleCache2* iface);
313 static ULONG WINAPI DataCache_IOleCache2_Release(
314 IOleCache2* iface);
315 static HRESULT WINAPI DataCache_Cache(
316 IOleCache2* iface,
317 FORMATETC* pformatetc,
318 DWORD advf,
319 DWORD* pdwConnection);
320 static HRESULT WINAPI DataCache_Uncache(
321 IOleCache2* iface,
322 DWORD dwConnection);
323 static HRESULT WINAPI DataCache_EnumCache(
324 IOleCache2* iface,
325 IEnumSTATDATA** ppenumSTATDATA);
326 static HRESULT WINAPI DataCache_InitCache(
327 IOleCache2* iface,
328 IDataObject* pDataObject);
329 static HRESULT WINAPI DataCache_IOleCache2_SetData(
330 IOleCache2* iface,
331 FORMATETC* pformatetc,
332 STGMEDIUM* pmedium,
333 BOOL fRelease);
334 static HRESULT WINAPI DataCache_UpdateCache(
335 IOleCache2* iface,
336 LPDATAOBJECT pDataObject,
337 DWORD grfUpdf,
338 LPVOID pReserved);
339 static HRESULT WINAPI DataCache_DiscardCache(
340 IOleCache2* iface,
341 DWORD dwDiscardOptions);
344 * Prototypes for the methods of the DataCache class
345 * that implement IOleCacheControl methods.
347 static HRESULT WINAPI DataCache_IOleCacheControl_QueryInterface(
348 IOleCacheControl* iface,
349 REFIID riid,
350 void** ppvObject);
351 static ULONG WINAPI DataCache_IOleCacheControl_AddRef(
352 IOleCacheControl* iface);
353 static ULONG WINAPI DataCache_IOleCacheControl_Release(
354 IOleCacheControl* iface);
355 static HRESULT WINAPI DataCache_OnRun(
356 IOleCacheControl* iface,
357 LPDATAOBJECT pDataObject);
358 static HRESULT WINAPI DataCache_OnStop(
359 IOleCacheControl* iface);
362 * Virtual function tables for the DataCache class.
364 static ICOM_VTABLE(IUnknown) DataCache_NDIUnknown_VTable =
366 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
367 DataCache_NDIUnknown_QueryInterface,
368 DataCache_NDIUnknown_AddRef,
369 DataCache_NDIUnknown_Release
372 static ICOM_VTABLE(IDataObject) DataCache_IDataObject_VTable =
374 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
375 DataCache_IDataObject_QueryInterface,
376 DataCache_IDataObject_AddRef,
377 DataCache_IDataObject_Release,
378 DataCache_GetData,
379 DataCache_GetDataHere,
380 DataCache_QueryGetData,
381 DataCache_GetCanonicalFormatEtc,
382 DataCache_IDataObject_SetData,
383 DataCache_EnumFormatEtc,
384 DataCache_DAdvise,
385 DataCache_DUnadvise,
386 DataCache_EnumDAdvise
389 static ICOM_VTABLE(IPersistStorage) DataCache_IPersistStorage_VTable =
391 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
392 DataCache_IPersistStorage_QueryInterface,
393 DataCache_IPersistStorage_AddRef,
394 DataCache_IPersistStorage_Release,
395 DataCache_GetClassID,
396 DataCache_IsDirty,
397 DataCache_InitNew,
398 DataCache_Load,
399 DataCache_Save,
400 DataCache_SaveCompleted,
401 DataCache_HandsOffStorage
404 static ICOM_VTABLE(IViewObject2) DataCache_IViewObject2_VTable =
406 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
407 DataCache_IViewObject2_QueryInterface,
408 DataCache_IViewObject2_AddRef,
409 DataCache_IViewObject2_Release,
410 DataCache_Draw,
411 DataCache_GetColorSet,
412 DataCache_Freeze,
413 DataCache_Unfreeze,
414 DataCache_SetAdvise,
415 DataCache_GetAdvise,
416 DataCache_GetExtent
419 static ICOM_VTABLE(IOleCache2) DataCache_IOleCache2_VTable =
421 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
422 DataCache_IOleCache2_QueryInterface,
423 DataCache_IOleCache2_AddRef,
424 DataCache_IOleCache2_Release,
425 DataCache_Cache,
426 DataCache_Uncache,
427 DataCache_EnumCache,
428 DataCache_InitCache,
429 DataCache_IOleCache2_SetData,
430 DataCache_UpdateCache,
431 DataCache_DiscardCache
434 static ICOM_VTABLE(IOleCacheControl) DataCache_IOleCacheControl_VTable =
436 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
437 DataCache_IOleCacheControl_QueryInterface,
438 DataCache_IOleCacheControl_AddRef,
439 DataCache_IOleCacheControl_Release,
440 DataCache_OnRun,
441 DataCache_OnStop
444 /******************************************************************************
445 * CreateDataCache [OLE32.54]
447 HRESULT WINAPI CreateDataCache(
448 LPUNKNOWN pUnkOuter,
449 REFCLSID rclsid,
450 REFIID riid,
451 LPVOID* ppvObj)
453 DataCache* newCache = NULL;
454 HRESULT hr = S_OK;
456 TRACE("(%s, %p, %s, %p)\n", debugstr_guid(rclsid), pUnkOuter, debugstr_guid(riid), ppvObj);
459 * Sanity check
461 if (ppvObj==0)
462 return E_POINTER;
464 *ppvObj = 0;
467 * If this cache is constructed for aggregation, make sure
468 * the caller is requesting the IUnknown interface.
469 * This is necessary because it's the only time the non-delegating
470 * IUnknown pointer can be returned to the outside.
472 if ( (pUnkOuter!=NULL) &&
473 (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) != 0) )
474 return CLASS_E_NOAGGREGATION;
477 * Try to construct a new instance of the class.
479 newCache = DataCache_Construct(rclsid,
480 pUnkOuter);
482 if (newCache == 0)
483 return E_OUTOFMEMORY;
486 * Make sure it supports the interface required by the caller.
488 hr = IUnknown_QueryInterface((IUnknown*)&(newCache->lpvtbl2), riid, ppvObj);
491 * Release the reference obtained in the constructor. If
492 * the QueryInterface was unsuccessful, it will free the class.
494 IUnknown_Release((IUnknown*)&(newCache->lpvtbl2));
496 return hr;
499 /*********************************************************
500 * Method implementation for DataCache class.
502 static DataCache* DataCache_Construct(
503 REFCLSID clsid,
504 LPUNKNOWN pUnkOuter)
506 DataCache* newObject = 0;
509 * Allocate space for the object.
511 newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(DataCache));
513 if (newObject==0)
514 return newObject;
517 * Initialize the virtual function table.
519 newObject->lpvtbl1 = &DataCache_IDataObject_VTable;
520 newObject->lpvtbl2 = &DataCache_NDIUnknown_VTable;
521 newObject->lpvtbl3 = &DataCache_IPersistStorage_VTable;
522 newObject->lpvtbl4 = &DataCache_IViewObject2_VTable;
523 newObject->lpvtbl5 = &DataCache_IOleCache2_VTable;
524 newObject->lpvtbl6 = &DataCache_IOleCacheControl_VTable;
527 * Start with one reference count. The caller of this function
528 * must release the interface pointer when it is done.
530 newObject->ref = 1;
533 * Initialize the outer unknown
534 * We don't keep a reference on the outer unknown since, the way
535 * aggregation works, our lifetime is at least as large as it's
536 * lifetime.
538 if (pUnkOuter==NULL)
539 pUnkOuter = (IUnknown*)&(newObject->lpvtbl2);
541 newObject->outerUnknown = pUnkOuter;
544 * Initialize the other members of the structure.
546 newObject->presentationStorage = NULL;
547 newObject->sinkAspects = 0;
548 newObject->sinkAdviseFlag = 0;
549 newObject->sinkInterface = 0;
551 return newObject;
554 static void DataCache_Destroy(
555 DataCache* ptrToDestroy)
557 TRACE("()\n");
559 if (ptrToDestroy->sinkInterface != NULL)
561 IAdviseSink_Release(ptrToDestroy->sinkInterface);
562 ptrToDestroy->sinkInterface = NULL;
565 if (ptrToDestroy->presentationStorage != NULL)
567 IStorage_Release(ptrToDestroy->presentationStorage);
568 ptrToDestroy->presentationStorage = NULL;
572 * Free the datacache pointer.
574 HeapFree(GetProcessHeap(), 0, ptrToDestroy);
577 /************************************************************************
578 * DataCache_ReadPresentationData
580 * This method will read information for the requested presentation
581 * into the given structure.
583 * Param:
584 * this - Pointer to the DataCache object
585 * drawAspect - The aspect of the object that we wish to draw.
586 * header - The structure containing information about this
587 * aspect of the object.
589 static HRESULT DataCache_ReadPresentationData(
590 DataCache* this,
591 DWORD drawAspect,
592 PresentationDataHeader* header)
594 IStream* presStream = NULL;
595 HRESULT hres;
598 * Open the presentation stream.
600 hres = DataCache_OpenPresStream(
601 this,
602 drawAspect,
603 &presStream);
605 if (FAILED(hres))
606 return hres;
609 * Read the header.
612 hres = IStream_Read(
613 presStream,
614 header,
615 sizeof(PresentationDataHeader),
616 NULL);
619 * Cleanup.
621 IStream_Release(presStream);
624 * We don't want to propagate any other error
625 * code than a failure.
627 if (hres!=S_OK)
628 hres = E_FAIL;
630 return hres;
633 /************************************************************************
634 * DataCache_FireOnViewChange
636 * This method will fire an OnViewChange notification to the advise
637 * sink registered with the datacache.
639 * See IAdviseSink::OnViewChange for more details.
641 static void DataCache_FireOnViewChange(
642 DataCache* this,
643 DWORD aspect,
644 LONG lindex)
646 TRACE("(%p, %lx, %ld)\n", this, aspect, lindex);
649 * The sink supplies a filter when it registers
650 * we make sure we only send the notifications when that
651 * filter matches.
653 if ((this->sinkAspects & aspect) != 0)
655 if (this->sinkInterface != NULL)
657 IAdviseSink_OnViewChange(this->sinkInterface,
658 aspect,
659 lindex);
662 * Some sinks want to be unregistered automatically when
663 * the first notification goes out.
665 if ( (this->sinkAdviseFlag & ADVF_ONLYONCE) != 0)
667 IAdviseSink_Release(this->sinkInterface);
669 this->sinkInterface = NULL;
670 this->sinkAspects = 0;
671 this->sinkAdviseFlag = 0;
677 /* Helper for DataCache_OpenPresStream */
678 static BOOL DataCache_IsPresentationStream(const STATSTG *elem)
680 /* The presentation streams have names of the form "\002OlePresXXX",
681 * where XXX goes from 000 to 999. */
682 static const WCHAR OlePres[] = { 2,'O','l','e','P','r','e','s' };
684 LPCWSTR name = elem->pwcsName;
686 return (elem->type == STGTY_STREAM)
687 && (elem->cbSize.s.LowPart >= sizeof(PresentationDataHeader))
688 && (strlenW(name) == 11)
689 && (strncmpW(name, OlePres, 8) == 0)
690 && (name[8] >= '0') && (name[8] <= '9')
691 && (name[9] >= '0') && (name[9] <= '9')
692 && (name[10] >= '0') && (name[10] <= '9');
695 /************************************************************************
696 * DataCache_OpenPresStream
698 * This method will find the stream for the given presentation. It makes
699 * no attempt at fallback.
701 * Param:
702 * this - Pointer to the DataCache object
703 * drawAspect - The aspect of the object that we wish to draw.
704 * pStm - A returned stream. It points to the beginning of the
705 * - presentation data, including the header.
707 * Errors:
708 * S_OK The requested stream has been opened.
709 * OLE_E_BLANK The requested stream could not be found.
710 * Quite a few others I'm too lazy to map correctly.
712 * Notes:
713 * Algorithm: Scan the elements of the presentation storage, looking
714 * for presentation streams. For each presentation stream,
715 * load the header and check to see if the aspect maches.
717 * If a fallback is desired, just opening the first presentation stream
718 * is a possibility.
720 static HRESULT DataCache_OpenPresStream(
721 DataCache *this,
722 DWORD drawAspect,
723 IStream **ppStm)
725 STATSTG elem;
726 IEnumSTATSTG *pEnum;
727 HRESULT hr;
729 if (!ppStm) return E_POINTER;
731 hr = IStorage_EnumElements(this->presentationStorage, 0, NULL, 0, &pEnum);
732 if (FAILED(hr)) return hr;
734 while ((hr = IEnumSTATSTG_Next(pEnum, 1, &elem, NULL)) == S_OK)
736 if (DataCache_IsPresentationStream(&elem))
738 IStream *pStm;
740 hr = IStorage_OpenStream(this->presentationStorage, elem.pwcsName,
741 NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0,
742 &pStm);
743 if (SUCCEEDED(hr))
745 PresentationDataHeader header;
746 ULONG actual_read;
748 hr = IStream_Read(pStm, &header, sizeof(header), &actual_read);
750 /* can't use SUCCEEDED(hr): S_FALSE counts as an error */
751 if (hr == S_OK && actual_read == sizeof(header)
752 && header.dvAspect == drawAspect)
754 /* Rewind the stream before returning it. */
755 LARGE_INTEGER offset;
756 offset.s.LowPart = 0;
757 offset.s.HighPart = 0;
758 IStream_Seek(pStm, offset, STREAM_SEEK_SET, NULL);
760 *ppStm = pStm;
762 CoTaskMemFree(elem.pwcsName);
763 IEnumSTATSTG_Release(pEnum);
765 return S_OK;
768 IStream_Release(pStm);
772 CoTaskMemFree(elem.pwcsName);
775 IEnumSTATSTG_Release(pEnum);
777 return (hr == S_FALSE ? OLE_E_BLANK : hr);
780 /************************************************************************
781 * DataCache_ReadPresentationData
783 * This method will read information for the requested presentation
784 * into the given structure.
786 * Param:
787 * this - Pointer to the DataCache object
788 * drawAspect - The aspect of the object that we wish to draw.
790 * Returns:
791 * This method returns a metafile handle if it is successful.
792 * it will return 0 if not.
794 static HMETAFILE DataCache_ReadPresMetafile(
795 DataCache* this,
796 DWORD drawAspect)
798 LARGE_INTEGER offset;
799 IStream* presStream = NULL;
800 HRESULT hres;
801 void* metafileBits;
802 STATSTG streamInfo;
803 HMETAFILE newMetafile = 0;
806 * Open the presentation stream.
808 hres = DataCache_OpenPresStream(
809 this,
810 drawAspect,
811 &presStream);
813 if (FAILED(hres))
814 return hres;
817 * Get the size of the stream.
819 hres = IStream_Stat(presStream,
820 &streamInfo,
821 STATFLAG_NONAME);
824 * Skip the header
826 offset.s.HighPart = 0;
827 offset.s.LowPart = sizeof(PresentationDataHeader);
829 hres = IStream_Seek(
830 presStream,
831 offset,
832 STREAM_SEEK_SET,
833 NULL);
835 streamInfo.cbSize.s.LowPart -= offset.s.LowPart;
838 * Allocate a buffer for the metafile bits.
840 metafileBits = HeapAlloc(GetProcessHeap(),
842 streamInfo.cbSize.s.LowPart);
845 * Read the metafile bits.
847 hres = IStream_Read(
848 presStream,
849 metafileBits,
850 streamInfo.cbSize.s.LowPart,
851 NULL);
854 * Create a metafile with those bits.
856 if (SUCCEEDED(hres))
858 newMetafile = SetMetaFileBitsEx(streamInfo.cbSize.s.LowPart, metafileBits);
862 * Cleanup.
864 HeapFree(GetProcessHeap(), 0, metafileBits);
865 IStream_Release(presStream);
867 if (newMetafile==0)
868 hres = E_FAIL;
870 return newMetafile;
873 /*********************************************************
874 * Method implementation for the non delegating IUnknown
875 * part of the DataCache class.
878 /************************************************************************
879 * DataCache_NDIUnknown_QueryInterface (IUnknown)
881 * See Windows documentation for more details on IUnknown methods.
883 * This version of QueryInterface will not delegate it's implementation
884 * to the outer unknown.
886 static HRESULT WINAPI DataCache_NDIUnknown_QueryInterface(
887 IUnknown* iface,
888 REFIID riid,
889 void** ppvObject)
891 _ICOM_THIS_From_NDIUnknown(DataCache, iface);
894 * Perform a sanity check on the parameters.
896 if ( (this==0) || (ppvObject==0) )
897 return E_INVALIDARG;
900 * Initialize the return parameter.
902 *ppvObject = 0;
905 * Compare the riid with the interface IDs implemented by this object.
907 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
909 *ppvObject = iface;
911 else if (memcmp(&IID_IDataObject, riid, sizeof(IID_IDataObject)) == 0)
913 *ppvObject = (IDataObject*)&(this->lpvtbl1);
915 else if ( (memcmp(&IID_IPersistStorage, riid, sizeof(IID_IPersistStorage)) == 0) ||
916 (memcmp(&IID_IPersist, riid, sizeof(IID_IPersist)) == 0) )
918 *ppvObject = (IPersistStorage*)&(this->lpvtbl3);
920 else if ( (memcmp(&IID_IViewObject, riid, sizeof(IID_IViewObject)) == 0) ||
921 (memcmp(&IID_IViewObject2, riid, sizeof(IID_IViewObject2)) == 0) )
923 *ppvObject = (IViewObject2*)&(this->lpvtbl4);
925 else if ( (memcmp(&IID_IOleCache, riid, sizeof(IID_IOleCache)) == 0) ||
926 (memcmp(&IID_IOleCache2, riid, sizeof(IID_IOleCache2)) == 0) )
928 *ppvObject = (IOleCache2*)&(this->lpvtbl5);
930 else if (memcmp(&IID_IOleCacheControl, riid, sizeof(IID_IOleCacheControl)) == 0)
932 *ppvObject = (IOleCacheControl*)&(this->lpvtbl6);
936 * Check that we obtained an interface.
938 if ((*ppvObject)==0)
940 WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid));
941 return E_NOINTERFACE;
945 * Query Interface always increases the reference count by one when it is
946 * successful.
948 IUnknown_AddRef((IUnknown*)*ppvObject);
950 return S_OK;;
953 /************************************************************************
954 * DataCache_NDIUnknown_AddRef (IUnknown)
956 * See Windows documentation for more details on IUnknown methods.
958 * This version of QueryInterface will not delegate it's implementation
959 * to the outer unknown.
961 static ULONG WINAPI DataCache_NDIUnknown_AddRef(
962 IUnknown* iface)
964 _ICOM_THIS_From_NDIUnknown(DataCache, iface);
966 this->ref++;
968 return this->ref;
971 /************************************************************************
972 * DataCache_NDIUnknown_Release (IUnknown)
974 * See Windows documentation for more details on IUnknown methods.
976 * This version of QueryInterface will not delegate it's implementation
977 * to the outer unknown.
979 static ULONG WINAPI DataCache_NDIUnknown_Release(
980 IUnknown* iface)
982 _ICOM_THIS_From_NDIUnknown(DataCache, iface);
985 * Decrease the reference count on this object.
987 this->ref--;
990 * If the reference count goes down to 0, perform suicide.
992 if (this->ref==0)
994 DataCache_Destroy(this);
996 return 0;
999 return this->ref;
1002 /*********************************************************
1003 * Method implementation for the IDataObject
1004 * part of the DataCache class.
1007 /************************************************************************
1008 * DataCache_IDataObject_QueryInterface (IUnknown)
1010 * See Windows documentation for more details on IUnknown methods.
1012 static HRESULT WINAPI DataCache_IDataObject_QueryInterface(
1013 IDataObject* iface,
1014 REFIID riid,
1015 void** ppvObject)
1017 _ICOM_THIS_From_IDataObject(DataCache, iface);
1019 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1022 /************************************************************************
1023 * DataCache_IDataObject_AddRef (IUnknown)
1025 * See Windows documentation for more details on IUnknown methods.
1027 static ULONG WINAPI DataCache_IDataObject_AddRef(
1028 IDataObject* iface)
1030 _ICOM_THIS_From_IDataObject(DataCache, iface);
1032 return IUnknown_AddRef(this->outerUnknown);
1035 /************************************************************************
1036 * DataCache_IDataObject_Release (IUnknown)
1038 * See Windows documentation for more details on IUnknown methods.
1040 static ULONG WINAPI DataCache_IDataObject_Release(
1041 IDataObject* iface)
1043 _ICOM_THIS_From_IDataObject(DataCache, iface);
1045 return IUnknown_Release(this->outerUnknown);
1048 /************************************************************************
1049 * DataCache_GetData
1051 * Get Data from a source dataobject using format pformatetcIn->cfFormat
1052 * See Windows documentation for more details on GetData.
1053 * TODO: Currently only CF_METAFILEPICT is implemented
1055 static HRESULT WINAPI DataCache_GetData(
1056 IDataObject* iface,
1057 LPFORMATETC pformatetcIn,
1058 STGMEDIUM* pmedium)
1060 HRESULT hr = 0;
1061 HRESULT hrRet = E_UNEXPECTED;
1062 IPersistStorage *pPersistStorage = 0;
1063 IStorage *pStorage = 0;
1064 IStream *pStream = 0;
1065 OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
1066 HGLOBAL hGlobalMF = 0;
1067 void *mfBits = 0;
1068 PresentationDataHeader pdh;
1069 METAFILEPICT *mfPict;
1070 HMETAFILE hMetaFile = 0;
1072 if (pformatetcIn->cfFormat == CF_METAFILEPICT)
1074 /* Get the Persist Storage */
1076 hr = IDataObject_QueryInterface(iface, &IID_IPersistStorage, (void**)&pPersistStorage);
1078 if (hr != S_OK)
1079 goto cleanup;
1081 /* Create a doc file to copy the doc to a storage */
1083 hr = StgCreateDocfile(NULL, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &pStorage);
1085 if (hr != S_OK)
1086 goto cleanup;
1088 /* Save it to storage */
1090 hr = OleSave(pPersistStorage, pStorage, FALSE);
1092 if (hr != S_OK)
1093 goto cleanup;
1095 /* Open the Presentation data srteam */
1097 hr = IStorage_OpenStream(pStorage, name, 0, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &pStream);
1099 if (hr != S_OK)
1100 goto cleanup;
1102 /* Read the presentation header */
1104 hr = IStream_Read(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
1106 if (hr != S_OK)
1107 goto cleanup;
1109 mfBits = HeapAlloc(GetProcessHeap(), 0, pdh.dwSize);
1111 /* Read the Metafile bits */
1113 hr = IStream_Read(pStream, mfBits, pdh.dwSize, NULL);
1115 if (hr != S_OK)
1116 goto cleanup;
1118 /* Create the metafile and place it in the STGMEDIUM structure */
1120 hMetaFile = SetMetaFileBitsEx(pdh.dwSize, mfBits);
1122 hGlobalMF = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, sizeof(METAFILEPICT));
1123 mfPict = (METAFILEPICT *)GlobalLock(hGlobalMF);
1124 mfPict->hMF = hMetaFile;
1126 GlobalUnlock(hGlobalMF);
1128 pmedium->u.hGlobal = hGlobalMF;
1129 pmedium->tymed = TYMED_MFPICT;
1130 hrRet = S_OK;
1132 cleanup:
1134 if (mfBits)
1135 HeapFree(GetProcessHeap(), 0, mfBits);
1137 if (pStream)
1138 IStream_Release(pStream);
1140 if (pStorage)
1141 IStorage_Release(pStorage);
1143 if (pPersistStorage)
1144 IPersistStorage_Release(pPersistStorage);
1146 return hrRet;
1149 /* TODO: Other formats are not implemented */
1151 return E_NOTIMPL;
1154 static HRESULT WINAPI DataCache_GetDataHere(
1155 IDataObject* iface,
1156 LPFORMATETC pformatetc,
1157 STGMEDIUM* pmedium)
1159 FIXME("stub\n");
1160 return E_NOTIMPL;
1163 static HRESULT WINAPI DataCache_QueryGetData(
1164 IDataObject* iface,
1165 LPFORMATETC pformatetc)
1167 FIXME("stub\n");
1168 return E_NOTIMPL;
1171 /************************************************************************
1172 * DataCache_EnumFormatEtc (IDataObject)
1174 * The data cache doesn't implement this method.
1176 * See Windows documentation for more details on IDataObject methods.
1178 static HRESULT WINAPI DataCache_GetCanonicalFormatEtc(
1179 IDataObject* iface,
1180 LPFORMATETC pformatectIn,
1181 LPFORMATETC pformatetcOut)
1183 TRACE("()\n");
1184 return E_NOTIMPL;
1187 /************************************************************************
1188 * DataCache_IDataObject_SetData (IDataObject)
1190 * This method is delegated to the IOleCache2 implementation.
1192 * See Windows documentation for more details on IDataObject methods.
1194 static HRESULT WINAPI DataCache_IDataObject_SetData(
1195 IDataObject* iface,
1196 LPFORMATETC pformatetc,
1197 STGMEDIUM* pmedium,
1198 BOOL fRelease)
1200 IOleCache2* oleCache = NULL;
1201 HRESULT hres;
1203 TRACE("(%p, %p, %p, %d)\n", iface, pformatetc, pmedium, fRelease);
1205 hres = IDataObject_QueryInterface(iface, &IID_IOleCache2, (void**)&oleCache);
1207 if (FAILED(hres))
1208 return E_UNEXPECTED;
1210 hres = IOleCache2_SetData(oleCache, pformatetc, pmedium, fRelease);
1212 IOleCache2_Release(oleCache);
1214 return hres;;
1217 /************************************************************************
1218 * DataCache_EnumFormatEtc (IDataObject)
1220 * The data cache doesn't implement this method.
1222 * See Windows documentation for more details on IDataObject methods.
1224 static HRESULT WINAPI DataCache_EnumFormatEtc(
1225 IDataObject* iface,
1226 DWORD dwDirection,
1227 IEnumFORMATETC** ppenumFormatEtc)
1229 TRACE("()\n");
1230 return E_NOTIMPL;
1233 /************************************************************************
1234 * DataCache_DAdvise (IDataObject)
1236 * The data cache doesn't support connections.
1238 * See Windows documentation for more details on IDataObject methods.
1240 static HRESULT WINAPI DataCache_DAdvise(
1241 IDataObject* iface,
1242 FORMATETC* pformatetc,
1243 DWORD advf,
1244 IAdviseSink* pAdvSink,
1245 DWORD* pdwConnection)
1247 TRACE("()\n");
1248 return OLE_E_ADVISENOTSUPPORTED;
1251 /************************************************************************
1252 * DataCache_DUnadvise (IDataObject)
1254 * The data cache doesn't support connections.
1256 * See Windows documentation for more details on IDataObject methods.
1258 static HRESULT WINAPI DataCache_DUnadvise(
1259 IDataObject* iface,
1260 DWORD dwConnection)
1262 TRACE("()\n");
1263 return OLE_E_NOCONNECTION;
1266 /************************************************************************
1267 * DataCache_EnumDAdvise (IDataObject)
1269 * The data cache doesn't support connections.
1271 * See Windows documentation for more details on IDataObject methods.
1273 static HRESULT WINAPI DataCache_EnumDAdvise(
1274 IDataObject* iface,
1275 IEnumSTATDATA** ppenumAdvise)
1277 TRACE("()\n");
1278 return OLE_E_ADVISENOTSUPPORTED;
1281 /*********************************************************
1282 * Method implementation for the IDataObject
1283 * part of the DataCache class.
1286 /************************************************************************
1287 * DataCache_IPersistStorage_QueryInterface (IUnknown)
1289 * See Windows documentation for more details on IUnknown methods.
1291 static HRESULT WINAPI DataCache_IPersistStorage_QueryInterface(
1292 IPersistStorage* iface,
1293 REFIID riid,
1294 void** ppvObject)
1296 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1298 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1301 /************************************************************************
1302 * DataCache_IPersistStorage_AddRef (IUnknown)
1304 * See Windows documentation for more details on IUnknown methods.
1306 static ULONG WINAPI DataCache_IPersistStorage_AddRef(
1307 IPersistStorage* iface)
1309 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1311 return IUnknown_AddRef(this->outerUnknown);
1314 /************************************************************************
1315 * DataCache_IPersistStorage_Release (IUnknown)
1317 * See Windows documentation for more details on IUnknown methods.
1319 static ULONG WINAPI DataCache_IPersistStorage_Release(
1320 IPersistStorage* iface)
1322 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1324 return IUnknown_Release(this->outerUnknown);
1327 /************************************************************************
1328 * DataCache_GetClassID (IPersistStorage)
1330 * The data cache doesn't implement this method.
1332 * See Windows documentation for more details on IPersistStorage methods.
1334 static HRESULT WINAPI DataCache_GetClassID(
1335 IPersistStorage* iface,
1336 CLSID* pClassID)
1338 TRACE("(%p, %p)\n", iface, pClassID);
1339 return E_NOTIMPL;
1342 /************************************************************************
1343 * DataCache_IsDirty (IPersistStorage)
1345 * Until we actully connect to a running object and retrieve new
1346 * information to it, we never get dirty.
1348 * See Windows documentation for more details on IPersistStorage methods.
1350 static HRESULT WINAPI DataCache_IsDirty(
1351 IPersistStorage* iface)
1353 TRACE("(%p)\n", iface);
1355 return S_FALSE;
1358 /************************************************************************
1359 * DataCache_InitNew (IPersistStorage)
1361 * The data cache implementation of IPersistStorage_InitNew simply stores
1362 * the storage pointer.
1364 * See Windows documentation for more details on IPersistStorage methods.
1366 static HRESULT WINAPI DataCache_InitNew(
1367 IPersistStorage* iface,
1368 IStorage* pStg)
1370 TRACE("(%p, %p)\n", iface, pStg);
1372 return DataCache_Load(iface, pStg);
1375 /************************************************************************
1376 * DataCache_Load (IPersistStorage)
1378 * The data cache implementation of IPersistStorage_Load doesn't
1379 * actually load anything. Instead, it holds on to the storage pointer
1380 * and it will load the presentation information when the
1381 * IDataObject_GetData or IViewObject2_Draw methods are called.
1383 * See Windows documentation for more details on IPersistStorage methods.
1385 static HRESULT WINAPI DataCache_Load(
1386 IPersistStorage* iface,
1387 IStorage* pStg)
1389 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1391 TRACE("(%p, %p)\n", iface, pStg);
1393 if (this->presentationStorage != NULL)
1395 IStorage_Release(this->presentationStorage);
1398 this->presentationStorage = pStg;
1400 if (this->presentationStorage != NULL)
1402 IStorage_AddRef(this->presentationStorage);
1404 return S_OK;
1407 /************************************************************************
1408 * DataCache_Save (IPersistStorage)
1410 * Until we actully connect to a running object and retrieve new
1411 * information to it, we never have to save anything. However, it is
1412 * our responsability to copy the information when saving to a new
1413 * storage.
1415 * See Windows documentation for more details on IPersistStorage methods.
1417 static HRESULT WINAPI DataCache_Save(
1418 IPersistStorage* iface,
1419 IStorage* pStg,
1420 BOOL fSameAsLoad)
1422 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1424 TRACE("(%p, %p, %d)\n", iface, pStg, fSameAsLoad);
1426 if ( (!fSameAsLoad) &&
1427 (this->presentationStorage!=NULL) )
1429 return IStorage_CopyTo(this->presentationStorage,
1431 NULL,
1432 NULL,
1433 pStg);
1436 return S_OK;
1439 /************************************************************************
1440 * DataCache_SaveCompleted (IPersistStorage)
1442 * This method is called to tell the cache to release the storage
1443 * pointer it's currentlu holding.
1445 * See Windows documentation for more details on IPersistStorage methods.
1447 static HRESULT WINAPI DataCache_SaveCompleted(
1448 IPersistStorage* iface,
1449 IStorage* pStgNew)
1451 TRACE("(%p, %p)\n", iface, pStgNew);
1453 if (pStgNew)
1456 * First, make sure we get our hands off any storage we have.
1459 DataCache_HandsOffStorage(iface);
1462 * Then, attach to the new storage.
1465 DataCache_Load(iface, pStgNew);
1468 return S_OK;
1471 /************************************************************************
1472 * DataCache_HandsOffStorage (IPersistStorage)
1474 * This method is called to tell the cache to release the storage
1475 * pointer it's currentlu holding.
1477 * See Windows documentation for more details on IPersistStorage methods.
1479 static HRESULT WINAPI DataCache_HandsOffStorage(
1480 IPersistStorage* iface)
1482 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1484 TRACE("(%p)\n", iface);
1486 if (this->presentationStorage != NULL)
1488 IStorage_Release(this->presentationStorage);
1489 this->presentationStorage = NULL;
1492 return S_OK;
1495 /*********************************************************
1496 * Method implementation for the IViewObject2
1497 * part of the DataCache class.
1500 /************************************************************************
1501 * DataCache_IViewObject2_QueryInterface (IUnknown)
1503 * See Windows documentation for more details on IUnknown methods.
1505 static HRESULT WINAPI DataCache_IViewObject2_QueryInterface(
1506 IViewObject2* iface,
1507 REFIID riid,
1508 void** ppvObject)
1510 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1512 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1515 /************************************************************************
1516 * DataCache_IViewObject2_AddRef (IUnknown)
1518 * See Windows documentation for more details on IUnknown methods.
1520 static ULONG WINAPI DataCache_IViewObject2_AddRef(
1521 IViewObject2* iface)
1523 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1525 return IUnknown_AddRef(this->outerUnknown);
1528 /************************************************************************
1529 * DataCache_IViewObject2_Release (IUnknown)
1531 * See Windows documentation for more details on IUnknown methods.
1533 static ULONG WINAPI DataCache_IViewObject2_Release(
1534 IViewObject2* iface)
1536 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1538 return IUnknown_Release(this->outerUnknown);
1541 /************************************************************************
1542 * DataCache_Draw (IViewObject2)
1544 * This method will draw the cached representation of the object
1545 * to the given device context.
1547 * See Windows documentation for more details on IViewObject2 methods.
1549 static HRESULT WINAPI DataCache_Draw(
1550 IViewObject2* iface,
1551 DWORD dwDrawAspect,
1552 LONG lindex,
1553 void* pvAspect,
1554 DVTARGETDEVICE* ptd,
1555 HDC hdcTargetDev,
1556 HDC hdcDraw,
1557 LPCRECTL lprcBounds,
1558 LPCRECTL lprcWBounds,
1559 IVO_ContCallback pfnContinue,
1560 DWORD dwContinue)
1562 PresentationDataHeader presData;
1563 HMETAFILE presMetafile = 0;
1564 HRESULT hres;
1566 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1568 TRACE("(%p, %lx, %ld, %p, %x, %x, %p, %p, %p, %lx)\n",
1569 iface,
1570 dwDrawAspect,
1571 lindex,
1572 pvAspect,
1573 hdcTargetDev,
1574 hdcDraw,
1575 lprcBounds,
1576 lprcWBounds,
1577 pfnContinue,
1578 dwContinue);
1581 * Sanity check
1583 if (lprcBounds==NULL)
1584 return E_INVALIDARG;
1587 * First, we need to retrieve the dimensions of the
1588 * image in the metafile.
1590 hres = DataCache_ReadPresentationData(this,
1591 dwDrawAspect,
1592 &presData);
1594 if (FAILED(hres))
1595 return hres;
1598 * Then, we can extract the metafile itself from the cached
1599 * data.
1601 * FIXME Unless it isn't a metafile. I think it could be any CF_XXX type,
1602 * particularly CF_DIB.
1604 presMetafile = DataCache_ReadPresMetafile(this,
1605 dwDrawAspect);
1608 * If we have a metafile, just draw baby...
1609 * We have to be careful not to modify the state of the
1610 * DC.
1612 if (presMetafile!=0)
1614 INT prevMapMode = SetMapMode(hdcDraw, MM_ANISOTROPIC);
1615 SIZE oldWindowExt;
1616 SIZE oldViewportExt;
1617 POINT oldViewportOrg;
1619 SetWindowExtEx(hdcDraw,
1620 presData.dwObjectExtentX,
1621 presData.dwObjectExtentY,
1622 &oldWindowExt);
1624 SetViewportExtEx(hdcDraw,
1625 lprcBounds->right - lprcBounds->left,
1626 lprcBounds->bottom - lprcBounds->top,
1627 &oldViewportExt);
1629 SetViewportOrgEx(hdcDraw,
1630 lprcBounds->left,
1631 lprcBounds->top,
1632 &oldViewportOrg);
1634 PlayMetaFile(hdcDraw, presMetafile);
1636 SetWindowExtEx(hdcDraw,
1637 oldWindowExt.cx,
1638 oldWindowExt.cy,
1639 NULL);
1641 SetViewportExtEx(hdcDraw,
1642 oldViewportExt.cx,
1643 oldViewportExt.cy,
1644 NULL);
1646 SetViewportOrgEx(hdcDraw,
1647 oldViewportOrg.x,
1648 oldViewportOrg.y,
1649 NULL);
1651 SetMapMode(hdcDraw, prevMapMode);
1653 DeleteMetaFile(presMetafile);
1656 return S_OK;
1659 static HRESULT WINAPI DataCache_GetColorSet(
1660 IViewObject2* iface,
1661 DWORD dwDrawAspect,
1662 LONG lindex,
1663 void* pvAspect,
1664 DVTARGETDEVICE* ptd,
1665 HDC hicTargetDevice,
1666 LOGPALETTE** ppColorSet)
1668 FIXME("stub\n");
1669 return E_NOTIMPL;
1672 static HRESULT WINAPI DataCache_Freeze(
1673 IViewObject2* iface,
1674 DWORD dwDrawAspect,
1675 LONG lindex,
1676 void* pvAspect,
1677 DWORD* pdwFreeze)
1679 FIXME("stub\n");
1680 return E_NOTIMPL;
1683 static HRESULT WINAPI DataCache_Unfreeze(
1684 IViewObject2* iface,
1685 DWORD dwFreeze)
1687 FIXME("stub\n");
1688 return E_NOTIMPL;
1691 /************************************************************************
1692 * DataCache_SetAdvise (IViewObject2)
1694 * This sets-up an advisory sink with the data cache. When the object's
1695 * view changes, this sink is called.
1697 * See Windows documentation for more details on IViewObject2 methods.
1699 static HRESULT WINAPI DataCache_SetAdvise(
1700 IViewObject2* iface,
1701 DWORD aspects,
1702 DWORD advf,
1703 IAdviseSink* pAdvSink)
1705 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1707 TRACE("(%p, %lx, %lx, %p)\n", iface, aspects, advf, pAdvSink);
1710 * A call to this function removes the previous sink
1712 if (this->sinkInterface != NULL)
1714 IAdviseSink_Release(this->sinkInterface);
1715 this->sinkInterface = NULL;
1716 this->sinkAspects = 0;
1717 this->sinkAdviseFlag = 0;
1721 * Now, setup the new one.
1723 if (pAdvSink!=NULL)
1725 this->sinkInterface = pAdvSink;
1726 this->sinkAspects = aspects;
1727 this->sinkAdviseFlag = advf;
1729 IAdviseSink_AddRef(this->sinkInterface);
1733 * When the ADVF_PRIMEFIRST flag is set, we have to advise the
1734 * sink immediately.
1736 if (advf & ADVF_PRIMEFIRST)
1738 DataCache_FireOnViewChange(this,
1739 DVASPECT_CONTENT,
1740 -1);
1743 return S_OK;
1746 /************************************************************************
1747 * DataCache_GetAdvise (IViewObject2)
1749 * This method queries the current state of the advise sink
1750 * installed on the data cache.
1752 * See Windows documentation for more details on IViewObject2 methods.
1754 static HRESULT WINAPI DataCache_GetAdvise(
1755 IViewObject2* iface,
1756 DWORD* pAspects,
1757 DWORD* pAdvf,
1758 IAdviseSink** ppAdvSink)
1760 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1762 TRACE("(%p, %p, %p, %p)\n", iface, pAspects, pAdvf, ppAdvSink);
1765 * Just copy all the requested values.
1767 if (pAspects!=NULL)
1768 *pAspects = this->sinkAspects;
1770 if (pAdvf!=NULL)
1771 *pAdvf = this->sinkAdviseFlag;
1773 if (ppAdvSink!=NULL)
1775 IAdviseSink_QueryInterface(this->sinkInterface,
1776 &IID_IAdviseSink,
1777 (void**)ppAdvSink);
1780 return S_OK;
1783 /************************************************************************
1784 * DataCache_GetExtent (IViewObject2)
1786 * This method retrieves the "natural" size of this cached object.
1788 * See Windows documentation for more details on IViewObject2 methods.
1790 static HRESULT WINAPI DataCache_GetExtent(
1791 IViewObject2* iface,
1792 DWORD dwDrawAspect,
1793 LONG lindex,
1794 DVTARGETDEVICE* ptd,
1795 LPSIZEL lpsizel)
1797 PresentationDataHeader presData;
1798 HRESULT hres = E_FAIL;
1800 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1802 TRACE("(%p, %lx, %ld, %p, %p)\n",
1803 iface, dwDrawAspect, lindex, ptd, lpsizel);
1806 * Sanity check
1808 if (lpsizel==NULL)
1809 return E_POINTER;
1812 * Initialize the out parameter.
1814 lpsizel->cx = 0;
1815 lpsizel->cy = 0;
1818 * This flag should be set to -1.
1820 if (lindex!=-1)
1821 FIXME("Unimplemented flag lindex = %ld\n", lindex);
1824 * Right now, we suport only the callback from
1825 * the default handler.
1827 if (ptd!=NULL)
1828 FIXME("Unimplemented ptd = %p\n", ptd);
1831 * Get the presentation information from the
1832 * cache.
1834 hres = DataCache_ReadPresentationData(this,
1835 dwDrawAspect,
1836 &presData);
1838 if (SUCCEEDED(hres))
1840 lpsizel->cx = presData.dwObjectExtentX;
1841 lpsizel->cy = presData.dwObjectExtentY;
1845 * This method returns OLE_E_BLANK when it fails.
1847 if (FAILED(hres))
1848 hres = OLE_E_BLANK;
1850 return hres;
1854 /*********************************************************
1855 * Method implementation for the IOleCache2
1856 * part of the DataCache class.
1859 /************************************************************************
1860 * DataCache_IOleCache2_QueryInterface (IUnknown)
1862 * See Windows documentation for more details on IUnknown methods.
1864 static HRESULT WINAPI DataCache_IOleCache2_QueryInterface(
1865 IOleCache2* iface,
1866 REFIID riid,
1867 void** ppvObject)
1869 _ICOM_THIS_From_IOleCache2(DataCache, iface);
1871 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1874 /************************************************************************
1875 * DataCache_IOleCache2_AddRef (IUnknown)
1877 * See Windows documentation for more details on IUnknown methods.
1879 static ULONG WINAPI DataCache_IOleCache2_AddRef(
1880 IOleCache2* iface)
1882 _ICOM_THIS_From_IOleCache2(DataCache, iface);
1884 return IUnknown_AddRef(this->outerUnknown);
1887 /************************************************************************
1888 * DataCache_IOleCache2_Release (IUnknown)
1890 * See Windows documentation for more details on IUnknown methods.
1892 static ULONG WINAPI DataCache_IOleCache2_Release(
1893 IOleCache2* iface)
1895 _ICOM_THIS_From_IOleCache2(DataCache, iface);
1897 return IUnknown_Release(this->outerUnknown);
1900 static HRESULT WINAPI DataCache_Cache(
1901 IOleCache2* iface,
1902 FORMATETC* pformatetc,
1903 DWORD advf,
1904 DWORD* pdwConnection)
1906 FIXME("stub\n");
1907 return E_NOTIMPL;
1910 static HRESULT WINAPI DataCache_Uncache(
1911 IOleCache2* iface,
1912 DWORD dwConnection)
1914 FIXME("stub\n");
1915 return E_NOTIMPL;
1918 static HRESULT WINAPI DataCache_EnumCache(
1919 IOleCache2* iface,
1920 IEnumSTATDATA** ppenumSTATDATA)
1922 FIXME("stub\n");
1923 return E_NOTIMPL;
1926 static HRESULT WINAPI DataCache_InitCache(
1927 IOleCache2* iface,
1928 IDataObject* pDataObject)
1930 FIXME("stub\n");
1931 return E_NOTIMPL;
1934 static HRESULT WINAPI DataCache_IOleCache2_SetData(
1935 IOleCache2* iface,
1936 FORMATETC* pformatetc,
1937 STGMEDIUM* pmedium,
1938 BOOL fRelease)
1940 FIXME("stub\n");
1941 return E_NOTIMPL;
1944 static HRESULT WINAPI DataCache_UpdateCache(
1945 IOleCache2* iface,
1946 LPDATAOBJECT pDataObject,
1947 DWORD grfUpdf,
1948 LPVOID pReserved)
1950 FIXME("stub\n");
1951 return E_NOTIMPL;
1954 static HRESULT WINAPI DataCache_DiscardCache(
1955 IOleCache2* iface,
1956 DWORD dwDiscardOptions)
1958 FIXME("stub\n");
1959 return E_NOTIMPL;
1963 /*********************************************************
1964 * Method implementation for the IOleCacheControl
1965 * part of the DataCache class.
1968 /************************************************************************
1969 * DataCache_IOleCacheControl_QueryInterface (IUnknown)
1971 * See Windows documentation for more details on IUnknown methods.
1973 static HRESULT WINAPI DataCache_IOleCacheControl_QueryInterface(
1974 IOleCacheControl* iface,
1975 REFIID riid,
1976 void** ppvObject)
1978 _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
1980 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1983 /************************************************************************
1984 * DataCache_IOleCacheControl_AddRef (IUnknown)
1986 * See Windows documentation for more details on IUnknown methods.
1988 static ULONG WINAPI DataCache_IOleCacheControl_AddRef(
1989 IOleCacheControl* iface)
1991 _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
1993 return IUnknown_AddRef(this->outerUnknown);
1996 /************************************************************************
1997 * DataCache_IOleCacheControl_Release (IUnknown)
1999 * See Windows documentation for more details on IUnknown methods.
2001 static ULONG WINAPI DataCache_IOleCacheControl_Release(
2002 IOleCacheControl* iface)
2004 _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
2006 return IUnknown_Release(this->outerUnknown);
2009 static HRESULT WINAPI DataCache_OnRun(
2010 IOleCacheControl* iface,
2011 LPDATAOBJECT pDataObject)
2013 FIXME("stub\n");
2014 return E_NOTIMPL;
2017 static HRESULT WINAPI DataCache_OnStop(
2018 IOleCacheControl* iface)
2020 FIXME("stub\n");
2021 return E_NOTIMPL;