Define NONAMELESS{STRUCT,UNION} explicitly in the files that need them.
[wine/multimedia.git] / dlls / ole32 / datacache.c
bloba5918d4edfd21788237be250c6f09128d0f90417
1 /*
2 * OLE 2 Data cache
4 * Copyright 1999 Francis Beaudet
5 * Copyright 2000 Abey George
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * NOTES:
22 * The OLE2 data cache supports a whole whack of
23 * interfaces including:
24 * IDataObject, IPersistStorage, IViewObject2,
25 * IOleCache2 and IOleCacheControl.
27 * Most of the implementation details are taken from: Inside OLE
28 * second edition by Kraig Brockschmidt,
30 * NOTES
31 * - This implementation of the datacache will let your application
32 * load documents that have embedded OLE objects in them and it will
33 * also retrieve the metafile representation of those objects.
34 * - This implementation of the datacache will also allow your
35 * application to save new documents with OLE objects in them.
36 * - The main thing that it doesn't do is allow you to activate
37 * or modify the OLE objects in any way.
38 * - I haven't found any good documentation on the real usage of
39 * the streams created by the data cache. In particular, How to
40 * determine what the XXX stands for in the stream name
41 * "\002OlePresXXX". It appears to just be a counter.
42 * - Also, I don't know the real content of the presentation stream
43 * header. I was able to figure-out where the extent of the object
44 * was stored and the aspect, but that's about it.
46 #include <assert.h>
47 #include <string.h>
49 #define NONAMELESSUNION
50 #define NONAMELESSSTRUCT
51 #include "windef.h"
52 #include "winbase.h"
53 #include "wingdi.h"
54 #include "winuser.h"
55 #include "winerror.h"
56 #include "wine/unicode.h"
57 #include "ole2.h"
58 #include "wine/debug.h"
60 WINE_DEFAULT_DEBUG_CHANNEL(ole);
62 /****************************************************************************
63 * PresentationDataHeader
65 * This structure represents the header of the \002OlePresXXX stream in
66 * the OLE object strorage.
68 * Most fields are still unknown.
70 typedef struct PresentationDataHeader
72 DWORD unknown1; /* -1 */
73 DWORD unknown2; /* 3, possibly CF_METAFILEPICT */
74 DWORD unknown3; /* 4, possibly TYMED_ISTREAM */
75 DVASPECT dvAspect;
76 DWORD unknown5; /* -1 */
78 DWORD unknown6;
79 DWORD unknown7; /* 0 */
80 DWORD dwObjectExtentX;
81 DWORD dwObjectExtentY;
82 DWORD dwSize;
83 } PresentationDataHeader;
85 /****************************************************************************
86 * DataCache
88 struct DataCache
91 * List all interface VTables here
93 ICOM_VTABLE(IDataObject)* lpvtbl1;
94 ICOM_VTABLE(IUnknown)* lpvtbl2;
95 ICOM_VTABLE(IPersistStorage)* lpvtbl3;
96 ICOM_VTABLE(IViewObject2)* lpvtbl4;
97 ICOM_VTABLE(IOleCache2)* lpvtbl5;
98 ICOM_VTABLE(IOleCacheControl)* lpvtbl6;
101 * Reference count of this object
103 ULONG ref;
106 * IUnknown implementation of the outer object.
108 IUnknown* outerUnknown;
111 * This storage pointer is set through a call to
112 * IPersistStorage_Load. This is where the visual
113 * representation of the object is stored.
115 IStorage* presentationStorage;
118 * The user of this object can setup ONE advise sink
119 * connection with the object. These parameters describe
120 * that connection.
122 DWORD sinkAspects;
123 DWORD sinkAdviseFlag;
124 IAdviseSink* sinkInterface;
128 typedef struct DataCache DataCache;
131 * Here, I define utility macros to help with the casting of the
132 * "this" parameter.
133 * There is a version to accomodate all of the VTables implemented
134 * by this object.
136 #define _ICOM_THIS_From_IDataObject(class,name) class* this = (class*)name;
137 #define _ICOM_THIS_From_NDIUnknown(class, name) class* this = (class*)(((char*)name)-sizeof(void*));
138 #define _ICOM_THIS_From_IPersistStorage(class, name) class* this = (class*)(((char*)name)-2*sizeof(void*));
139 #define _ICOM_THIS_From_IViewObject2(class, name) class* this = (class*)(((char*)name)-3*sizeof(void*));
140 #define _ICOM_THIS_From_IOleCache2(class, name) class* this = (class*)(((char*)name)-4*sizeof(void*));
141 #define _ICOM_THIS_From_IOleCacheControl(class, name) class* this = (class*)(((char*)name)-5*sizeof(void*));
144 * Prototypes for the methods of the DataCache class.
146 static DataCache* DataCache_Construct(REFCLSID clsid,
147 LPUNKNOWN pUnkOuter);
148 static void DataCache_Destroy(DataCache* ptrToDestroy);
149 static HRESULT DataCache_ReadPresentationData(DataCache* this,
150 DWORD drawAspect,
151 PresentationDataHeader* header);
152 static HRESULT DataCache_OpenPresStream(DataCache *this,
153 DWORD drawAspect,
154 IStream **pStm);
155 static HMETAFILE DataCache_ReadPresMetafile(DataCache* this,
156 DWORD drawAspect);
157 static void DataCache_FireOnViewChange(DataCache* this,
158 DWORD aspect,
159 LONG lindex);
162 * Prototypes for the methods of the DataCache class
163 * that implement non delegating IUnknown methods.
165 static HRESULT WINAPI DataCache_NDIUnknown_QueryInterface(
166 IUnknown* iface,
167 REFIID riid,
168 void** ppvObject);
169 static ULONG WINAPI DataCache_NDIUnknown_AddRef(
170 IUnknown* iface);
171 static ULONG WINAPI DataCache_NDIUnknown_Release(
172 IUnknown* iface);
175 * Prototypes for the methods of the DataCache class
176 * that implement IDataObject methods.
178 static HRESULT WINAPI DataCache_IDataObject_QueryInterface(
179 IDataObject* iface,
180 REFIID riid,
181 void** ppvObject);
182 static ULONG WINAPI DataCache_IDataObject_AddRef(
183 IDataObject* iface);
184 static ULONG WINAPI DataCache_IDataObject_Release(
185 IDataObject* iface);
186 static HRESULT WINAPI DataCache_GetData(
187 IDataObject* iface,
188 LPFORMATETC pformatetcIn,
189 STGMEDIUM* pmedium);
190 static HRESULT WINAPI DataCache_GetDataHere(
191 IDataObject* iface,
192 LPFORMATETC pformatetc,
193 STGMEDIUM* pmedium);
194 static HRESULT WINAPI DataCache_QueryGetData(
195 IDataObject* iface,
196 LPFORMATETC pformatetc);
197 static HRESULT WINAPI DataCache_GetCanonicalFormatEtc(
198 IDataObject* iface,
199 LPFORMATETC pformatectIn,
200 LPFORMATETC pformatetcOut);
201 static HRESULT WINAPI DataCache_IDataObject_SetData(
202 IDataObject* iface,
203 LPFORMATETC pformatetc,
204 STGMEDIUM* pmedium,
205 BOOL fRelease);
206 static HRESULT WINAPI DataCache_EnumFormatEtc(
207 IDataObject* iface,
208 DWORD dwDirection,
209 IEnumFORMATETC** ppenumFormatEtc);
210 static HRESULT WINAPI DataCache_DAdvise(
211 IDataObject* iface,
212 FORMATETC* pformatetc,
213 DWORD advf,
214 IAdviseSink* pAdvSink,
215 DWORD* pdwConnection);
216 static HRESULT WINAPI DataCache_DUnadvise(
217 IDataObject* iface,
218 DWORD dwConnection);
219 static HRESULT WINAPI DataCache_EnumDAdvise(
220 IDataObject* iface,
221 IEnumSTATDATA** ppenumAdvise);
224 * Prototypes for the methods of the DataCache class
225 * that implement IPersistStorage methods.
227 static HRESULT WINAPI DataCache_IPersistStorage_QueryInterface(
228 IPersistStorage* iface,
229 REFIID riid,
230 void** ppvObject);
231 static ULONG WINAPI DataCache_IPersistStorage_AddRef(
232 IPersistStorage* iface);
233 static ULONG WINAPI DataCache_IPersistStorage_Release(
234 IPersistStorage* iface);
235 static HRESULT WINAPI DataCache_GetClassID(
236 IPersistStorage* iface,
237 CLSID* pClassID);
238 static HRESULT WINAPI DataCache_IsDirty(
239 IPersistStorage* iface);
240 static HRESULT WINAPI DataCache_InitNew(
241 IPersistStorage* iface,
242 IStorage* pStg);
243 static HRESULT WINAPI DataCache_Load(
244 IPersistStorage* iface,
245 IStorage* pStg);
246 static HRESULT WINAPI DataCache_Save(
247 IPersistStorage* iface,
248 IStorage* pStg,
249 BOOL fSameAsLoad);
250 static HRESULT WINAPI DataCache_SaveCompleted(
251 IPersistStorage* iface,
252 IStorage* pStgNew);
253 static HRESULT WINAPI DataCache_HandsOffStorage(
254 IPersistStorage* iface);
257 * Prototypes for the methods of the DataCache class
258 * that implement IViewObject2 methods.
260 static HRESULT WINAPI DataCache_IViewObject2_QueryInterface(
261 IViewObject2* iface,
262 REFIID riid,
263 void** ppvObject);
264 static ULONG WINAPI DataCache_IViewObject2_AddRef(
265 IViewObject2* iface);
266 static ULONG WINAPI DataCache_IViewObject2_Release(
267 IViewObject2* iface);
268 static HRESULT WINAPI DataCache_Draw(
269 IViewObject2* iface,
270 DWORD dwDrawAspect,
271 LONG lindex,
272 void* pvAspect,
273 DVTARGETDEVICE* ptd,
274 HDC hdcTargetDev,
275 HDC hdcDraw,
276 LPCRECTL lprcBounds,
277 LPCRECTL lprcWBounds,
278 IVO_ContCallback pfnContinue,
279 DWORD dwContinue);
280 static HRESULT WINAPI DataCache_GetColorSet(
281 IViewObject2* iface,
282 DWORD dwDrawAspect,
283 LONG lindex,
284 void* pvAspect,
285 DVTARGETDEVICE* ptd,
286 HDC hicTargetDevice,
287 LOGPALETTE** ppColorSet);
288 static HRESULT WINAPI DataCache_Freeze(
289 IViewObject2* iface,
290 DWORD dwDrawAspect,
291 LONG lindex,
292 void* pvAspect,
293 DWORD* pdwFreeze);
294 static HRESULT WINAPI DataCache_Unfreeze(
295 IViewObject2* iface,
296 DWORD dwFreeze);
297 static HRESULT WINAPI DataCache_SetAdvise(
298 IViewObject2* iface,
299 DWORD aspects,
300 DWORD advf,
301 IAdviseSink* pAdvSink);
302 static HRESULT WINAPI DataCache_GetAdvise(
303 IViewObject2* iface,
304 DWORD* pAspects,
305 DWORD* pAdvf,
306 IAdviseSink** ppAdvSink);
307 static HRESULT WINAPI DataCache_GetExtent(
308 IViewObject2* iface,
309 DWORD dwDrawAspect,
310 LONG lindex,
311 DVTARGETDEVICE* ptd,
312 LPSIZEL lpsizel);
315 * Prototypes for the methods of the DataCache class
316 * that implement IOleCache2 methods.
318 static HRESULT WINAPI DataCache_IOleCache2_QueryInterface(
319 IOleCache2* iface,
320 REFIID riid,
321 void** ppvObject);
322 static ULONG WINAPI DataCache_IOleCache2_AddRef(
323 IOleCache2* iface);
324 static ULONG WINAPI DataCache_IOleCache2_Release(
325 IOleCache2* iface);
326 static HRESULT WINAPI DataCache_Cache(
327 IOleCache2* iface,
328 FORMATETC* pformatetc,
329 DWORD advf,
330 DWORD* pdwConnection);
331 static HRESULT WINAPI DataCache_Uncache(
332 IOleCache2* iface,
333 DWORD dwConnection);
334 static HRESULT WINAPI DataCache_EnumCache(
335 IOleCache2* iface,
336 IEnumSTATDATA** ppenumSTATDATA);
337 static HRESULT WINAPI DataCache_InitCache(
338 IOleCache2* iface,
339 IDataObject* pDataObject);
340 static HRESULT WINAPI DataCache_IOleCache2_SetData(
341 IOleCache2* iface,
342 FORMATETC* pformatetc,
343 STGMEDIUM* pmedium,
344 BOOL fRelease);
345 static HRESULT WINAPI DataCache_UpdateCache(
346 IOleCache2* iface,
347 LPDATAOBJECT pDataObject,
348 DWORD grfUpdf,
349 LPVOID pReserved);
350 static HRESULT WINAPI DataCache_DiscardCache(
351 IOleCache2* iface,
352 DWORD dwDiscardOptions);
355 * Prototypes for the methods of the DataCache class
356 * that implement IOleCacheControl methods.
358 static HRESULT WINAPI DataCache_IOleCacheControl_QueryInterface(
359 IOleCacheControl* iface,
360 REFIID riid,
361 void** ppvObject);
362 static ULONG WINAPI DataCache_IOleCacheControl_AddRef(
363 IOleCacheControl* iface);
364 static ULONG WINAPI DataCache_IOleCacheControl_Release(
365 IOleCacheControl* iface);
366 static HRESULT WINAPI DataCache_OnRun(
367 IOleCacheControl* iface,
368 LPDATAOBJECT pDataObject);
369 static HRESULT WINAPI DataCache_OnStop(
370 IOleCacheControl* iface);
373 * Virtual function tables for the DataCache class.
375 static ICOM_VTABLE(IUnknown) DataCache_NDIUnknown_VTable =
377 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
378 DataCache_NDIUnknown_QueryInterface,
379 DataCache_NDIUnknown_AddRef,
380 DataCache_NDIUnknown_Release
383 static ICOM_VTABLE(IDataObject) DataCache_IDataObject_VTable =
385 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
386 DataCache_IDataObject_QueryInterface,
387 DataCache_IDataObject_AddRef,
388 DataCache_IDataObject_Release,
389 DataCache_GetData,
390 DataCache_GetDataHere,
391 DataCache_QueryGetData,
392 DataCache_GetCanonicalFormatEtc,
393 DataCache_IDataObject_SetData,
394 DataCache_EnumFormatEtc,
395 DataCache_DAdvise,
396 DataCache_DUnadvise,
397 DataCache_EnumDAdvise
400 static ICOM_VTABLE(IPersistStorage) DataCache_IPersistStorage_VTable =
402 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
403 DataCache_IPersistStorage_QueryInterface,
404 DataCache_IPersistStorage_AddRef,
405 DataCache_IPersistStorage_Release,
406 DataCache_GetClassID,
407 DataCache_IsDirty,
408 DataCache_InitNew,
409 DataCache_Load,
410 DataCache_Save,
411 DataCache_SaveCompleted,
412 DataCache_HandsOffStorage
415 static ICOM_VTABLE(IViewObject2) DataCache_IViewObject2_VTable =
417 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
418 DataCache_IViewObject2_QueryInterface,
419 DataCache_IViewObject2_AddRef,
420 DataCache_IViewObject2_Release,
421 DataCache_Draw,
422 DataCache_GetColorSet,
423 DataCache_Freeze,
424 DataCache_Unfreeze,
425 DataCache_SetAdvise,
426 DataCache_GetAdvise,
427 DataCache_GetExtent
430 static ICOM_VTABLE(IOleCache2) DataCache_IOleCache2_VTable =
432 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
433 DataCache_IOleCache2_QueryInterface,
434 DataCache_IOleCache2_AddRef,
435 DataCache_IOleCache2_Release,
436 DataCache_Cache,
437 DataCache_Uncache,
438 DataCache_EnumCache,
439 DataCache_InitCache,
440 DataCache_IOleCache2_SetData,
441 DataCache_UpdateCache,
442 DataCache_DiscardCache
445 static ICOM_VTABLE(IOleCacheControl) DataCache_IOleCacheControl_VTable =
447 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
448 DataCache_IOleCacheControl_QueryInterface,
449 DataCache_IOleCacheControl_AddRef,
450 DataCache_IOleCacheControl_Release,
451 DataCache_OnRun,
452 DataCache_OnStop
455 /******************************************************************************
456 * CreateDataCache [OLE32.54]
458 HRESULT WINAPI CreateDataCache(
459 LPUNKNOWN pUnkOuter,
460 REFCLSID rclsid,
461 REFIID riid,
462 LPVOID* ppvObj)
464 DataCache* newCache = NULL;
465 HRESULT hr = S_OK;
467 TRACE("(%s, %p, %s, %p)\n", debugstr_guid(rclsid), pUnkOuter, debugstr_guid(riid), ppvObj);
470 * Sanity check
472 if (ppvObj==0)
473 return E_POINTER;
475 *ppvObj = 0;
478 * If this cache is constructed for aggregation, make sure
479 * the caller is requesting the IUnknown interface.
480 * This is necessary because it's the only time the non-delegating
481 * IUnknown pointer can be returned to the outside.
483 if ( (pUnkOuter!=NULL) &&
484 (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) != 0) )
485 return CLASS_E_NOAGGREGATION;
488 * Try to construct a new instance of the class.
490 newCache = DataCache_Construct(rclsid,
491 pUnkOuter);
493 if (newCache == 0)
494 return E_OUTOFMEMORY;
497 * Make sure it supports the interface required by the caller.
499 hr = IUnknown_QueryInterface((IUnknown*)&(newCache->lpvtbl2), riid, ppvObj);
502 * Release the reference obtained in the constructor. If
503 * the QueryInterface was unsuccessful, it will free the class.
505 IUnknown_Release((IUnknown*)&(newCache->lpvtbl2));
507 return hr;
510 /*********************************************************
511 * Method implementation for DataCache class.
513 static DataCache* DataCache_Construct(
514 REFCLSID clsid,
515 LPUNKNOWN pUnkOuter)
517 DataCache* newObject = 0;
520 * Allocate space for the object.
522 newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(DataCache));
524 if (newObject==0)
525 return newObject;
528 * Initialize the virtual function table.
530 newObject->lpvtbl1 = &DataCache_IDataObject_VTable;
531 newObject->lpvtbl2 = &DataCache_NDIUnknown_VTable;
532 newObject->lpvtbl3 = &DataCache_IPersistStorage_VTable;
533 newObject->lpvtbl4 = &DataCache_IViewObject2_VTable;
534 newObject->lpvtbl5 = &DataCache_IOleCache2_VTable;
535 newObject->lpvtbl6 = &DataCache_IOleCacheControl_VTable;
538 * Start with one reference count. The caller of this function
539 * must release the interface pointer when it is done.
541 newObject->ref = 1;
544 * Initialize the outer unknown
545 * We don't keep a reference on the outer unknown since, the way
546 * aggregation works, our lifetime is at least as large as it's
547 * lifetime.
549 if (pUnkOuter==NULL)
550 pUnkOuter = (IUnknown*)&(newObject->lpvtbl2);
552 newObject->outerUnknown = pUnkOuter;
555 * Initialize the other members of the structure.
557 newObject->presentationStorage = NULL;
558 newObject->sinkAspects = 0;
559 newObject->sinkAdviseFlag = 0;
560 newObject->sinkInterface = 0;
562 return newObject;
565 static void DataCache_Destroy(
566 DataCache* ptrToDestroy)
568 TRACE("()\n");
570 if (ptrToDestroy->sinkInterface != NULL)
572 IAdviseSink_Release(ptrToDestroy->sinkInterface);
573 ptrToDestroy->sinkInterface = NULL;
576 if (ptrToDestroy->presentationStorage != NULL)
578 IStorage_Release(ptrToDestroy->presentationStorage);
579 ptrToDestroy->presentationStorage = NULL;
583 * Free the datacache pointer.
585 HeapFree(GetProcessHeap(), 0, ptrToDestroy);
588 /************************************************************************
589 * DataCache_ReadPresentationData
591 * This method will read information for the requested presentation
592 * into the given structure.
594 * Param:
595 * this - Pointer to the DataCache object
596 * drawAspect - The aspect of the object that we wish to draw.
597 * header - The structure containing information about this
598 * aspect of the object.
600 static HRESULT DataCache_ReadPresentationData(
601 DataCache* this,
602 DWORD drawAspect,
603 PresentationDataHeader* header)
605 IStream* presStream = NULL;
606 HRESULT hres;
609 * Open the presentation stream.
611 hres = DataCache_OpenPresStream(
612 this,
613 drawAspect,
614 &presStream);
616 if (FAILED(hres))
617 return hres;
620 * Read the header.
623 hres = IStream_Read(
624 presStream,
625 header,
626 sizeof(PresentationDataHeader),
627 NULL);
630 * Cleanup.
632 IStream_Release(presStream);
635 * We don't want to propagate any other error
636 * code than a failure.
638 if (hres!=S_OK)
639 hres = E_FAIL;
641 return hres;
644 /************************************************************************
645 * DataCache_FireOnViewChange
647 * This method will fire an OnViewChange notification to the advise
648 * sink registered with the datacache.
650 * See IAdviseSink::OnViewChange for more details.
652 static void DataCache_FireOnViewChange(
653 DataCache* this,
654 DWORD aspect,
655 LONG lindex)
657 TRACE("(%p, %lx, %ld)\n", this, aspect, lindex);
660 * The sink supplies a filter when it registers
661 * we make sure we only send the notifications when that
662 * filter matches.
664 if ((this->sinkAspects & aspect) != 0)
666 if (this->sinkInterface != NULL)
668 IAdviseSink_OnViewChange(this->sinkInterface,
669 aspect,
670 lindex);
673 * Some sinks want to be unregistered automatically when
674 * the first notification goes out.
676 if ( (this->sinkAdviseFlag & ADVF_ONLYONCE) != 0)
678 IAdviseSink_Release(this->sinkInterface);
680 this->sinkInterface = NULL;
681 this->sinkAspects = 0;
682 this->sinkAdviseFlag = 0;
688 /* Helper for DataCache_OpenPresStream */
689 static BOOL DataCache_IsPresentationStream(const STATSTG *elem)
691 /* The presentation streams have names of the form "\002OlePresXXX",
692 * where XXX goes from 000 to 999. */
693 static const WCHAR OlePres[] = { 2,'O','l','e','P','r','e','s' };
695 LPCWSTR name = elem->pwcsName;
697 return (elem->type == STGTY_STREAM)
698 && (elem->cbSize.s.LowPart >= sizeof(PresentationDataHeader))
699 && (strlenW(name) == 11)
700 && (strncmpW(name, OlePres, 8) == 0)
701 && (name[8] >= '0') && (name[8] <= '9')
702 && (name[9] >= '0') && (name[9] <= '9')
703 && (name[10] >= '0') && (name[10] <= '9');
706 /************************************************************************
707 * DataCache_OpenPresStream
709 * This method will find the stream for the given presentation. It makes
710 * no attempt at fallback.
712 * Param:
713 * this - Pointer to the DataCache object
714 * drawAspect - The aspect of the object that we wish to draw.
715 * pStm - A returned stream. It points to the beginning of the
716 * - presentation data, including the header.
718 * Errors:
719 * S_OK The requested stream has been opened.
720 * OLE_E_BLANK The requested stream could not be found.
721 * Quite a few others I'm too lazy to map correctly.
723 * Notes:
724 * Algorithm: Scan the elements of the presentation storage, looking
725 * for presentation streams. For each presentation stream,
726 * load the header and check to see if the aspect maches.
728 * If a fallback is desired, just opening the first presentation stream
729 * is a possibility.
731 static HRESULT DataCache_OpenPresStream(
732 DataCache *this,
733 DWORD drawAspect,
734 IStream **ppStm)
736 STATSTG elem;
737 IEnumSTATSTG *pEnum;
738 HRESULT hr;
740 if (!ppStm) return E_POINTER;
742 hr = IStorage_EnumElements(this->presentationStorage, 0, NULL, 0, &pEnum);
743 if (FAILED(hr)) return hr;
745 while ((hr = IEnumSTATSTG_Next(pEnum, 1, &elem, NULL)) == S_OK)
747 if (DataCache_IsPresentationStream(&elem))
749 IStream *pStm;
751 hr = IStorage_OpenStream(this->presentationStorage, elem.pwcsName,
752 NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0,
753 &pStm);
754 if (SUCCEEDED(hr))
756 PresentationDataHeader header;
757 ULONG actual_read;
759 hr = IStream_Read(pStm, &header, sizeof(header), &actual_read);
761 /* can't use SUCCEEDED(hr): S_FALSE counts as an error */
762 if (hr == S_OK && actual_read == sizeof(header)
763 && header.dvAspect == drawAspect)
765 /* Rewind the stream before returning it. */
766 LARGE_INTEGER offset;
767 offset.s.LowPart = 0;
768 offset.s.HighPart = 0;
769 IStream_Seek(pStm, offset, STREAM_SEEK_SET, NULL);
771 *ppStm = pStm;
773 CoTaskMemFree(elem.pwcsName);
774 IEnumSTATSTG_Release(pEnum);
776 return S_OK;
779 IStream_Release(pStm);
783 CoTaskMemFree(elem.pwcsName);
786 IEnumSTATSTG_Release(pEnum);
788 return (hr == S_FALSE ? OLE_E_BLANK : hr);
791 /************************************************************************
792 * DataCache_ReadPresentationData
794 * This method will read information for the requested presentation
795 * into the given structure.
797 * Param:
798 * this - Pointer to the DataCache object
799 * drawAspect - The aspect of the object that we wish to draw.
801 * Returns:
802 * This method returns a metafile handle if it is successful.
803 * it will return 0 if not.
805 static HMETAFILE DataCache_ReadPresMetafile(
806 DataCache* this,
807 DWORD drawAspect)
809 LARGE_INTEGER offset;
810 IStream* presStream = NULL;
811 HRESULT hres;
812 void* metafileBits;
813 STATSTG streamInfo;
814 HMETAFILE newMetafile = 0;
817 * Open the presentation stream.
819 hres = DataCache_OpenPresStream(
820 this,
821 drawAspect,
822 &presStream);
824 if (FAILED(hres))
825 return (HMETAFILE)hres;
828 * Get the size of the stream.
830 hres = IStream_Stat(presStream,
831 &streamInfo,
832 STATFLAG_NONAME);
835 * Skip the header
837 offset.s.HighPart = 0;
838 offset.s.LowPart = sizeof(PresentationDataHeader);
840 hres = IStream_Seek(
841 presStream,
842 offset,
843 STREAM_SEEK_SET,
844 NULL);
846 streamInfo.cbSize.s.LowPart -= offset.s.LowPart;
849 * Allocate a buffer for the metafile bits.
851 metafileBits = HeapAlloc(GetProcessHeap(),
853 streamInfo.cbSize.s.LowPart);
856 * Read the metafile bits.
858 hres = IStream_Read(
859 presStream,
860 metafileBits,
861 streamInfo.cbSize.s.LowPart,
862 NULL);
865 * Create a metafile with those bits.
867 if (SUCCEEDED(hres))
869 newMetafile = SetMetaFileBitsEx(streamInfo.cbSize.s.LowPart, metafileBits);
873 * Cleanup.
875 HeapFree(GetProcessHeap(), 0, metafileBits);
876 IStream_Release(presStream);
878 if (newMetafile==0)
879 hres = E_FAIL;
881 return newMetafile;
884 /*********************************************************
885 * Method implementation for the non delegating IUnknown
886 * part of the DataCache class.
889 /************************************************************************
890 * DataCache_NDIUnknown_QueryInterface (IUnknown)
892 * See Windows documentation for more details on IUnknown methods.
894 * This version of QueryInterface will not delegate it's implementation
895 * to the outer unknown.
897 static HRESULT WINAPI DataCache_NDIUnknown_QueryInterface(
898 IUnknown* iface,
899 REFIID riid,
900 void** ppvObject)
902 _ICOM_THIS_From_NDIUnknown(DataCache, iface);
905 * Perform a sanity check on the parameters.
907 if ( (this==0) || (ppvObject==0) )
908 return E_INVALIDARG;
911 * Initialize the return parameter.
913 *ppvObject = 0;
916 * Compare the riid with the interface IDs implemented by this object.
918 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
920 *ppvObject = iface;
922 else if (memcmp(&IID_IDataObject, riid, sizeof(IID_IDataObject)) == 0)
924 *ppvObject = (IDataObject*)&(this->lpvtbl1);
926 else if ( (memcmp(&IID_IPersistStorage, riid, sizeof(IID_IPersistStorage)) == 0) ||
927 (memcmp(&IID_IPersist, riid, sizeof(IID_IPersist)) == 0) )
929 *ppvObject = (IPersistStorage*)&(this->lpvtbl3);
931 else if ( (memcmp(&IID_IViewObject, riid, sizeof(IID_IViewObject)) == 0) ||
932 (memcmp(&IID_IViewObject2, riid, sizeof(IID_IViewObject2)) == 0) )
934 *ppvObject = (IViewObject2*)&(this->lpvtbl4);
936 else if ( (memcmp(&IID_IOleCache, riid, sizeof(IID_IOleCache)) == 0) ||
937 (memcmp(&IID_IOleCache2, riid, sizeof(IID_IOleCache2)) == 0) )
939 *ppvObject = (IOleCache2*)&(this->lpvtbl5);
941 else if (memcmp(&IID_IOleCacheControl, riid, sizeof(IID_IOleCacheControl)) == 0)
943 *ppvObject = (IOleCacheControl*)&(this->lpvtbl6);
947 * Check that we obtained an interface.
949 if ((*ppvObject)==0)
951 WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid));
952 return E_NOINTERFACE;
956 * Query Interface always increases the reference count by one when it is
957 * successful.
959 IUnknown_AddRef((IUnknown*)*ppvObject);
961 return S_OK;
964 /************************************************************************
965 * DataCache_NDIUnknown_AddRef (IUnknown)
967 * See Windows documentation for more details on IUnknown methods.
969 * This version of QueryInterface will not delegate it's implementation
970 * to the outer unknown.
972 static ULONG WINAPI DataCache_NDIUnknown_AddRef(
973 IUnknown* iface)
975 _ICOM_THIS_From_NDIUnknown(DataCache, iface);
977 this->ref++;
979 return this->ref;
982 /************************************************************************
983 * DataCache_NDIUnknown_Release (IUnknown)
985 * See Windows documentation for more details on IUnknown methods.
987 * This version of QueryInterface will not delegate it's implementation
988 * to the outer unknown.
990 static ULONG WINAPI DataCache_NDIUnknown_Release(
991 IUnknown* iface)
993 _ICOM_THIS_From_NDIUnknown(DataCache, iface);
996 * Decrease the reference count on this object.
998 this->ref--;
1001 * If the reference count goes down to 0, perform suicide.
1003 if (this->ref==0)
1005 DataCache_Destroy(this);
1007 return 0;
1010 return this->ref;
1013 /*********************************************************
1014 * Method implementation for the IDataObject
1015 * part of the DataCache class.
1018 /************************************************************************
1019 * DataCache_IDataObject_QueryInterface (IUnknown)
1021 * See Windows documentation for more details on IUnknown methods.
1023 static HRESULT WINAPI DataCache_IDataObject_QueryInterface(
1024 IDataObject* iface,
1025 REFIID riid,
1026 void** ppvObject)
1028 _ICOM_THIS_From_IDataObject(DataCache, iface);
1030 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1033 /************************************************************************
1034 * DataCache_IDataObject_AddRef (IUnknown)
1036 * See Windows documentation for more details on IUnknown methods.
1038 static ULONG WINAPI DataCache_IDataObject_AddRef(
1039 IDataObject* iface)
1041 _ICOM_THIS_From_IDataObject(DataCache, iface);
1043 return IUnknown_AddRef(this->outerUnknown);
1046 /************************************************************************
1047 * DataCache_IDataObject_Release (IUnknown)
1049 * See Windows documentation for more details on IUnknown methods.
1051 static ULONG WINAPI DataCache_IDataObject_Release(
1052 IDataObject* iface)
1054 _ICOM_THIS_From_IDataObject(DataCache, iface);
1056 return IUnknown_Release(this->outerUnknown);
1059 /************************************************************************
1060 * DataCache_GetData
1062 * Get Data from a source dataobject using format pformatetcIn->cfFormat
1063 * See Windows documentation for more details on GetData.
1064 * TODO: Currently only CF_METAFILEPICT is implemented
1066 static HRESULT WINAPI DataCache_GetData(
1067 IDataObject* iface,
1068 LPFORMATETC pformatetcIn,
1069 STGMEDIUM* pmedium)
1071 HRESULT hr = 0;
1072 HRESULT hrRet = E_UNEXPECTED;
1073 IPersistStorage *pPersistStorage = 0;
1074 IStorage *pStorage = 0;
1075 IStream *pStream = 0;
1076 OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
1077 HGLOBAL hGlobalMF = 0;
1078 void *mfBits = 0;
1079 PresentationDataHeader pdh;
1080 METAFILEPICT *mfPict;
1081 HMETAFILE hMetaFile = 0;
1083 if (pformatetcIn->cfFormat == CF_METAFILEPICT)
1085 /* Get the Persist Storage */
1087 hr = IDataObject_QueryInterface(iface, &IID_IPersistStorage, (void**)&pPersistStorage);
1089 if (hr != S_OK)
1090 goto cleanup;
1092 /* Create a doc file to copy the doc to a storage */
1094 hr = StgCreateDocfile(NULL, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &pStorage);
1096 if (hr != S_OK)
1097 goto cleanup;
1099 /* Save it to storage */
1101 hr = OleSave(pPersistStorage, pStorage, FALSE);
1103 if (hr != S_OK)
1104 goto cleanup;
1106 /* Open the Presentation data srteam */
1108 hr = IStorage_OpenStream(pStorage, name, 0, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &pStream);
1110 if (hr != S_OK)
1111 goto cleanup;
1113 /* Read the presentation header */
1115 hr = IStream_Read(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
1117 if (hr != S_OK)
1118 goto cleanup;
1120 mfBits = HeapAlloc(GetProcessHeap(), 0, pdh.dwSize);
1122 /* Read the Metafile bits */
1124 hr = IStream_Read(pStream, mfBits, pdh.dwSize, NULL);
1126 if (hr != S_OK)
1127 goto cleanup;
1129 /* Create the metafile and place it in the STGMEDIUM structure */
1131 hMetaFile = SetMetaFileBitsEx(pdh.dwSize, mfBits);
1133 hGlobalMF = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, sizeof(METAFILEPICT));
1134 mfPict = (METAFILEPICT *)GlobalLock(hGlobalMF);
1135 mfPict->hMF = hMetaFile;
1137 GlobalUnlock(hGlobalMF);
1139 pmedium->u.hGlobal = hGlobalMF;
1140 pmedium->tymed = TYMED_MFPICT;
1141 hrRet = S_OK;
1143 cleanup:
1145 if (mfBits)
1146 HeapFree(GetProcessHeap(), 0, mfBits);
1148 if (pStream)
1149 IStream_Release(pStream);
1151 if (pStorage)
1152 IStorage_Release(pStorage);
1154 if (pPersistStorage)
1155 IPersistStorage_Release(pPersistStorage);
1157 return hrRet;
1160 /* TODO: Other formats are not implemented */
1162 return E_NOTIMPL;
1165 static HRESULT WINAPI DataCache_GetDataHere(
1166 IDataObject* iface,
1167 LPFORMATETC pformatetc,
1168 STGMEDIUM* pmedium)
1170 FIXME("stub\n");
1171 return E_NOTIMPL;
1174 static HRESULT WINAPI DataCache_QueryGetData(
1175 IDataObject* iface,
1176 LPFORMATETC pformatetc)
1178 FIXME("stub\n");
1179 return E_NOTIMPL;
1182 /************************************************************************
1183 * DataCache_EnumFormatEtc (IDataObject)
1185 * The data cache doesn't implement this method.
1187 * See Windows documentation for more details on IDataObject methods.
1189 static HRESULT WINAPI DataCache_GetCanonicalFormatEtc(
1190 IDataObject* iface,
1191 LPFORMATETC pformatectIn,
1192 LPFORMATETC pformatetcOut)
1194 TRACE("()\n");
1195 return E_NOTIMPL;
1198 /************************************************************************
1199 * DataCache_IDataObject_SetData (IDataObject)
1201 * This method is delegated to the IOleCache2 implementation.
1203 * See Windows documentation for more details on IDataObject methods.
1205 static HRESULT WINAPI DataCache_IDataObject_SetData(
1206 IDataObject* iface,
1207 LPFORMATETC pformatetc,
1208 STGMEDIUM* pmedium,
1209 BOOL fRelease)
1211 IOleCache2* oleCache = NULL;
1212 HRESULT hres;
1214 TRACE("(%p, %p, %p, %d)\n", iface, pformatetc, pmedium, fRelease);
1216 hres = IDataObject_QueryInterface(iface, &IID_IOleCache2, (void**)&oleCache);
1218 if (FAILED(hres))
1219 return E_UNEXPECTED;
1221 hres = IOleCache2_SetData(oleCache, pformatetc, pmedium, fRelease);
1223 IOleCache2_Release(oleCache);
1225 return hres;
1228 /************************************************************************
1229 * DataCache_EnumFormatEtc (IDataObject)
1231 * The data cache doesn't implement this method.
1233 * See Windows documentation for more details on IDataObject methods.
1235 static HRESULT WINAPI DataCache_EnumFormatEtc(
1236 IDataObject* iface,
1237 DWORD dwDirection,
1238 IEnumFORMATETC** ppenumFormatEtc)
1240 TRACE("()\n");
1241 return E_NOTIMPL;
1244 /************************************************************************
1245 * DataCache_DAdvise (IDataObject)
1247 * The data cache doesn't support connections.
1249 * See Windows documentation for more details on IDataObject methods.
1251 static HRESULT WINAPI DataCache_DAdvise(
1252 IDataObject* iface,
1253 FORMATETC* pformatetc,
1254 DWORD advf,
1255 IAdviseSink* pAdvSink,
1256 DWORD* pdwConnection)
1258 TRACE("()\n");
1259 return OLE_E_ADVISENOTSUPPORTED;
1262 /************************************************************************
1263 * DataCache_DUnadvise (IDataObject)
1265 * The data cache doesn't support connections.
1267 * See Windows documentation for more details on IDataObject methods.
1269 static HRESULT WINAPI DataCache_DUnadvise(
1270 IDataObject* iface,
1271 DWORD dwConnection)
1273 TRACE("()\n");
1274 return OLE_E_NOCONNECTION;
1277 /************************************************************************
1278 * DataCache_EnumDAdvise (IDataObject)
1280 * The data cache doesn't support connections.
1282 * See Windows documentation for more details on IDataObject methods.
1284 static HRESULT WINAPI DataCache_EnumDAdvise(
1285 IDataObject* iface,
1286 IEnumSTATDATA** ppenumAdvise)
1288 TRACE("()\n");
1289 return OLE_E_ADVISENOTSUPPORTED;
1292 /*********************************************************
1293 * Method implementation for the IDataObject
1294 * part of the DataCache class.
1297 /************************************************************************
1298 * DataCache_IPersistStorage_QueryInterface (IUnknown)
1300 * See Windows documentation for more details on IUnknown methods.
1302 static HRESULT WINAPI DataCache_IPersistStorage_QueryInterface(
1303 IPersistStorage* iface,
1304 REFIID riid,
1305 void** ppvObject)
1307 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1309 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1312 /************************************************************************
1313 * DataCache_IPersistStorage_AddRef (IUnknown)
1315 * See Windows documentation for more details on IUnknown methods.
1317 static ULONG WINAPI DataCache_IPersistStorage_AddRef(
1318 IPersistStorage* iface)
1320 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1322 return IUnknown_AddRef(this->outerUnknown);
1325 /************************************************************************
1326 * DataCache_IPersistStorage_Release (IUnknown)
1328 * See Windows documentation for more details on IUnknown methods.
1330 static ULONG WINAPI DataCache_IPersistStorage_Release(
1331 IPersistStorage* iface)
1333 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1335 return IUnknown_Release(this->outerUnknown);
1338 /************************************************************************
1339 * DataCache_GetClassID (IPersistStorage)
1341 * The data cache doesn't implement this method.
1343 * See Windows documentation for more details on IPersistStorage methods.
1345 static HRESULT WINAPI DataCache_GetClassID(
1346 IPersistStorage* iface,
1347 CLSID* pClassID)
1349 TRACE("(%p, %p)\n", iface, pClassID);
1350 return E_NOTIMPL;
1353 /************************************************************************
1354 * DataCache_IsDirty (IPersistStorage)
1356 * Until we actully connect to a running object and retrieve new
1357 * information to it, we never get dirty.
1359 * See Windows documentation for more details on IPersistStorage methods.
1361 static HRESULT WINAPI DataCache_IsDirty(
1362 IPersistStorage* iface)
1364 TRACE("(%p)\n", iface);
1366 return S_FALSE;
1369 /************************************************************************
1370 * DataCache_InitNew (IPersistStorage)
1372 * The data cache implementation of IPersistStorage_InitNew simply stores
1373 * the storage pointer.
1375 * See Windows documentation for more details on IPersistStorage methods.
1377 static HRESULT WINAPI DataCache_InitNew(
1378 IPersistStorage* iface,
1379 IStorage* pStg)
1381 TRACE("(%p, %p)\n", iface, pStg);
1383 return DataCache_Load(iface, pStg);
1386 /************************************************************************
1387 * DataCache_Load (IPersistStorage)
1389 * The data cache implementation of IPersistStorage_Load doesn't
1390 * actually load anything. Instead, it holds on to the storage pointer
1391 * and it will load the presentation information when the
1392 * IDataObject_GetData or IViewObject2_Draw methods are called.
1394 * See Windows documentation for more details on IPersistStorage methods.
1396 static HRESULT WINAPI DataCache_Load(
1397 IPersistStorage* iface,
1398 IStorage* pStg)
1400 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1402 TRACE("(%p, %p)\n", iface, pStg);
1404 if (this->presentationStorage != NULL)
1406 IStorage_Release(this->presentationStorage);
1409 this->presentationStorage = pStg;
1411 if (this->presentationStorage != NULL)
1413 IStorage_AddRef(this->presentationStorage);
1415 return S_OK;
1418 /************************************************************************
1419 * DataCache_Save (IPersistStorage)
1421 * Until we actully connect to a running object and retrieve new
1422 * information to it, we never have to save anything. However, it is
1423 * our responsability to copy the information when saving to a new
1424 * storage.
1426 * See Windows documentation for more details on IPersistStorage methods.
1428 static HRESULT WINAPI DataCache_Save(
1429 IPersistStorage* iface,
1430 IStorage* pStg,
1431 BOOL fSameAsLoad)
1433 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1435 TRACE("(%p, %p, %d)\n", iface, pStg, fSameAsLoad);
1437 if ( (!fSameAsLoad) &&
1438 (this->presentationStorage!=NULL) )
1440 return IStorage_CopyTo(this->presentationStorage,
1442 NULL,
1443 NULL,
1444 pStg);
1447 return S_OK;
1450 /************************************************************************
1451 * DataCache_SaveCompleted (IPersistStorage)
1453 * This method is called to tell the cache to release the storage
1454 * pointer it's currentlu holding.
1456 * See Windows documentation for more details on IPersistStorage methods.
1458 static HRESULT WINAPI DataCache_SaveCompleted(
1459 IPersistStorage* iface,
1460 IStorage* pStgNew)
1462 TRACE("(%p, %p)\n", iface, pStgNew);
1464 if (pStgNew)
1467 * First, make sure we get our hands off any storage we have.
1470 DataCache_HandsOffStorage(iface);
1473 * Then, attach to the new storage.
1476 DataCache_Load(iface, pStgNew);
1479 return S_OK;
1482 /************************************************************************
1483 * DataCache_HandsOffStorage (IPersistStorage)
1485 * This method is called to tell the cache to release the storage
1486 * pointer it's currentlu holding.
1488 * See Windows documentation for more details on IPersistStorage methods.
1490 static HRESULT WINAPI DataCache_HandsOffStorage(
1491 IPersistStorage* iface)
1493 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1495 TRACE("(%p)\n", iface);
1497 if (this->presentationStorage != NULL)
1499 IStorage_Release(this->presentationStorage);
1500 this->presentationStorage = NULL;
1503 return S_OK;
1506 /*********************************************************
1507 * Method implementation for the IViewObject2
1508 * part of the DataCache class.
1511 /************************************************************************
1512 * DataCache_IViewObject2_QueryInterface (IUnknown)
1514 * See Windows documentation for more details on IUnknown methods.
1516 static HRESULT WINAPI DataCache_IViewObject2_QueryInterface(
1517 IViewObject2* iface,
1518 REFIID riid,
1519 void** ppvObject)
1521 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1523 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1526 /************************************************************************
1527 * DataCache_IViewObject2_AddRef (IUnknown)
1529 * See Windows documentation for more details on IUnknown methods.
1531 static ULONG WINAPI DataCache_IViewObject2_AddRef(
1532 IViewObject2* iface)
1534 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1536 return IUnknown_AddRef(this->outerUnknown);
1539 /************************************************************************
1540 * DataCache_IViewObject2_Release (IUnknown)
1542 * See Windows documentation for more details on IUnknown methods.
1544 static ULONG WINAPI DataCache_IViewObject2_Release(
1545 IViewObject2* iface)
1547 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1549 return IUnknown_Release(this->outerUnknown);
1552 /************************************************************************
1553 * DataCache_Draw (IViewObject2)
1555 * This method will draw the cached representation of the object
1556 * to the given device context.
1558 * See Windows documentation for more details on IViewObject2 methods.
1560 static HRESULT WINAPI DataCache_Draw(
1561 IViewObject2* iface,
1562 DWORD dwDrawAspect,
1563 LONG lindex,
1564 void* pvAspect,
1565 DVTARGETDEVICE* ptd,
1566 HDC hdcTargetDev,
1567 HDC hdcDraw,
1568 LPCRECTL lprcBounds,
1569 LPCRECTL lprcWBounds,
1570 IVO_ContCallback pfnContinue,
1571 DWORD dwContinue)
1573 PresentationDataHeader presData;
1574 HMETAFILE presMetafile = 0;
1575 HRESULT hres;
1577 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1579 TRACE("(%p, %lx, %ld, %p, %p, %p, %p, %p, %p, %lx)\n",
1580 iface,
1581 dwDrawAspect,
1582 lindex,
1583 pvAspect,
1584 hdcTargetDev,
1585 hdcDraw,
1586 lprcBounds,
1587 lprcWBounds,
1588 pfnContinue,
1589 dwContinue);
1592 * Sanity check
1594 if (lprcBounds==NULL)
1595 return E_INVALIDARG;
1598 * First, we need to retrieve the dimensions of the
1599 * image in the metafile.
1601 hres = DataCache_ReadPresentationData(this,
1602 dwDrawAspect,
1603 &presData);
1605 if (FAILED(hres))
1606 return hres;
1609 * Then, we can extract the metafile itself from the cached
1610 * data.
1612 * FIXME Unless it isn't a metafile. I think it could be any CF_XXX type,
1613 * particularly CF_DIB.
1615 presMetafile = DataCache_ReadPresMetafile(this,
1616 dwDrawAspect);
1619 * If we have a metafile, just draw baby...
1620 * We have to be careful not to modify the state of the
1621 * DC.
1623 if (presMetafile!=0)
1625 INT prevMapMode = SetMapMode(hdcDraw, MM_ANISOTROPIC);
1626 SIZE oldWindowExt;
1627 SIZE oldViewportExt;
1628 POINT oldViewportOrg;
1630 SetWindowExtEx(hdcDraw,
1631 presData.dwObjectExtentX,
1632 presData.dwObjectExtentY,
1633 &oldWindowExt);
1635 SetViewportExtEx(hdcDraw,
1636 lprcBounds->right - lprcBounds->left,
1637 lprcBounds->bottom - lprcBounds->top,
1638 &oldViewportExt);
1640 SetViewportOrgEx(hdcDraw,
1641 lprcBounds->left,
1642 lprcBounds->top,
1643 &oldViewportOrg);
1645 PlayMetaFile(hdcDraw, presMetafile);
1647 SetWindowExtEx(hdcDraw,
1648 oldWindowExt.cx,
1649 oldWindowExt.cy,
1650 NULL);
1652 SetViewportExtEx(hdcDraw,
1653 oldViewportExt.cx,
1654 oldViewportExt.cy,
1655 NULL);
1657 SetViewportOrgEx(hdcDraw,
1658 oldViewportOrg.x,
1659 oldViewportOrg.y,
1660 NULL);
1662 SetMapMode(hdcDraw, prevMapMode);
1664 DeleteMetaFile(presMetafile);
1667 return S_OK;
1670 static HRESULT WINAPI DataCache_GetColorSet(
1671 IViewObject2* iface,
1672 DWORD dwDrawAspect,
1673 LONG lindex,
1674 void* pvAspect,
1675 DVTARGETDEVICE* ptd,
1676 HDC hicTargetDevice,
1677 LOGPALETTE** ppColorSet)
1679 FIXME("stub\n");
1680 return E_NOTIMPL;
1683 static HRESULT WINAPI DataCache_Freeze(
1684 IViewObject2* iface,
1685 DWORD dwDrawAspect,
1686 LONG lindex,
1687 void* pvAspect,
1688 DWORD* pdwFreeze)
1690 FIXME("stub\n");
1691 return E_NOTIMPL;
1694 static HRESULT WINAPI DataCache_Unfreeze(
1695 IViewObject2* iface,
1696 DWORD dwFreeze)
1698 FIXME("stub\n");
1699 return E_NOTIMPL;
1702 /************************************************************************
1703 * DataCache_SetAdvise (IViewObject2)
1705 * This sets-up an advisory sink with the data cache. When the object's
1706 * view changes, this sink is called.
1708 * See Windows documentation for more details on IViewObject2 methods.
1710 static HRESULT WINAPI DataCache_SetAdvise(
1711 IViewObject2* iface,
1712 DWORD aspects,
1713 DWORD advf,
1714 IAdviseSink* pAdvSink)
1716 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1718 TRACE("(%p, %lx, %lx, %p)\n", iface, aspects, advf, pAdvSink);
1721 * A call to this function removes the previous sink
1723 if (this->sinkInterface != NULL)
1725 IAdviseSink_Release(this->sinkInterface);
1726 this->sinkInterface = NULL;
1727 this->sinkAspects = 0;
1728 this->sinkAdviseFlag = 0;
1732 * Now, setup the new one.
1734 if (pAdvSink!=NULL)
1736 this->sinkInterface = pAdvSink;
1737 this->sinkAspects = aspects;
1738 this->sinkAdviseFlag = advf;
1740 IAdviseSink_AddRef(this->sinkInterface);
1744 * When the ADVF_PRIMEFIRST flag is set, we have to advise the
1745 * sink immediately.
1747 if (advf & ADVF_PRIMEFIRST)
1749 DataCache_FireOnViewChange(this,
1750 DVASPECT_CONTENT,
1751 -1);
1754 return S_OK;
1757 /************************************************************************
1758 * DataCache_GetAdvise (IViewObject2)
1760 * This method queries the current state of the advise sink
1761 * installed on the data cache.
1763 * See Windows documentation for more details on IViewObject2 methods.
1765 static HRESULT WINAPI DataCache_GetAdvise(
1766 IViewObject2* iface,
1767 DWORD* pAspects,
1768 DWORD* pAdvf,
1769 IAdviseSink** ppAdvSink)
1771 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1773 TRACE("(%p, %p, %p, %p)\n", iface, pAspects, pAdvf, ppAdvSink);
1776 * Just copy all the requested values.
1778 if (pAspects!=NULL)
1779 *pAspects = this->sinkAspects;
1781 if (pAdvf!=NULL)
1782 *pAdvf = this->sinkAdviseFlag;
1784 if (ppAdvSink!=NULL)
1786 IAdviseSink_QueryInterface(this->sinkInterface,
1787 &IID_IAdviseSink,
1788 (void**)ppAdvSink);
1791 return S_OK;
1794 /************************************************************************
1795 * DataCache_GetExtent (IViewObject2)
1797 * This method retrieves the "natural" size of this cached object.
1799 * See Windows documentation for more details on IViewObject2 methods.
1801 static HRESULT WINAPI DataCache_GetExtent(
1802 IViewObject2* iface,
1803 DWORD dwDrawAspect,
1804 LONG lindex,
1805 DVTARGETDEVICE* ptd,
1806 LPSIZEL lpsizel)
1808 PresentationDataHeader presData;
1809 HRESULT hres = E_FAIL;
1811 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1813 TRACE("(%p, %lx, %ld, %p, %p)\n",
1814 iface, dwDrawAspect, lindex, ptd, lpsizel);
1817 * Sanity check
1819 if (lpsizel==NULL)
1820 return E_POINTER;
1823 * Initialize the out parameter.
1825 lpsizel->cx = 0;
1826 lpsizel->cy = 0;
1829 * This flag should be set to -1.
1831 if (lindex!=-1)
1832 FIXME("Unimplemented flag lindex = %ld\n", lindex);
1835 * Right now, we suport only the callback from
1836 * the default handler.
1838 if (ptd!=NULL)
1839 FIXME("Unimplemented ptd = %p\n", ptd);
1842 * Get the presentation information from the
1843 * cache.
1845 hres = DataCache_ReadPresentationData(this,
1846 dwDrawAspect,
1847 &presData);
1849 if (SUCCEEDED(hres))
1851 lpsizel->cx = presData.dwObjectExtentX;
1852 lpsizel->cy = presData.dwObjectExtentY;
1856 * This method returns OLE_E_BLANK when it fails.
1858 if (FAILED(hres))
1859 hres = OLE_E_BLANK;
1861 return hres;
1865 /*********************************************************
1866 * Method implementation for the IOleCache2
1867 * part of the DataCache class.
1870 /************************************************************************
1871 * DataCache_IOleCache2_QueryInterface (IUnknown)
1873 * See Windows documentation for more details on IUnknown methods.
1875 static HRESULT WINAPI DataCache_IOleCache2_QueryInterface(
1876 IOleCache2* iface,
1877 REFIID riid,
1878 void** ppvObject)
1880 _ICOM_THIS_From_IOleCache2(DataCache, iface);
1882 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1885 /************************************************************************
1886 * DataCache_IOleCache2_AddRef (IUnknown)
1888 * See Windows documentation for more details on IUnknown methods.
1890 static ULONG WINAPI DataCache_IOleCache2_AddRef(
1891 IOleCache2* iface)
1893 _ICOM_THIS_From_IOleCache2(DataCache, iface);
1895 return IUnknown_AddRef(this->outerUnknown);
1898 /************************************************************************
1899 * DataCache_IOleCache2_Release (IUnknown)
1901 * See Windows documentation for more details on IUnknown methods.
1903 static ULONG WINAPI DataCache_IOleCache2_Release(
1904 IOleCache2* iface)
1906 _ICOM_THIS_From_IOleCache2(DataCache, iface);
1908 return IUnknown_Release(this->outerUnknown);
1911 static HRESULT WINAPI DataCache_Cache(
1912 IOleCache2* iface,
1913 FORMATETC* pformatetc,
1914 DWORD advf,
1915 DWORD* pdwConnection)
1917 FIXME("stub\n");
1918 return E_NOTIMPL;
1921 static HRESULT WINAPI DataCache_Uncache(
1922 IOleCache2* iface,
1923 DWORD dwConnection)
1925 FIXME("stub\n");
1926 return E_NOTIMPL;
1929 static HRESULT WINAPI DataCache_EnumCache(
1930 IOleCache2* iface,
1931 IEnumSTATDATA** ppenumSTATDATA)
1933 FIXME("stub\n");
1934 return E_NOTIMPL;
1937 static HRESULT WINAPI DataCache_InitCache(
1938 IOleCache2* iface,
1939 IDataObject* pDataObject)
1941 FIXME("stub\n");
1942 return E_NOTIMPL;
1945 static HRESULT WINAPI DataCache_IOleCache2_SetData(
1946 IOleCache2* iface,
1947 FORMATETC* pformatetc,
1948 STGMEDIUM* pmedium,
1949 BOOL fRelease)
1951 FIXME("stub\n");
1952 return E_NOTIMPL;
1955 static HRESULT WINAPI DataCache_UpdateCache(
1956 IOleCache2* iface,
1957 LPDATAOBJECT pDataObject,
1958 DWORD grfUpdf,
1959 LPVOID pReserved)
1961 FIXME("stub\n");
1962 return E_NOTIMPL;
1965 static HRESULT WINAPI DataCache_DiscardCache(
1966 IOleCache2* iface,
1967 DWORD dwDiscardOptions)
1969 FIXME("stub\n");
1970 return E_NOTIMPL;
1974 /*********************************************************
1975 * Method implementation for the IOleCacheControl
1976 * part of the DataCache class.
1979 /************************************************************************
1980 * DataCache_IOleCacheControl_QueryInterface (IUnknown)
1982 * See Windows documentation for more details on IUnknown methods.
1984 static HRESULT WINAPI DataCache_IOleCacheControl_QueryInterface(
1985 IOleCacheControl* iface,
1986 REFIID riid,
1987 void** ppvObject)
1989 _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
1991 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1994 /************************************************************************
1995 * DataCache_IOleCacheControl_AddRef (IUnknown)
1997 * See Windows documentation for more details on IUnknown methods.
1999 static ULONG WINAPI DataCache_IOleCacheControl_AddRef(
2000 IOleCacheControl* iface)
2002 _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
2004 return IUnknown_AddRef(this->outerUnknown);
2007 /************************************************************************
2008 * DataCache_IOleCacheControl_Release (IUnknown)
2010 * See Windows documentation for more details on IUnknown methods.
2012 static ULONG WINAPI DataCache_IOleCacheControl_Release(
2013 IOleCacheControl* iface)
2015 _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
2017 return IUnknown_Release(this->outerUnknown);
2020 static HRESULT WINAPI DataCache_OnRun(
2021 IOleCacheControl* iface,
2022 LPDATAOBJECT pDataObject)
2024 FIXME("stub\n");
2025 return E_NOTIMPL;
2028 static HRESULT WINAPI DataCache_OnStop(
2029 IOleCacheControl* iface)
2031 FIXME("stub\n");
2032 return E_NOTIMPL;