Cleaned up a few inter-dll dependencies.
[wine.git] / dlls / ole32 / datacache.c
blob5e2853cae83160de1dfe7a6b1a069a556ae6e416
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_oleview.h"
39 #include "wine/obj_cache.h"
40 #include "wine/unicode.h"
41 #include "ole2.h"
42 #include "debugtools.h"
44 DEFAULT_DEBUG_CHANNEL(ole);
46 /****************************************************************************
47 * PresentationDataHeader
49 * This structure represents the header of the \002OlePresXXX stream in
50 * the OLE object strorage.
52 * Most fields are still unknown.
54 typedef struct PresentationDataHeader
56 DWORD unknown1; /* -1 */
57 DWORD unknown2; /* 3, possibly CF_METAFILEPICT */
58 DWORD unknown3; /* 4, possibly TYMED_ISTREAM */
59 DVASPECT dvAspect;
60 DWORD unknown5; /* -1 */
62 DWORD unknown6;
63 DWORD unknown7; /* 0 */
64 DWORD dwObjectExtentX;
65 DWORD dwObjectExtentY;
66 DWORD dwSize;
67 } PresentationDataHeader;
69 /****************************************************************************
70 * DataCache
72 struct DataCache
75 * List all interface VTables here
77 ICOM_VTABLE(IDataObject)* lpvtbl1;
78 ICOM_VTABLE(IUnknown)* lpvtbl2;
79 ICOM_VTABLE(IPersistStorage)* lpvtbl3;
80 ICOM_VTABLE(IViewObject2)* lpvtbl4;
81 ICOM_VTABLE(IOleCache2)* lpvtbl5;
82 ICOM_VTABLE(IOleCacheControl)* lpvtbl6;
85 * Reference count of this object
87 ULONG ref;
90 * IUnknown implementation of the outer object.
92 IUnknown* outerUnknown;
95 * This storage pointer is set through a call to
96 * IPersistStorage_Load. This is where the visual
97 * representation of the object is stored.
99 IStorage* presentationStorage;
102 * The user of this object can setup ONE advise sink
103 * connection with the object. These parameters describe
104 * that connection.
106 DWORD sinkAspects;
107 DWORD sinkAdviseFlag;
108 IAdviseSink* sinkInterface;
112 typedef struct DataCache DataCache;
115 * Here, I define utility macros to help with the casting of the
116 * "this" parameter.
117 * There is a version to accomodate all of the VTables implemented
118 * by this object.
120 #define _ICOM_THIS_From_IDataObject(class,name) class* this = (class*)name;
121 #define _ICOM_THIS_From_NDIUnknown(class, name) class* this = (class*)(((char*)name)-sizeof(void*));
122 #define _ICOM_THIS_From_IPersistStorage(class, name) class* this = (class*)(((char*)name)-2*sizeof(void*));
123 #define _ICOM_THIS_From_IViewObject2(class, name) class* this = (class*)(((char*)name)-3*sizeof(void*));
124 #define _ICOM_THIS_From_IOleCache2(class, name) class* this = (class*)(((char*)name)-4*sizeof(void*));
125 #define _ICOM_THIS_From_IOleCacheControl(class, name) class* this = (class*)(((char*)name)-5*sizeof(void*));
128 * Prototypes for the methods of the DataCache class.
130 static DataCache* DataCache_Construct(REFCLSID clsid,
131 LPUNKNOWN pUnkOuter);
132 static void DataCache_Destroy(DataCache* ptrToDestroy);
133 static HRESULT DataCache_ReadPresentationData(DataCache* this,
134 DWORD drawAspect,
135 PresentationDataHeader* header);
136 static HRESULT DataCache_OpenPresStream(DataCache *this,
137 DWORD drawAspect,
138 IStream **pStm);
139 static HMETAFILE DataCache_ReadPresMetafile(DataCache* this,
140 DWORD drawAspect);
141 static void DataCache_FireOnViewChange(DataCache* this,
142 DWORD aspect,
143 LONG lindex);
146 * Prototypes for the methods of the DataCache class
147 * that implement non delegating IUnknown methods.
149 static HRESULT WINAPI DataCache_NDIUnknown_QueryInterface(
150 IUnknown* iface,
151 REFIID riid,
152 void** ppvObject);
153 static ULONG WINAPI DataCache_NDIUnknown_AddRef(
154 IUnknown* iface);
155 static ULONG WINAPI DataCache_NDIUnknown_Release(
156 IUnknown* iface);
159 * Prototypes for the methods of the DataCache class
160 * that implement IDataObject methods.
162 static HRESULT WINAPI DataCache_IDataObject_QueryInterface(
163 IDataObject* iface,
164 REFIID riid,
165 void** ppvObject);
166 static ULONG WINAPI DataCache_IDataObject_AddRef(
167 IDataObject* iface);
168 static ULONG WINAPI DataCache_IDataObject_Release(
169 IDataObject* iface);
170 static HRESULT WINAPI DataCache_GetData(
171 IDataObject* iface,
172 LPFORMATETC pformatetcIn,
173 STGMEDIUM* pmedium);
174 static HRESULT WINAPI DataCache_GetDataHere(
175 IDataObject* iface,
176 LPFORMATETC pformatetc,
177 STGMEDIUM* pmedium);
178 static HRESULT WINAPI DataCache_QueryGetData(
179 IDataObject* iface,
180 LPFORMATETC pformatetc);
181 static HRESULT WINAPI DataCache_GetCanonicalFormatEtc(
182 IDataObject* iface,
183 LPFORMATETC pformatectIn,
184 LPFORMATETC pformatetcOut);
185 static HRESULT WINAPI DataCache_IDataObject_SetData(
186 IDataObject* iface,
187 LPFORMATETC pformatetc,
188 STGMEDIUM* pmedium,
189 BOOL fRelease);
190 static HRESULT WINAPI DataCache_EnumFormatEtc(
191 IDataObject* iface,
192 DWORD dwDirection,
193 IEnumFORMATETC** ppenumFormatEtc);
194 static HRESULT WINAPI DataCache_DAdvise(
195 IDataObject* iface,
196 FORMATETC* pformatetc,
197 DWORD advf,
198 IAdviseSink* pAdvSink,
199 DWORD* pdwConnection);
200 static HRESULT WINAPI DataCache_DUnadvise(
201 IDataObject* iface,
202 DWORD dwConnection);
203 static HRESULT WINAPI DataCache_EnumDAdvise(
204 IDataObject* iface,
205 IEnumSTATDATA** ppenumAdvise);
208 * Prototypes for the methods of the DataCache class
209 * that implement IPersistStorage methods.
211 static HRESULT WINAPI DataCache_IPersistStorage_QueryInterface(
212 IPersistStorage* iface,
213 REFIID riid,
214 void** ppvObject);
215 static ULONG WINAPI DataCache_IPersistStorage_AddRef(
216 IPersistStorage* iface);
217 static ULONG WINAPI DataCache_IPersistStorage_Release(
218 IPersistStorage* iface);
219 static HRESULT WINAPI DataCache_GetClassID(
220 IPersistStorage* iface,
221 CLSID* pClassID);
222 static HRESULT WINAPI DataCache_IsDirty(
223 IPersistStorage* iface);
224 static HRESULT WINAPI DataCache_InitNew(
225 IPersistStorage* iface,
226 IStorage* pStg);
227 static HRESULT WINAPI DataCache_Load(
228 IPersistStorage* iface,
229 IStorage* pStg);
230 static HRESULT WINAPI DataCache_Save(
231 IPersistStorage* iface,
232 IStorage* pStg,
233 BOOL fSameAsLoad);
234 static HRESULT WINAPI DataCache_SaveCompleted(
235 IPersistStorage* iface,
236 IStorage* pStgNew);
237 static HRESULT WINAPI DataCache_HandsOffStorage(
238 IPersistStorage* iface);
241 * Prototypes for the methods of the DataCache class
242 * that implement IViewObject2 methods.
244 static HRESULT WINAPI DataCache_IViewObject2_QueryInterface(
245 IViewObject2* iface,
246 REFIID riid,
247 void** ppvObject);
248 static ULONG WINAPI DataCache_IViewObject2_AddRef(
249 IViewObject2* iface);
250 static ULONG WINAPI DataCache_IViewObject2_Release(
251 IViewObject2* iface);
252 static HRESULT WINAPI DataCache_Draw(
253 IViewObject2* iface,
254 DWORD dwDrawAspect,
255 LONG lindex,
256 void* pvAspect,
257 DVTARGETDEVICE* ptd,
258 HDC hdcTargetDev,
259 HDC hdcDraw,
260 LPCRECTL lprcBounds,
261 LPCRECTL lprcWBounds,
262 IVO_ContCallback pfnContinue,
263 DWORD dwContinue);
264 static HRESULT WINAPI DataCache_GetColorSet(
265 IViewObject2* iface,
266 DWORD dwDrawAspect,
267 LONG lindex,
268 void* pvAspect,
269 DVTARGETDEVICE* ptd,
270 HDC hicTargetDevice,
271 LOGPALETTE** ppColorSet);
272 static HRESULT WINAPI DataCache_Freeze(
273 IViewObject2* iface,
274 DWORD dwDrawAspect,
275 LONG lindex,
276 void* pvAspect,
277 DWORD* pdwFreeze);
278 static HRESULT WINAPI DataCache_Unfreeze(
279 IViewObject2* iface,
280 DWORD dwFreeze);
281 static HRESULT WINAPI DataCache_SetAdvise(
282 IViewObject2* iface,
283 DWORD aspects,
284 DWORD advf,
285 IAdviseSink* pAdvSink);
286 static HRESULT WINAPI DataCache_GetAdvise(
287 IViewObject2* iface,
288 DWORD* pAspects,
289 DWORD* pAdvf,
290 IAdviseSink** ppAdvSink);
291 static HRESULT WINAPI DataCache_GetExtent(
292 IViewObject2* iface,
293 DWORD dwDrawAspect,
294 LONG lindex,
295 DVTARGETDEVICE* ptd,
296 LPSIZEL lpsizel);
299 * Prototypes for the methods of the DataCache class
300 * that implement IOleCache2 methods.
302 static HRESULT WINAPI DataCache_IOleCache2_QueryInterface(
303 IOleCache2* iface,
304 REFIID riid,
305 void** ppvObject);
306 static ULONG WINAPI DataCache_IOleCache2_AddRef(
307 IOleCache2* iface);
308 static ULONG WINAPI DataCache_IOleCache2_Release(
309 IOleCache2* iface);
310 static HRESULT WINAPI DataCache_Cache(
311 IOleCache2* iface,
312 FORMATETC* pformatetc,
313 DWORD advf,
314 DWORD* pdwConnection);
315 static HRESULT WINAPI DataCache_Uncache(
316 IOleCache2* iface,
317 DWORD dwConnection);
318 static HRESULT WINAPI DataCache_EnumCache(
319 IOleCache2* iface,
320 IEnumSTATDATA** ppenumSTATDATA);
321 static HRESULT WINAPI DataCache_InitCache(
322 IOleCache2* iface,
323 IDataObject* pDataObject);
324 static HRESULT WINAPI DataCache_IOleCache2_SetData(
325 IOleCache2* iface,
326 FORMATETC* pformatetc,
327 STGMEDIUM* pmedium,
328 BOOL fRelease);
329 static HRESULT WINAPI DataCache_UpdateCache(
330 IOleCache2* iface,
331 LPDATAOBJECT pDataObject,
332 DWORD grfUpdf,
333 LPVOID pReserved);
334 static HRESULT WINAPI DataCache_DiscardCache(
335 IOleCache2* iface,
336 DWORD dwDiscardOptions);
339 * Prototypes for the methods of the DataCache class
340 * that implement IOleCacheControl methods.
342 static HRESULT WINAPI DataCache_IOleCacheControl_QueryInterface(
343 IOleCacheControl* iface,
344 REFIID riid,
345 void** ppvObject);
346 static ULONG WINAPI DataCache_IOleCacheControl_AddRef(
347 IOleCacheControl* iface);
348 static ULONG WINAPI DataCache_IOleCacheControl_Release(
349 IOleCacheControl* iface);
350 static HRESULT WINAPI DataCache_OnRun(
351 IOleCacheControl* iface,
352 LPDATAOBJECT pDataObject);
353 static HRESULT WINAPI DataCache_OnStop(
354 IOleCacheControl* iface);
357 * Virtual function tables for the DataCache class.
359 static ICOM_VTABLE(IUnknown) DataCache_NDIUnknown_VTable =
361 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
362 DataCache_NDIUnknown_QueryInterface,
363 DataCache_NDIUnknown_AddRef,
364 DataCache_NDIUnknown_Release
367 static ICOM_VTABLE(IDataObject) DataCache_IDataObject_VTable =
369 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
370 DataCache_IDataObject_QueryInterface,
371 DataCache_IDataObject_AddRef,
372 DataCache_IDataObject_Release,
373 DataCache_GetData,
374 DataCache_GetDataHere,
375 DataCache_QueryGetData,
376 DataCache_GetCanonicalFormatEtc,
377 DataCache_IDataObject_SetData,
378 DataCache_EnumFormatEtc,
379 DataCache_DAdvise,
380 DataCache_DUnadvise,
381 DataCache_EnumDAdvise
384 static ICOM_VTABLE(IPersistStorage) DataCache_IPersistStorage_VTable =
386 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
387 DataCache_IPersistStorage_QueryInterface,
388 DataCache_IPersistStorage_AddRef,
389 DataCache_IPersistStorage_Release,
390 DataCache_GetClassID,
391 DataCache_IsDirty,
392 DataCache_InitNew,
393 DataCache_Load,
394 DataCache_Save,
395 DataCache_SaveCompleted,
396 DataCache_HandsOffStorage
399 static ICOM_VTABLE(IViewObject2) DataCache_IViewObject2_VTable =
401 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
402 DataCache_IViewObject2_QueryInterface,
403 DataCache_IViewObject2_AddRef,
404 DataCache_IViewObject2_Release,
405 DataCache_Draw,
406 DataCache_GetColorSet,
407 DataCache_Freeze,
408 DataCache_Unfreeze,
409 DataCache_SetAdvise,
410 DataCache_GetAdvise,
411 DataCache_GetExtent
414 static ICOM_VTABLE(IOleCache2) DataCache_IOleCache2_VTable =
416 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
417 DataCache_IOleCache2_QueryInterface,
418 DataCache_IOleCache2_AddRef,
419 DataCache_IOleCache2_Release,
420 DataCache_Cache,
421 DataCache_Uncache,
422 DataCache_EnumCache,
423 DataCache_InitCache,
424 DataCache_IOleCache2_SetData,
425 DataCache_UpdateCache,
426 DataCache_DiscardCache
429 static ICOM_VTABLE(IOleCacheControl) DataCache_IOleCacheControl_VTable =
431 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
432 DataCache_IOleCacheControl_QueryInterface,
433 DataCache_IOleCacheControl_AddRef,
434 DataCache_IOleCacheControl_Release,
435 DataCache_OnRun,
436 DataCache_OnStop
439 /******************************************************************************
440 * CreateDataCache [OLE32.54]
442 HRESULT WINAPI CreateDataCache(
443 LPUNKNOWN pUnkOuter,
444 REFCLSID rclsid,
445 REFIID riid,
446 LPVOID* ppvObj)
448 DataCache* newCache = NULL;
449 HRESULT hr = S_OK;
451 TRACE("(%s, %p, %s, %p)\n", debugstr_guid(rclsid), pUnkOuter, debugstr_guid(riid), ppvObj);
454 * Sanity check
456 if (ppvObj==0)
457 return E_POINTER;
459 *ppvObj = 0;
462 * If this cache is constructed for aggregation, make sure
463 * the caller is requesting the IUnknown interface.
464 * This is necessary because it's the only time the non-delegating
465 * IUnknown pointer can be returned to the outside.
467 if ( (pUnkOuter!=NULL) &&
468 (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) != 0) )
469 return CLASS_E_NOAGGREGATION;
472 * Try to construct a new instance of the class.
474 newCache = DataCache_Construct(rclsid,
475 pUnkOuter);
477 if (newCache == 0)
478 return E_OUTOFMEMORY;
481 * Make sure it supports the interface required by the caller.
483 hr = IUnknown_QueryInterface((IUnknown*)&(newCache->lpvtbl2), riid, ppvObj);
486 * Release the reference obtained in the constructor. If
487 * the QueryInterface was unsuccessful, it will free the class.
489 IUnknown_Release((IUnknown*)&(newCache->lpvtbl2));
491 return hr;
494 /*********************************************************
495 * Method implementation for DataCache class.
497 static DataCache* DataCache_Construct(
498 REFCLSID clsid,
499 LPUNKNOWN pUnkOuter)
501 DataCache* newObject = 0;
504 * Allocate space for the object.
506 newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(DataCache));
508 if (newObject==0)
509 return newObject;
512 * Initialize the virtual function table.
514 newObject->lpvtbl1 = &DataCache_IDataObject_VTable;
515 newObject->lpvtbl2 = &DataCache_NDIUnknown_VTable;
516 newObject->lpvtbl3 = &DataCache_IPersistStorage_VTable;
517 newObject->lpvtbl4 = &DataCache_IViewObject2_VTable;
518 newObject->lpvtbl5 = &DataCache_IOleCache2_VTable;
519 newObject->lpvtbl6 = &DataCache_IOleCacheControl_VTable;
522 * Start with one reference count. The caller of this function
523 * must release the interface pointer when it is done.
525 newObject->ref = 1;
528 * Initialize the outer unknown
529 * We don't keep a reference on the outer unknown since, the way
530 * aggregation works, our lifetime is at least as large as it's
531 * lifetime.
533 if (pUnkOuter==NULL)
534 pUnkOuter = (IUnknown*)&(newObject->lpvtbl2);
536 newObject->outerUnknown = pUnkOuter;
539 * Initialize the other members of the structure.
541 newObject->presentationStorage = NULL;
542 newObject->sinkAspects = 0;
543 newObject->sinkAdviseFlag = 0;
544 newObject->sinkInterface = 0;
546 return newObject;
549 static void DataCache_Destroy(
550 DataCache* ptrToDestroy)
552 TRACE("()\n");
554 if (ptrToDestroy->sinkInterface != NULL)
556 IAdviseSink_Release(ptrToDestroy->sinkInterface);
557 ptrToDestroy->sinkInterface = NULL;
560 if (ptrToDestroy->presentationStorage != NULL)
562 IStorage_Release(ptrToDestroy->presentationStorage);
563 ptrToDestroy->presentationStorage = NULL;
567 * Free the datacache pointer.
569 HeapFree(GetProcessHeap(), 0, ptrToDestroy);
572 /************************************************************************
573 * DataCache_ReadPresentationData
575 * This method will read information for the requested presentation
576 * into the given structure.
578 * Param:
579 * this - Pointer to the DataCache object
580 * drawAspect - The aspect of the object that we wish to draw.
581 * header - The structure containing information about this
582 * aspect of the object.
584 static HRESULT DataCache_ReadPresentationData(
585 DataCache* this,
586 DWORD drawAspect,
587 PresentationDataHeader* header)
589 IStream* presStream = NULL;
590 HRESULT hres;
593 * Open the presentation stream.
595 hres = DataCache_OpenPresStream(
596 this,
597 drawAspect,
598 &presStream);
600 if (FAILED(hres))
601 return hres;
604 * Read the header.
607 hres = IStream_Read(
608 presStream,
609 header,
610 sizeof(PresentationDataHeader),
611 NULL);
614 * Cleanup.
616 IStream_Release(presStream);
619 * We don't want to propagate any other error
620 * code than a failure.
622 if (hres!=S_OK)
623 hres = E_FAIL;
625 return hres;
628 /************************************************************************
629 * DataCache_FireOnViewChange
631 * This method will fire an OnViewChange notification to the advise
632 * sink registered with the datacache.
634 * See IAdviseSink::OnViewChange for more details.
636 static void DataCache_FireOnViewChange(
637 DataCache* this,
638 DWORD aspect,
639 LONG lindex)
641 TRACE("(%p, %lx, %ld)\n", this, aspect, lindex);
644 * The sink supplies a filter when it registers
645 * we make sure we only send the notifications when that
646 * filter matches.
648 if ((this->sinkAspects & aspect) != 0)
650 if (this->sinkInterface != NULL)
652 IAdviseSink_OnViewChange(this->sinkInterface,
653 aspect,
654 lindex);
657 * Some sinks want to be unregistered automatically when
658 * the first notification goes out.
660 if ( (this->sinkAdviseFlag & ADVF_ONLYONCE) != 0)
662 IAdviseSink_Release(this->sinkInterface);
664 this->sinkInterface = NULL;
665 this->sinkAspects = 0;
666 this->sinkAdviseFlag = 0;
672 /* Helper for DataCache_OpenPresStream */
673 static BOOL DataCache_IsPresentationStream(const STATSTG *elem)
675 /* The presentation streams have names of the form "\002OlePresXXX",
676 * where XXX goes from 000 to 999. */
677 static const WCHAR OlePres[] = { 2,'O','l','e','P','r','e','s' };
679 LPCWSTR name = elem->pwcsName;
681 return (elem->type == STGTY_STREAM)
682 && (elem->cbSize.s.LowPart >= sizeof(PresentationDataHeader))
683 && (strlenW(name) == 11)
684 && (strncmpW(name, OlePres, 8) == 0)
685 && (name[8] >= '0') && (name[8] <= '9')
686 && (name[9] >= '0') && (name[9] <= '9')
687 && (name[10] >= '0') && (name[10] <= '9');
690 /************************************************************************
691 * DataCache_OpenPresStream
693 * This method will find the stream for the given presentation. It makes
694 * no attempt at fallback.
696 * Param:
697 * this - Pointer to the DataCache object
698 * drawAspect - The aspect of the object that we wish to draw.
699 * pStm - A returned stream. It points to the beginning of the
700 * - presentation data, including the header.
702 * Errors:
703 * S_OK The requested stream has been opened.
704 * OLE_E_BLANK The requested stream could not be found.
705 * Quite a few others I'm too lazy to map correctly.
707 * Notes:
708 * Algorithm: Scan the elements of the presentation storage, looking
709 * for presentation streams. For each presentation stream,
710 * load the header and check to see if the aspect maches.
712 * If a fallback is desired, just opening the first presentation stream
713 * is a possibility.
715 static HRESULT DataCache_OpenPresStream(
716 DataCache *this,
717 DWORD drawAspect,
718 IStream **ppStm)
720 STATSTG elem;
721 IEnumSTATSTG *pEnum;
722 HRESULT hr;
724 if (!ppStm) return E_POINTER;
726 hr = IStorage_EnumElements(this->presentationStorage, 0, NULL, 0, &pEnum);
727 if (FAILED(hr)) return hr;
729 while ((hr = IEnumSTATSTG_Next(pEnum, 1, &elem, NULL)) == S_OK)
731 if (DataCache_IsPresentationStream(&elem))
733 IStream *pStm;
735 hr = IStorage_OpenStream(this->presentationStorage, elem.pwcsName,
736 NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0,
737 &pStm);
738 if (SUCCEEDED(hr))
740 PresentationDataHeader header;
741 ULONG actual_read;
743 hr = IStream_Read(pStm, &header, sizeof(header), &actual_read);
745 /* can't use SUCCEEDED(hr): S_FALSE counts as an error */
746 if (hr == S_OK && actual_read == sizeof(header)
747 && header.dvAspect == drawAspect)
749 /* Rewind the stream before returning it. */
750 LARGE_INTEGER offset;
751 offset.s.LowPart = 0;
752 offset.s.HighPart = 0;
753 IStream_Seek(pStm, offset, STREAM_SEEK_SET, NULL);
755 *ppStm = pStm;
757 CoTaskMemFree(elem.pwcsName);
758 IEnumSTATSTG_Release(pEnum);
760 return S_OK;
763 IStream_Release(pStm);
767 CoTaskMemFree(elem.pwcsName);
770 IEnumSTATSTG_Release(pEnum);
772 return (hr == S_FALSE ? OLE_E_BLANK : hr);
775 /************************************************************************
776 * DataCache_ReadPresentationData
778 * This method will read information for the requested presentation
779 * into the given structure.
781 * Param:
782 * this - Pointer to the DataCache object
783 * drawAspect - The aspect of the object that we wish to draw.
785 * Returns:
786 * This method returns a metafile handle if it is successful.
787 * it will return 0 if not.
789 static HMETAFILE DataCache_ReadPresMetafile(
790 DataCache* this,
791 DWORD drawAspect)
793 LARGE_INTEGER offset;
794 IStream* presStream = NULL;
795 HRESULT hres;
796 void* metafileBits;
797 STATSTG streamInfo;
798 HMETAFILE newMetafile = 0;
801 * Open the presentation stream.
803 hres = DataCache_OpenPresStream(
804 this,
805 drawAspect,
806 &presStream);
808 if (FAILED(hres))
809 return hres;
812 * Get the size of the stream.
814 hres = IStream_Stat(presStream,
815 &streamInfo,
816 STATFLAG_NONAME);
819 * Skip the header
821 offset.s.HighPart = 0;
822 offset.s.LowPart = sizeof(PresentationDataHeader);
824 hres = IStream_Seek(
825 presStream,
826 offset,
827 STREAM_SEEK_SET,
828 NULL);
830 streamInfo.cbSize.s.LowPart -= offset.s.LowPart;
833 * Allocate a buffer for the metafile bits.
835 metafileBits = HeapAlloc(GetProcessHeap(),
837 streamInfo.cbSize.s.LowPart);
840 * Read the metafile bits.
842 hres = IStream_Read(
843 presStream,
844 metafileBits,
845 streamInfo.cbSize.s.LowPart,
846 NULL);
849 * Create a metafile with those bits.
851 if (SUCCEEDED(hres))
853 newMetafile = SetMetaFileBitsEx(streamInfo.cbSize.s.LowPart, metafileBits);
857 * Cleanup.
859 HeapFree(GetProcessHeap(), 0, metafileBits);
860 IStream_Release(presStream);
862 if (newMetafile==0)
863 hres = E_FAIL;
865 return newMetafile;
868 /*********************************************************
869 * Method implementation for the non delegating IUnknown
870 * part of the DataCache class.
873 /************************************************************************
874 * DataCache_NDIUnknown_QueryInterface (IUnknown)
876 * See Windows documentation for more details on IUnknown methods.
878 * This version of QueryInterface will not delegate it's implementation
879 * to the outer unknown.
881 static HRESULT WINAPI DataCache_NDIUnknown_QueryInterface(
882 IUnknown* iface,
883 REFIID riid,
884 void** ppvObject)
886 _ICOM_THIS_From_NDIUnknown(DataCache, iface);
889 * Perform a sanity check on the parameters.
891 if ( (this==0) || (ppvObject==0) )
892 return E_INVALIDARG;
895 * Initialize the return parameter.
897 *ppvObject = 0;
900 * Compare the riid with the interface IDs implemented by this object.
902 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
904 *ppvObject = iface;
906 else if (memcmp(&IID_IDataObject, riid, sizeof(IID_IDataObject)) == 0)
908 *ppvObject = (IDataObject*)&(this->lpvtbl1);
910 else if ( (memcmp(&IID_IPersistStorage, riid, sizeof(IID_IPersistStorage)) == 0) ||
911 (memcmp(&IID_IPersist, riid, sizeof(IID_IPersist)) == 0) )
913 *ppvObject = (IPersistStorage*)&(this->lpvtbl3);
915 else if ( (memcmp(&IID_IViewObject, riid, sizeof(IID_IViewObject)) == 0) ||
916 (memcmp(&IID_IViewObject2, riid, sizeof(IID_IViewObject2)) == 0) )
918 *ppvObject = (IViewObject2*)&(this->lpvtbl4);
920 else if ( (memcmp(&IID_IOleCache, riid, sizeof(IID_IOleCache)) == 0) ||
921 (memcmp(&IID_IOleCache2, riid, sizeof(IID_IOleCache2)) == 0) )
923 *ppvObject = (IOleCache2*)&(this->lpvtbl5);
925 else if (memcmp(&IID_IOleCacheControl, riid, sizeof(IID_IOleCacheControl)) == 0)
927 *ppvObject = (IOleCacheControl*)&(this->lpvtbl6);
931 * Check that we obtained an interface.
933 if ((*ppvObject)==0)
935 WARN( "() : asking for un supported interface %s\n", debugstr_guid(riid));
936 return E_NOINTERFACE;
940 * Query Interface always increases the reference count by one when it is
941 * successful.
943 IUnknown_AddRef((IUnknown*)*ppvObject);
945 return S_OK;;
948 /************************************************************************
949 * DataCache_NDIUnknown_AddRef (IUnknown)
951 * See Windows documentation for more details on IUnknown methods.
953 * This version of QueryInterface will not delegate it's implementation
954 * to the outer unknown.
956 static ULONG WINAPI DataCache_NDIUnknown_AddRef(
957 IUnknown* iface)
959 _ICOM_THIS_From_NDIUnknown(DataCache, iface);
961 this->ref++;
963 return this->ref;
966 /************************************************************************
967 * DataCache_NDIUnknown_Release (IUnknown)
969 * See Windows documentation for more details on IUnknown methods.
971 * This version of QueryInterface will not delegate it's implementation
972 * to the outer unknown.
974 static ULONG WINAPI DataCache_NDIUnknown_Release(
975 IUnknown* iface)
977 _ICOM_THIS_From_NDIUnknown(DataCache, iface);
980 * Decrease the reference count on this object.
982 this->ref--;
985 * If the reference count goes down to 0, perform suicide.
987 if (this->ref==0)
989 DataCache_Destroy(this);
991 return 0;
994 return this->ref;
997 /*********************************************************
998 * Method implementation for the IDataObject
999 * part of the DataCache class.
1002 /************************************************************************
1003 * DataCache_IDataObject_QueryInterface (IUnknown)
1005 * See Windows documentation for more details on IUnknown methods.
1007 static HRESULT WINAPI DataCache_IDataObject_QueryInterface(
1008 IDataObject* iface,
1009 REFIID riid,
1010 void** ppvObject)
1012 _ICOM_THIS_From_IDataObject(DataCache, iface);
1014 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1017 /************************************************************************
1018 * DataCache_IDataObject_AddRef (IUnknown)
1020 * See Windows documentation for more details on IUnknown methods.
1022 static ULONG WINAPI DataCache_IDataObject_AddRef(
1023 IDataObject* iface)
1025 _ICOM_THIS_From_IDataObject(DataCache, iface);
1027 return IUnknown_AddRef(this->outerUnknown);
1030 /************************************************************************
1031 * DataCache_IDataObject_Release (IUnknown)
1033 * See Windows documentation for more details on IUnknown methods.
1035 static ULONG WINAPI DataCache_IDataObject_Release(
1036 IDataObject* iface)
1038 _ICOM_THIS_From_IDataObject(DataCache, iface);
1040 return IUnknown_Release(this->outerUnknown);
1043 /************************************************************************
1044 * DataCache_GetData
1046 * Get Data from a source dataobject using format pformatetcIn->cfFormat
1047 * See Windows documentation for more details on GetData.
1048 * TODO: Currently only CF_METAFILEPICT is implemented
1050 static HRESULT WINAPI DataCache_GetData(
1051 IDataObject* iface,
1052 LPFORMATETC pformatetcIn,
1053 STGMEDIUM* pmedium)
1055 HRESULT hr = 0;
1056 HRESULT hrRet = E_UNEXPECTED;
1057 IPersistStorage *pPersistStorage = 0;
1058 IStorage *pStorage = 0;
1059 IStream *pStream = 0;
1060 OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
1061 HGLOBAL hGlobalMF = 0;
1062 void *mfBits = 0;
1063 PresentationDataHeader pdh;
1064 METAFILEPICT *mfPict;
1065 HMETAFILE hMetaFile = 0;
1067 if (pformatetcIn->cfFormat == CF_METAFILEPICT)
1069 /* Get the Persist Storage */
1071 hr = IDataObject_QueryInterface(iface, &IID_IPersistStorage, (void**)&pPersistStorage);
1073 if (hr != S_OK)
1074 goto cleanup;
1076 /* Create a doc file to copy the doc to a storage */
1078 hr = StgCreateDocfile(NULL, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &pStorage);
1080 if (hr != S_OK)
1081 goto cleanup;
1083 /* Save it to storage */
1085 hr = OleSave(pPersistStorage, pStorage, FALSE);
1087 if (hr != S_OK)
1088 goto cleanup;
1090 /* Open the Presentation data srteam */
1092 hr = IStorage_OpenStream(pStorage, name, 0, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &pStream);
1094 if (hr != S_OK)
1095 goto cleanup;
1097 /* Read the presentation header */
1099 hr = IStream_Read(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
1101 if (hr != S_OK)
1102 goto cleanup;
1104 mfBits = HeapAlloc(GetProcessHeap(), 0, pdh.dwSize);
1106 /* Read the Metafile bits */
1108 hr = IStream_Read(pStream, mfBits, pdh.dwSize, NULL);
1110 if (hr != S_OK)
1111 goto cleanup;
1113 /* Create the metafile and place it in the STGMEDIUM structure */
1115 hMetaFile = SetMetaFileBitsEx(pdh.dwSize, mfBits);
1117 hGlobalMF = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, sizeof(METAFILEPICT));
1118 mfPict = (METAFILEPICT *)GlobalLock(hGlobalMF);
1119 mfPict->hMF = hMetaFile;
1121 GlobalUnlock(hGlobalMF);
1123 pmedium->u.hGlobal = hGlobalMF;
1124 pmedium->tymed = TYMED_MFPICT;
1125 hrRet = S_OK;
1127 cleanup:
1129 if (mfBits)
1130 HeapFree(GetProcessHeap(), 0, mfBits);
1132 if (pStream)
1133 IStream_Release(pStream);
1135 if (pStorage)
1136 IStorage_Release(pStorage);
1138 if (pPersistStorage)
1139 IPersistStorage_Release(pPersistStorage);
1141 return hrRet;
1144 /* TODO: Other formats are not implemented */
1146 return E_NOTIMPL;
1149 static HRESULT WINAPI DataCache_GetDataHere(
1150 IDataObject* iface,
1151 LPFORMATETC pformatetc,
1152 STGMEDIUM* pmedium)
1154 FIXME("stub\n");
1155 return E_NOTIMPL;
1158 static HRESULT WINAPI DataCache_QueryGetData(
1159 IDataObject* iface,
1160 LPFORMATETC pformatetc)
1162 FIXME("stub\n");
1163 return E_NOTIMPL;
1166 /************************************************************************
1167 * DataCache_EnumFormatEtc (IDataObject)
1169 * The data cache doesn't implement this method.
1171 * See Windows documentation for more details on IDataObject methods.
1173 static HRESULT WINAPI DataCache_GetCanonicalFormatEtc(
1174 IDataObject* iface,
1175 LPFORMATETC pformatectIn,
1176 LPFORMATETC pformatetcOut)
1178 TRACE("()\n");
1179 return E_NOTIMPL;
1182 /************************************************************************
1183 * DataCache_IDataObject_SetData (IDataObject)
1185 * This method is delegated to the IOleCache2 implementation.
1187 * See Windows documentation for more details on IDataObject methods.
1189 static HRESULT WINAPI DataCache_IDataObject_SetData(
1190 IDataObject* iface,
1191 LPFORMATETC pformatetc,
1192 STGMEDIUM* pmedium,
1193 BOOL fRelease)
1195 IOleCache2* oleCache = NULL;
1196 HRESULT hres;
1198 TRACE("(%p, %p, %p, %d)\n", iface, pformatetc, pmedium, fRelease);
1200 hres = IDataObject_QueryInterface(iface, &IID_IOleCache2, (void**)&oleCache);
1202 if (FAILED(hres))
1203 return E_UNEXPECTED;
1205 hres = IOleCache2_SetData(oleCache, pformatetc, pmedium, fRelease);
1207 IOleCache2_Release(oleCache);
1209 return hres;;
1212 /************************************************************************
1213 * DataCache_EnumFormatEtc (IDataObject)
1215 * The data cache doesn't implement this method.
1217 * See Windows documentation for more details on IDataObject methods.
1219 static HRESULT WINAPI DataCache_EnumFormatEtc(
1220 IDataObject* iface,
1221 DWORD dwDirection,
1222 IEnumFORMATETC** ppenumFormatEtc)
1224 TRACE("()\n");
1225 return E_NOTIMPL;
1228 /************************************************************************
1229 * DataCache_DAdvise (IDataObject)
1231 * The data cache doesn't support connections.
1233 * See Windows documentation for more details on IDataObject methods.
1235 static HRESULT WINAPI DataCache_DAdvise(
1236 IDataObject* iface,
1237 FORMATETC* pformatetc,
1238 DWORD advf,
1239 IAdviseSink* pAdvSink,
1240 DWORD* pdwConnection)
1242 TRACE("()\n");
1243 return OLE_E_ADVISENOTSUPPORTED;
1246 /************************************************************************
1247 * DataCache_DUnadvise (IDataObject)
1249 * The data cache doesn't support connections.
1251 * See Windows documentation for more details on IDataObject methods.
1253 static HRESULT WINAPI DataCache_DUnadvise(
1254 IDataObject* iface,
1255 DWORD dwConnection)
1257 TRACE("()\n");
1258 return OLE_E_NOCONNECTION;
1261 /************************************************************************
1262 * DataCache_EnumDAdvise (IDataObject)
1264 * The data cache doesn't support connections.
1266 * See Windows documentation for more details on IDataObject methods.
1268 static HRESULT WINAPI DataCache_EnumDAdvise(
1269 IDataObject* iface,
1270 IEnumSTATDATA** ppenumAdvise)
1272 TRACE("()\n");
1273 return OLE_E_ADVISENOTSUPPORTED;
1276 /*********************************************************
1277 * Method implementation for the IDataObject
1278 * part of the DataCache class.
1281 /************************************************************************
1282 * DataCache_IPersistStorage_QueryInterface (IUnknown)
1284 * See Windows documentation for more details on IUnknown methods.
1286 static HRESULT WINAPI DataCache_IPersistStorage_QueryInterface(
1287 IPersistStorage* iface,
1288 REFIID riid,
1289 void** ppvObject)
1291 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1293 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1296 /************************************************************************
1297 * DataCache_IPersistStorage_AddRef (IUnknown)
1299 * See Windows documentation for more details on IUnknown methods.
1301 static ULONG WINAPI DataCache_IPersistStorage_AddRef(
1302 IPersistStorage* iface)
1304 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1306 return IUnknown_AddRef(this->outerUnknown);
1309 /************************************************************************
1310 * DataCache_IPersistStorage_Release (IUnknown)
1312 * See Windows documentation for more details on IUnknown methods.
1314 static ULONG WINAPI DataCache_IPersistStorage_Release(
1315 IPersistStorage* iface)
1317 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1319 return IUnknown_Release(this->outerUnknown);
1322 /************************************************************************
1323 * DataCache_GetClassID (IPersistStorage)
1325 * The data cache doesn't implement this method.
1327 * See Windows documentation for more details on IPersistStorage methods.
1329 static HRESULT WINAPI DataCache_GetClassID(
1330 IPersistStorage* iface,
1331 CLSID* pClassID)
1333 TRACE("(%p, %p)\n", iface, pClassID);
1334 return E_NOTIMPL;
1337 /************************************************************************
1338 * DataCache_IsDirty (IPersistStorage)
1340 * Until we actully connect to a running object and retrieve new
1341 * information to it, we never get dirty.
1343 * See Windows documentation for more details on IPersistStorage methods.
1345 static HRESULT WINAPI DataCache_IsDirty(
1346 IPersistStorage* iface)
1348 TRACE("(%p)\n", iface);
1350 return S_FALSE;
1353 /************************************************************************
1354 * DataCache_InitNew (IPersistStorage)
1356 * The data cache implementation of IPersistStorage_InitNew simply stores
1357 * the storage pointer.
1359 * See Windows documentation for more details on IPersistStorage methods.
1361 static HRESULT WINAPI DataCache_InitNew(
1362 IPersistStorage* iface,
1363 IStorage* pStg)
1365 TRACE("(%p, %p)\n", iface, pStg);
1367 return DataCache_Load(iface, pStg);
1370 /************************************************************************
1371 * DataCache_Load (IPersistStorage)
1373 * The data cache implementation of IPersistStorage_Load doesn't
1374 * actually load anything. Instead, it holds on to the storage pointer
1375 * and it will load the presentation information when the
1376 * IDataObject_GetData or IViewObject2_Draw methods are called.
1378 * See Windows documentation for more details on IPersistStorage methods.
1380 static HRESULT WINAPI DataCache_Load(
1381 IPersistStorage* iface,
1382 IStorage* pStg)
1384 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1386 TRACE("(%p, %p)\n", iface, pStg);
1388 if (this->presentationStorage != NULL)
1390 IStorage_Release(this->presentationStorage);
1393 this->presentationStorage = pStg;
1395 if (this->presentationStorage != NULL)
1397 IStorage_AddRef(this->presentationStorage);
1399 return S_OK;
1402 /************************************************************************
1403 * DataCache_Save (IPersistStorage)
1405 * Until we actully connect to a running object and retrieve new
1406 * information to it, we never have to save anything. However, it is
1407 * our responsability to copy the information when saving to a new
1408 * storage.
1410 * See Windows documentation for more details on IPersistStorage methods.
1412 static HRESULT WINAPI DataCache_Save(
1413 IPersistStorage* iface,
1414 IStorage* pStg,
1415 BOOL fSameAsLoad)
1417 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1419 TRACE("(%p, %p, %d)\n", iface, pStg, fSameAsLoad);
1421 if ( (!fSameAsLoad) &&
1422 (this->presentationStorage!=NULL) )
1424 return IStorage_CopyTo(this->presentationStorage,
1426 NULL,
1427 NULL,
1428 pStg);
1431 return S_OK;
1434 /************************************************************************
1435 * DataCache_SaveCompleted (IPersistStorage)
1437 * This method is called to tell the cache to release the storage
1438 * pointer it's currentlu holding.
1440 * See Windows documentation for more details on IPersistStorage methods.
1442 static HRESULT WINAPI DataCache_SaveCompleted(
1443 IPersistStorage* iface,
1444 IStorage* pStgNew)
1446 TRACE("(%p, %p)\n", iface, pStgNew);
1448 if (pStgNew)
1451 * First, make sure we get our hands off any storage we have.
1454 DataCache_HandsOffStorage(iface);
1457 * Then, attach to the new storage.
1460 DataCache_Load(iface, pStgNew);
1463 return S_OK;
1466 /************************************************************************
1467 * DataCache_HandsOffStorage (IPersistStorage)
1469 * This method is called to tell the cache to release the storage
1470 * pointer it's currentlu holding.
1472 * See Windows documentation for more details on IPersistStorage methods.
1474 static HRESULT WINAPI DataCache_HandsOffStorage(
1475 IPersistStorage* iface)
1477 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1479 TRACE("(%p)\n", iface);
1481 if (this->presentationStorage != NULL)
1483 IStorage_Release(this->presentationStorage);
1484 this->presentationStorage = NULL;
1487 return S_OK;
1490 /*********************************************************
1491 * Method implementation for the IViewObject2
1492 * part of the DataCache class.
1495 /************************************************************************
1496 * DataCache_IViewObject2_QueryInterface (IUnknown)
1498 * See Windows documentation for more details on IUnknown methods.
1500 static HRESULT WINAPI DataCache_IViewObject2_QueryInterface(
1501 IViewObject2* iface,
1502 REFIID riid,
1503 void** ppvObject)
1505 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1507 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1510 /************************************************************************
1511 * DataCache_IViewObject2_AddRef (IUnknown)
1513 * See Windows documentation for more details on IUnknown methods.
1515 static ULONG WINAPI DataCache_IViewObject2_AddRef(
1516 IViewObject2* iface)
1518 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1520 return IUnknown_AddRef(this->outerUnknown);
1523 /************************************************************************
1524 * DataCache_IViewObject2_Release (IUnknown)
1526 * See Windows documentation for more details on IUnknown methods.
1528 static ULONG WINAPI DataCache_IViewObject2_Release(
1529 IViewObject2* iface)
1531 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1533 return IUnknown_Release(this->outerUnknown);
1536 /************************************************************************
1537 * DataCache_Draw (IViewObject2)
1539 * This method will draw the cached representation of the object
1540 * to the given device context.
1542 * See Windows documentation for more details on IViewObject2 methods.
1544 static HRESULT WINAPI DataCache_Draw(
1545 IViewObject2* iface,
1546 DWORD dwDrawAspect,
1547 LONG lindex,
1548 void* pvAspect,
1549 DVTARGETDEVICE* ptd,
1550 HDC hdcTargetDev,
1551 HDC hdcDraw,
1552 LPCRECTL lprcBounds,
1553 LPCRECTL lprcWBounds,
1554 IVO_ContCallback pfnContinue,
1555 DWORD dwContinue)
1557 PresentationDataHeader presData;
1558 HMETAFILE presMetafile = 0;
1559 HRESULT hres;
1561 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1563 TRACE("(%p, %lx, %ld, %p, %x, %x, %p, %p, %p, %lx)\n",
1564 iface,
1565 dwDrawAspect,
1566 lindex,
1567 pvAspect,
1568 hdcTargetDev,
1569 hdcDraw,
1570 lprcBounds,
1571 lprcWBounds,
1572 pfnContinue,
1573 dwContinue);
1576 * Sanity check
1578 if (lprcBounds==NULL)
1579 return E_INVALIDARG;
1582 * First, we need to retrieve the dimensions of the
1583 * image in the metafile.
1585 hres = DataCache_ReadPresentationData(this,
1586 dwDrawAspect,
1587 &presData);
1589 if (FAILED(hres))
1590 return hres;
1593 * Then, we can extract the metafile itself from the cached
1594 * data.
1596 * FIXME Unless it isn't a metafile. I think it could be any CF_XXX type,
1597 * particularly CF_DIB.
1599 presMetafile = DataCache_ReadPresMetafile(this,
1600 dwDrawAspect);
1603 * If we have a metafile, just draw baby...
1604 * We have to be careful not to modify the state of the
1605 * DC.
1607 if (presMetafile!=0)
1609 INT prevMapMode = SetMapMode(hdcDraw, MM_ANISOTROPIC);
1610 SIZE oldWindowExt;
1611 SIZE oldViewportExt;
1612 POINT oldViewportOrg;
1614 SetWindowExtEx(hdcDraw,
1615 presData.dwObjectExtentX,
1616 presData.dwObjectExtentY,
1617 &oldWindowExt);
1619 SetViewportExtEx(hdcDraw,
1620 lprcBounds->right - lprcBounds->left,
1621 lprcBounds->bottom - lprcBounds->top,
1622 &oldViewportExt);
1624 SetViewportOrgEx(hdcDraw,
1625 lprcBounds->left,
1626 lprcBounds->top,
1627 &oldViewportOrg);
1629 PlayMetaFile(hdcDraw, presMetafile);
1631 SetWindowExtEx(hdcDraw,
1632 oldWindowExt.cx,
1633 oldWindowExt.cy,
1634 NULL);
1636 SetViewportExtEx(hdcDraw,
1637 oldViewportExt.cx,
1638 oldViewportExt.cy,
1639 NULL);
1641 SetViewportOrgEx(hdcDraw,
1642 oldViewportOrg.x,
1643 oldViewportOrg.y,
1644 NULL);
1646 SetMapMode(hdcDraw, prevMapMode);
1648 DeleteMetaFile(presMetafile);
1651 return S_OK;
1654 static HRESULT WINAPI DataCache_GetColorSet(
1655 IViewObject2* iface,
1656 DWORD dwDrawAspect,
1657 LONG lindex,
1658 void* pvAspect,
1659 DVTARGETDEVICE* ptd,
1660 HDC hicTargetDevice,
1661 LOGPALETTE** ppColorSet)
1663 FIXME("stub\n");
1664 return E_NOTIMPL;
1667 static HRESULT WINAPI DataCache_Freeze(
1668 IViewObject2* iface,
1669 DWORD dwDrawAspect,
1670 LONG lindex,
1671 void* pvAspect,
1672 DWORD* pdwFreeze)
1674 FIXME("stub\n");
1675 return E_NOTIMPL;
1678 static HRESULT WINAPI DataCache_Unfreeze(
1679 IViewObject2* iface,
1680 DWORD dwFreeze)
1682 FIXME("stub\n");
1683 return E_NOTIMPL;
1686 /************************************************************************
1687 * DataCache_SetAdvise (IViewObject2)
1689 * This sets-up an advisory sink with the data cache. When the object's
1690 * view changes, this sink is called.
1692 * See Windows documentation for more details on IViewObject2 methods.
1694 static HRESULT WINAPI DataCache_SetAdvise(
1695 IViewObject2* iface,
1696 DWORD aspects,
1697 DWORD advf,
1698 IAdviseSink* pAdvSink)
1700 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1702 TRACE("(%p, %lx, %lx, %p)\n", iface, aspects, advf, pAdvSink);
1705 * A call to this function removes the previous sink
1707 if (this->sinkInterface != NULL)
1709 IAdviseSink_Release(this->sinkInterface);
1710 this->sinkInterface = NULL;
1711 this->sinkAspects = 0;
1712 this->sinkAdviseFlag = 0;
1716 * Now, setup the new one.
1718 if (pAdvSink!=NULL)
1720 this->sinkInterface = pAdvSink;
1721 this->sinkAspects = aspects;
1722 this->sinkAdviseFlag = advf;
1724 IAdviseSink_AddRef(this->sinkInterface);
1728 * When the ADVF_PRIMEFIRST flag is set, we have to advise the
1729 * sink immediately.
1731 if (advf & ADVF_PRIMEFIRST)
1733 DataCache_FireOnViewChange(this,
1734 DVASPECT_CONTENT,
1735 -1);
1738 return S_OK;
1741 /************************************************************************
1742 * DataCache_GetAdvise (IViewObject2)
1744 * This method queries the current state of the advise sink
1745 * installed on the data cache.
1747 * See Windows documentation for more details on IViewObject2 methods.
1749 static HRESULT WINAPI DataCache_GetAdvise(
1750 IViewObject2* iface,
1751 DWORD* pAspects,
1752 DWORD* pAdvf,
1753 IAdviseSink** ppAdvSink)
1755 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1757 TRACE("(%p, %p, %p, %p)\n", iface, pAspects, pAdvf, ppAdvSink);
1760 * Just copy all the requested values.
1762 if (pAspects!=NULL)
1763 *pAspects = this->sinkAspects;
1765 if (pAdvf!=NULL)
1766 *pAdvf = this->sinkAdviseFlag;
1768 if (ppAdvSink!=NULL)
1770 IAdviseSink_QueryInterface(this->sinkInterface,
1771 &IID_IAdviseSink,
1772 (void**)ppAdvSink);
1775 return S_OK;
1778 /************************************************************************
1779 * DataCache_GetExtent (IViewObject2)
1781 * This method retrieves the "natural" size of this cached object.
1783 * See Windows documentation for more details on IViewObject2 methods.
1785 static HRESULT WINAPI DataCache_GetExtent(
1786 IViewObject2* iface,
1787 DWORD dwDrawAspect,
1788 LONG lindex,
1789 DVTARGETDEVICE* ptd,
1790 LPSIZEL lpsizel)
1792 PresentationDataHeader presData;
1793 HRESULT hres = E_FAIL;
1795 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1797 TRACE("(%p, %lx, %ld, %p, %p)\n",
1798 iface, dwDrawAspect, lindex, ptd, lpsizel);
1801 * Sanity check
1803 if (lpsizel==NULL)
1804 return E_POINTER;
1807 * Initialize the out parameter.
1809 lpsizel->cx = 0;
1810 lpsizel->cy = 0;
1813 * This flag should be set to -1.
1815 if (lindex!=-1)
1816 FIXME("Unimplemented flag lindex = %ld\n", lindex);
1819 * Right now, we suport only the callback from
1820 * the default handler.
1822 if (ptd!=NULL)
1823 FIXME("Unimplemented ptd = %p\n", ptd);
1826 * Get the presentation information from the
1827 * cache.
1829 hres = DataCache_ReadPresentationData(this,
1830 dwDrawAspect,
1831 &presData);
1833 if (SUCCEEDED(hres))
1835 lpsizel->cx = presData.dwObjectExtentX;
1836 lpsizel->cy = presData.dwObjectExtentY;
1840 * This method returns OLE_E_BLANK when it fails.
1842 if (FAILED(hres))
1843 hres = OLE_E_BLANK;
1845 return hres;
1849 /*********************************************************
1850 * Method implementation for the IOleCache2
1851 * part of the DataCache class.
1854 /************************************************************************
1855 * DataCache_IOleCache2_QueryInterface (IUnknown)
1857 * See Windows documentation for more details on IUnknown methods.
1859 static HRESULT WINAPI DataCache_IOleCache2_QueryInterface(
1860 IOleCache2* iface,
1861 REFIID riid,
1862 void** ppvObject)
1864 _ICOM_THIS_From_IOleCache2(DataCache, iface);
1866 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1869 /************************************************************************
1870 * DataCache_IOleCache2_AddRef (IUnknown)
1872 * See Windows documentation for more details on IUnknown methods.
1874 static ULONG WINAPI DataCache_IOleCache2_AddRef(
1875 IOleCache2* iface)
1877 _ICOM_THIS_From_IOleCache2(DataCache, iface);
1879 return IUnknown_AddRef(this->outerUnknown);
1882 /************************************************************************
1883 * DataCache_IOleCache2_Release (IUnknown)
1885 * See Windows documentation for more details on IUnknown methods.
1887 static ULONG WINAPI DataCache_IOleCache2_Release(
1888 IOleCache2* iface)
1890 _ICOM_THIS_From_IOleCache2(DataCache, iface);
1892 return IUnknown_Release(this->outerUnknown);
1895 static HRESULT WINAPI DataCache_Cache(
1896 IOleCache2* iface,
1897 FORMATETC* pformatetc,
1898 DWORD advf,
1899 DWORD* pdwConnection)
1901 FIXME("stub\n");
1902 return E_NOTIMPL;
1905 static HRESULT WINAPI DataCache_Uncache(
1906 IOleCache2* iface,
1907 DWORD dwConnection)
1909 FIXME("stub\n");
1910 return E_NOTIMPL;
1913 static HRESULT WINAPI DataCache_EnumCache(
1914 IOleCache2* iface,
1915 IEnumSTATDATA** ppenumSTATDATA)
1917 FIXME("stub\n");
1918 return E_NOTIMPL;
1921 static HRESULT WINAPI DataCache_InitCache(
1922 IOleCache2* iface,
1923 IDataObject* pDataObject)
1925 FIXME("stub\n");
1926 return E_NOTIMPL;
1929 static HRESULT WINAPI DataCache_IOleCache2_SetData(
1930 IOleCache2* iface,
1931 FORMATETC* pformatetc,
1932 STGMEDIUM* pmedium,
1933 BOOL fRelease)
1935 FIXME("stub\n");
1936 return E_NOTIMPL;
1939 static HRESULT WINAPI DataCache_UpdateCache(
1940 IOleCache2* iface,
1941 LPDATAOBJECT pDataObject,
1942 DWORD grfUpdf,
1943 LPVOID pReserved)
1945 FIXME("stub\n");
1946 return E_NOTIMPL;
1949 static HRESULT WINAPI DataCache_DiscardCache(
1950 IOleCache2* iface,
1951 DWORD dwDiscardOptions)
1953 FIXME("stub\n");
1954 return E_NOTIMPL;
1958 /*********************************************************
1959 * Method implementation for the IOleCacheControl
1960 * part of the DataCache class.
1963 /************************************************************************
1964 * DataCache_IOleCacheControl_QueryInterface (IUnknown)
1966 * See Windows documentation for more details on IUnknown methods.
1968 static HRESULT WINAPI DataCache_IOleCacheControl_QueryInterface(
1969 IOleCacheControl* iface,
1970 REFIID riid,
1971 void** ppvObject)
1973 _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
1975 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1978 /************************************************************************
1979 * DataCache_IOleCacheControl_AddRef (IUnknown)
1981 * See Windows documentation for more details on IUnknown methods.
1983 static ULONG WINAPI DataCache_IOleCacheControl_AddRef(
1984 IOleCacheControl* iface)
1986 _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
1988 return IUnknown_AddRef(this->outerUnknown);
1991 /************************************************************************
1992 * DataCache_IOleCacheControl_Release (IUnknown)
1994 * See Windows documentation for more details on IUnknown methods.
1996 static ULONG WINAPI DataCache_IOleCacheControl_Release(
1997 IOleCacheControl* iface)
1999 _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
2001 return IUnknown_Release(this->outerUnknown);
2004 static HRESULT WINAPI DataCache_OnRun(
2005 IOleCacheControl* iface,
2006 LPDATAOBJECT pDataObject)
2008 FIXME("stub\n");
2009 return E_NOTIMPL;
2012 static HRESULT WINAPI DataCache_OnStop(
2013 IOleCacheControl* iface)
2015 FIXME("stub\n");
2016 return E_NOTIMPL;