Fixed header dependencies to be fully compatible with the Windows
[wine/multimedia.git] / dlls / ole32 / datacache.c
blob65feca5a92cb03c47a444e6b473f02bdaa3d5101
1 /*
2 * OLE 2 Data cache
4 * Copyright 1999 Francis Beaudet
5 * Copyright 2000 Abey George
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * NOTES:
22 * The OLE2 data cache supports a whole whack of
23 * interfaces including:
24 * IDataObject, IPersistStorage, IViewObject2,
25 * IOleCache2 and IOleCacheControl.
27 * Most of the implementation details are taken from: Inside OLE
28 * second edition by Kraig Brockschmidt,
30 * NOTES
31 * - This implementation of the datacache will let your application
32 * load documents that have embedded OLE objects in them and it will
33 * also retrieve the metafile representation of those objects.
34 * - This implementation of the datacache will also allow your
35 * application to save new documents with OLE objects in them.
36 * - The main thing that it doesn't do is allow you to activate
37 * or modify the OLE objects in any way.
38 * - I haven't found any good documentation on the real usage of
39 * the streams created by the data cache. In particular, How to
40 * determine what the XXX stands for in the stream name
41 * "\002OlePresXXX". It appears to just be a counter.
42 * - Also, I don't know the real content of the presentation stream
43 * header. I was able to figure-out where the extent of the object
44 * was stored and the aspect, but that's about it.
46 #include <assert.h>
47 #include <stdarg.h>
48 #include <string.h>
50 #define NONAMELESSUNION
51 #define NONAMELESSSTRUCT
52 #include "windef.h"
53 #include "winbase.h"
54 #include "wingdi.h"
55 #include "winuser.h"
56 #include "winerror.h"
57 #include "wine/unicode.h"
58 #include "ole2.h"
59 #include "wine/debug.h"
61 WINE_DEFAULT_DEBUG_CHANNEL(ole);
63 /****************************************************************************
64 * PresentationDataHeader
66 * This structure represents the header of the \002OlePresXXX stream in
67 * the OLE object strorage.
69 * Most fields are still unknown.
71 typedef struct PresentationDataHeader
73 DWORD unknown1; /* -1 */
74 DWORD unknown2; /* 3, possibly CF_METAFILEPICT */
75 DWORD unknown3; /* 4, possibly TYMED_ISTREAM */
76 DVASPECT dvAspect;
77 DWORD unknown5; /* -1 */
79 DWORD unknown6;
80 DWORD unknown7; /* 0 */
81 DWORD dwObjectExtentX;
82 DWORD dwObjectExtentY;
83 DWORD dwSize;
84 } PresentationDataHeader;
86 /****************************************************************************
87 * DataCache
89 struct DataCache
92 * List all interface VTables here
94 ICOM_VTABLE(IDataObject)* lpvtbl1;
95 ICOM_VTABLE(IUnknown)* lpvtbl2;
96 ICOM_VTABLE(IPersistStorage)* lpvtbl3;
97 ICOM_VTABLE(IViewObject2)* lpvtbl4;
98 ICOM_VTABLE(IOleCache2)* lpvtbl5;
99 ICOM_VTABLE(IOleCacheControl)* lpvtbl6;
102 * Reference count of this object
104 ULONG ref;
107 * IUnknown implementation of the outer object.
109 IUnknown* outerUnknown;
112 * This storage pointer is set through a call to
113 * IPersistStorage_Load. This is where the visual
114 * representation of the object is stored.
116 IStorage* presentationStorage;
119 * The user of this object can setup ONE advise sink
120 * connection with the object. These parameters describe
121 * that connection.
123 DWORD sinkAspects;
124 DWORD sinkAdviseFlag;
125 IAdviseSink* sinkInterface;
129 typedef struct DataCache DataCache;
132 * Here, I define utility macros to help with the casting of the
133 * "this" parameter.
134 * There is a version to accomodate all of the VTables implemented
135 * by this object.
137 #define _ICOM_THIS_From_IDataObject(class,name) class* this = (class*)name;
138 #define _ICOM_THIS_From_NDIUnknown(class, name) class* this = (class*)(((char*)name)-sizeof(void*));
139 #define _ICOM_THIS_From_IPersistStorage(class, name) class* this = (class*)(((char*)name)-2*sizeof(void*));
140 #define _ICOM_THIS_From_IViewObject2(class, name) class* this = (class*)(((char*)name)-3*sizeof(void*));
141 #define _ICOM_THIS_From_IOleCache2(class, name) class* this = (class*)(((char*)name)-4*sizeof(void*));
142 #define _ICOM_THIS_From_IOleCacheControl(class, name) class* this = (class*)(((char*)name)-5*sizeof(void*));
145 * Prototypes for the methods of the DataCache class.
147 static DataCache* DataCache_Construct(REFCLSID clsid,
148 LPUNKNOWN pUnkOuter);
149 static void DataCache_Destroy(DataCache* ptrToDestroy);
150 static HRESULT DataCache_ReadPresentationData(DataCache* this,
151 DWORD drawAspect,
152 PresentationDataHeader* header);
153 static HRESULT DataCache_OpenPresStream(DataCache *this,
154 DWORD drawAspect,
155 IStream **pStm);
156 static HMETAFILE DataCache_ReadPresMetafile(DataCache* this,
157 DWORD drawAspect);
158 static void DataCache_FireOnViewChange(DataCache* this,
159 DWORD aspect,
160 LONG lindex);
163 * Prototypes for the methods of the DataCache class
164 * that implement non delegating IUnknown methods.
166 static HRESULT WINAPI DataCache_NDIUnknown_QueryInterface(
167 IUnknown* iface,
168 REFIID riid,
169 void** ppvObject);
170 static ULONG WINAPI DataCache_NDIUnknown_AddRef(
171 IUnknown* iface);
172 static ULONG WINAPI DataCache_NDIUnknown_Release(
173 IUnknown* iface);
176 * Prototypes for the methods of the DataCache class
177 * that implement IDataObject methods.
179 static HRESULT WINAPI DataCache_IDataObject_QueryInterface(
180 IDataObject* iface,
181 REFIID riid,
182 void** ppvObject);
183 static ULONG WINAPI DataCache_IDataObject_AddRef(
184 IDataObject* iface);
185 static ULONG WINAPI DataCache_IDataObject_Release(
186 IDataObject* iface);
187 static HRESULT WINAPI DataCache_GetData(
188 IDataObject* iface,
189 LPFORMATETC pformatetcIn,
190 STGMEDIUM* pmedium);
191 static HRESULT WINAPI DataCache_GetDataHere(
192 IDataObject* iface,
193 LPFORMATETC pformatetc,
194 STGMEDIUM* pmedium);
195 static HRESULT WINAPI DataCache_QueryGetData(
196 IDataObject* iface,
197 LPFORMATETC pformatetc);
198 static HRESULT WINAPI DataCache_GetCanonicalFormatEtc(
199 IDataObject* iface,
200 LPFORMATETC pformatectIn,
201 LPFORMATETC pformatetcOut);
202 static HRESULT WINAPI DataCache_IDataObject_SetData(
203 IDataObject* iface,
204 LPFORMATETC pformatetc,
205 STGMEDIUM* pmedium,
206 BOOL fRelease);
207 static HRESULT WINAPI DataCache_EnumFormatEtc(
208 IDataObject* iface,
209 DWORD dwDirection,
210 IEnumFORMATETC** ppenumFormatEtc);
211 static HRESULT WINAPI DataCache_DAdvise(
212 IDataObject* iface,
213 FORMATETC* pformatetc,
214 DWORD advf,
215 IAdviseSink* pAdvSink,
216 DWORD* pdwConnection);
217 static HRESULT WINAPI DataCache_DUnadvise(
218 IDataObject* iface,
219 DWORD dwConnection);
220 static HRESULT WINAPI DataCache_EnumDAdvise(
221 IDataObject* iface,
222 IEnumSTATDATA** ppenumAdvise);
225 * Prototypes for the methods of the DataCache class
226 * that implement IPersistStorage methods.
228 static HRESULT WINAPI DataCache_IPersistStorage_QueryInterface(
229 IPersistStorage* iface,
230 REFIID riid,
231 void** ppvObject);
232 static ULONG WINAPI DataCache_IPersistStorage_AddRef(
233 IPersistStorage* iface);
234 static ULONG WINAPI DataCache_IPersistStorage_Release(
235 IPersistStorage* iface);
236 static HRESULT WINAPI DataCache_GetClassID(
237 IPersistStorage* iface,
238 CLSID* pClassID);
239 static HRESULT WINAPI DataCache_IsDirty(
240 IPersistStorage* iface);
241 static HRESULT WINAPI DataCache_InitNew(
242 IPersistStorage* iface,
243 IStorage* pStg);
244 static HRESULT WINAPI DataCache_Load(
245 IPersistStorage* iface,
246 IStorage* pStg);
247 static HRESULT WINAPI DataCache_Save(
248 IPersistStorage* iface,
249 IStorage* pStg,
250 BOOL fSameAsLoad);
251 static HRESULT WINAPI DataCache_SaveCompleted(
252 IPersistStorage* iface,
253 IStorage* pStgNew);
254 static HRESULT WINAPI DataCache_HandsOffStorage(
255 IPersistStorage* iface);
258 * Prototypes for the methods of the DataCache class
259 * that implement IViewObject2 methods.
261 static HRESULT WINAPI DataCache_IViewObject2_QueryInterface(
262 IViewObject2* iface,
263 REFIID riid,
264 void** ppvObject);
265 static ULONG WINAPI DataCache_IViewObject2_AddRef(
266 IViewObject2* iface);
267 static ULONG WINAPI DataCache_IViewObject2_Release(
268 IViewObject2* iface);
269 static HRESULT WINAPI DataCache_Draw(
270 IViewObject2* iface,
271 DWORD dwDrawAspect,
272 LONG lindex,
273 void* pvAspect,
274 DVTARGETDEVICE* ptd,
275 HDC hdcTargetDev,
276 HDC hdcDraw,
277 LPCRECTL lprcBounds,
278 LPCRECTL lprcWBounds,
279 BOOL (CALLBACK *pfnContinue)(ULONG_PTR dwContinue),
280 DWORD dwContinue);
281 static HRESULT WINAPI DataCache_GetColorSet(
282 IViewObject2* iface,
283 DWORD dwDrawAspect,
284 LONG lindex,
285 void* pvAspect,
286 DVTARGETDEVICE* ptd,
287 HDC hicTargetDevice,
288 LOGPALETTE** ppColorSet);
289 static HRESULT WINAPI DataCache_Freeze(
290 IViewObject2* iface,
291 DWORD dwDrawAspect,
292 LONG lindex,
293 void* pvAspect,
294 DWORD* pdwFreeze);
295 static HRESULT WINAPI DataCache_Unfreeze(
296 IViewObject2* iface,
297 DWORD dwFreeze);
298 static HRESULT WINAPI DataCache_SetAdvise(
299 IViewObject2* iface,
300 DWORD aspects,
301 DWORD advf,
302 IAdviseSink* pAdvSink);
303 static HRESULT WINAPI DataCache_GetAdvise(
304 IViewObject2* iface,
305 DWORD* pAspects,
306 DWORD* pAdvf,
307 IAdviseSink** ppAdvSink);
308 static HRESULT WINAPI DataCache_GetExtent(
309 IViewObject2* iface,
310 DWORD dwDrawAspect,
311 LONG lindex,
312 DVTARGETDEVICE* ptd,
313 LPSIZEL lpsizel);
316 * Prototypes for the methods of the DataCache class
317 * that implement IOleCache2 methods.
319 static HRESULT WINAPI DataCache_IOleCache2_QueryInterface(
320 IOleCache2* iface,
321 REFIID riid,
322 void** ppvObject);
323 static ULONG WINAPI DataCache_IOleCache2_AddRef(
324 IOleCache2* iface);
325 static ULONG WINAPI DataCache_IOleCache2_Release(
326 IOleCache2* iface);
327 static HRESULT WINAPI DataCache_Cache(
328 IOleCache2* iface,
329 FORMATETC* pformatetc,
330 DWORD advf,
331 DWORD* pdwConnection);
332 static HRESULT WINAPI DataCache_Uncache(
333 IOleCache2* iface,
334 DWORD dwConnection);
335 static HRESULT WINAPI DataCache_EnumCache(
336 IOleCache2* iface,
337 IEnumSTATDATA** ppenumSTATDATA);
338 static HRESULT WINAPI DataCache_InitCache(
339 IOleCache2* iface,
340 IDataObject* pDataObject);
341 static HRESULT WINAPI DataCache_IOleCache2_SetData(
342 IOleCache2* iface,
343 FORMATETC* pformatetc,
344 STGMEDIUM* pmedium,
345 BOOL fRelease);
346 static HRESULT WINAPI DataCache_UpdateCache(
347 IOleCache2* iface,
348 LPDATAOBJECT pDataObject,
349 DWORD grfUpdf,
350 LPVOID pReserved);
351 static HRESULT WINAPI DataCache_DiscardCache(
352 IOleCache2* iface,
353 DWORD dwDiscardOptions);
356 * Prototypes for the methods of the DataCache class
357 * that implement IOleCacheControl methods.
359 static HRESULT WINAPI DataCache_IOleCacheControl_QueryInterface(
360 IOleCacheControl* iface,
361 REFIID riid,
362 void** ppvObject);
363 static ULONG WINAPI DataCache_IOleCacheControl_AddRef(
364 IOleCacheControl* iface);
365 static ULONG WINAPI DataCache_IOleCacheControl_Release(
366 IOleCacheControl* iface);
367 static HRESULT WINAPI DataCache_OnRun(
368 IOleCacheControl* iface,
369 LPDATAOBJECT pDataObject);
370 static HRESULT WINAPI DataCache_OnStop(
371 IOleCacheControl* iface);
374 * Virtual function tables for the DataCache class.
376 static ICOM_VTABLE(IUnknown) DataCache_NDIUnknown_VTable =
378 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
379 DataCache_NDIUnknown_QueryInterface,
380 DataCache_NDIUnknown_AddRef,
381 DataCache_NDIUnknown_Release
384 static ICOM_VTABLE(IDataObject) DataCache_IDataObject_VTable =
386 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
387 DataCache_IDataObject_QueryInterface,
388 DataCache_IDataObject_AddRef,
389 DataCache_IDataObject_Release,
390 DataCache_GetData,
391 DataCache_GetDataHere,
392 DataCache_QueryGetData,
393 DataCache_GetCanonicalFormatEtc,
394 DataCache_IDataObject_SetData,
395 DataCache_EnumFormatEtc,
396 DataCache_DAdvise,
397 DataCache_DUnadvise,
398 DataCache_EnumDAdvise
401 static ICOM_VTABLE(IPersistStorage) DataCache_IPersistStorage_VTable =
403 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
404 DataCache_IPersistStorage_QueryInterface,
405 DataCache_IPersistStorage_AddRef,
406 DataCache_IPersistStorage_Release,
407 DataCache_GetClassID,
408 DataCache_IsDirty,
409 DataCache_InitNew,
410 DataCache_Load,
411 DataCache_Save,
412 DataCache_SaveCompleted,
413 DataCache_HandsOffStorage
416 static ICOM_VTABLE(IViewObject2) DataCache_IViewObject2_VTable =
418 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
419 DataCache_IViewObject2_QueryInterface,
420 DataCache_IViewObject2_AddRef,
421 DataCache_IViewObject2_Release,
422 DataCache_Draw,
423 DataCache_GetColorSet,
424 DataCache_Freeze,
425 DataCache_Unfreeze,
426 DataCache_SetAdvise,
427 DataCache_GetAdvise,
428 DataCache_GetExtent
431 static ICOM_VTABLE(IOleCache2) DataCache_IOleCache2_VTable =
433 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
434 DataCache_IOleCache2_QueryInterface,
435 DataCache_IOleCache2_AddRef,
436 DataCache_IOleCache2_Release,
437 DataCache_Cache,
438 DataCache_Uncache,
439 DataCache_EnumCache,
440 DataCache_InitCache,
441 DataCache_IOleCache2_SetData,
442 DataCache_UpdateCache,
443 DataCache_DiscardCache
446 static ICOM_VTABLE(IOleCacheControl) DataCache_IOleCacheControl_VTable =
448 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
449 DataCache_IOleCacheControl_QueryInterface,
450 DataCache_IOleCacheControl_AddRef,
451 DataCache_IOleCacheControl_Release,
452 DataCache_OnRun,
453 DataCache_OnStop
456 /******************************************************************************
457 * CreateDataCache [OLE32.54]
459 HRESULT WINAPI CreateDataCache(
460 LPUNKNOWN pUnkOuter,
461 REFCLSID rclsid,
462 REFIID riid,
463 LPVOID* ppvObj)
465 DataCache* newCache = NULL;
466 HRESULT hr = S_OK;
468 TRACE("(%s, %p, %s, %p)\n", debugstr_guid(rclsid), pUnkOuter, debugstr_guid(riid), ppvObj);
471 * Sanity check
473 if (ppvObj==0)
474 return E_POINTER;
476 *ppvObj = 0;
479 * If this cache is constructed for aggregation, make sure
480 * the caller is requesting the IUnknown interface.
481 * This is necessary because it's the only time the non-delegating
482 * IUnknown pointer can be returned to the outside.
484 if ( (pUnkOuter!=NULL) &&
485 (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) != 0) )
486 return CLASS_E_NOAGGREGATION;
489 * Try to construct a new instance of the class.
491 newCache = DataCache_Construct(rclsid,
492 pUnkOuter);
494 if (newCache == 0)
495 return E_OUTOFMEMORY;
498 * Make sure it supports the interface required by the caller.
500 hr = IUnknown_QueryInterface((IUnknown*)&(newCache->lpvtbl2), riid, ppvObj);
503 * Release the reference obtained in the constructor. If
504 * the QueryInterface was unsuccessful, it will free the class.
506 IUnknown_Release((IUnknown*)&(newCache->lpvtbl2));
508 return hr;
511 /*********************************************************
512 * Method implementation for DataCache class.
514 static DataCache* DataCache_Construct(
515 REFCLSID clsid,
516 LPUNKNOWN pUnkOuter)
518 DataCache* newObject = 0;
521 * Allocate space for the object.
523 newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(DataCache));
525 if (newObject==0)
526 return newObject;
529 * Initialize the virtual function table.
531 newObject->lpvtbl1 = &DataCache_IDataObject_VTable;
532 newObject->lpvtbl2 = &DataCache_NDIUnknown_VTable;
533 newObject->lpvtbl3 = &DataCache_IPersistStorage_VTable;
534 newObject->lpvtbl4 = &DataCache_IViewObject2_VTable;
535 newObject->lpvtbl5 = &DataCache_IOleCache2_VTable;
536 newObject->lpvtbl6 = &DataCache_IOleCacheControl_VTable;
539 * Start with one reference count. The caller of this function
540 * must release the interface pointer when it is done.
542 newObject->ref = 1;
545 * Initialize the outer unknown
546 * We don't keep a reference on the outer unknown since, the way
547 * aggregation works, our lifetime is at least as large as it's
548 * lifetime.
550 if (pUnkOuter==NULL)
551 pUnkOuter = (IUnknown*)&(newObject->lpvtbl2);
553 newObject->outerUnknown = pUnkOuter;
556 * Initialize the other members of the structure.
558 newObject->presentationStorage = NULL;
559 newObject->sinkAspects = 0;
560 newObject->sinkAdviseFlag = 0;
561 newObject->sinkInterface = 0;
563 return newObject;
566 static void DataCache_Destroy(
567 DataCache* ptrToDestroy)
569 TRACE("()\n");
571 if (ptrToDestroy->sinkInterface != NULL)
573 IAdviseSink_Release(ptrToDestroy->sinkInterface);
574 ptrToDestroy->sinkInterface = NULL;
577 if (ptrToDestroy->presentationStorage != NULL)
579 IStorage_Release(ptrToDestroy->presentationStorage);
580 ptrToDestroy->presentationStorage = NULL;
584 * Free the datacache pointer.
586 HeapFree(GetProcessHeap(), 0, ptrToDestroy);
589 /************************************************************************
590 * DataCache_ReadPresentationData
592 * This method will read information for the requested presentation
593 * into the given structure.
595 * Param:
596 * this - Pointer to the DataCache object
597 * drawAspect - The aspect of the object that we wish to draw.
598 * header - The structure containing information about this
599 * aspect of the object.
601 static HRESULT DataCache_ReadPresentationData(
602 DataCache* this,
603 DWORD drawAspect,
604 PresentationDataHeader* header)
606 IStream* presStream = NULL;
607 HRESULT hres;
610 * Open the presentation stream.
612 hres = DataCache_OpenPresStream(
613 this,
614 drawAspect,
615 &presStream);
617 if (FAILED(hres))
618 return hres;
621 * Read the header.
624 hres = IStream_Read(
625 presStream,
626 header,
627 sizeof(PresentationDataHeader),
628 NULL);
631 * Cleanup.
633 IStream_Release(presStream);
636 * We don't want to propagate any other error
637 * code than a failure.
639 if (hres!=S_OK)
640 hres = E_FAIL;
642 return hres;
645 /************************************************************************
646 * DataCache_FireOnViewChange
648 * This method will fire an OnViewChange notification to the advise
649 * sink registered with the datacache.
651 * See IAdviseSink::OnViewChange for more details.
653 static void DataCache_FireOnViewChange(
654 DataCache* this,
655 DWORD aspect,
656 LONG lindex)
658 TRACE("(%p, %lx, %ld)\n", this, aspect, lindex);
661 * The sink supplies a filter when it registers
662 * we make sure we only send the notifications when that
663 * filter matches.
665 if ((this->sinkAspects & aspect) != 0)
667 if (this->sinkInterface != NULL)
669 IAdviseSink_OnViewChange(this->sinkInterface,
670 aspect,
671 lindex);
674 * Some sinks want to be unregistered automatically when
675 * the first notification goes out.
677 if ( (this->sinkAdviseFlag & ADVF_ONLYONCE) != 0)
679 IAdviseSink_Release(this->sinkInterface);
681 this->sinkInterface = NULL;
682 this->sinkAspects = 0;
683 this->sinkAdviseFlag = 0;
689 /* Helper for DataCache_OpenPresStream */
690 static BOOL DataCache_IsPresentationStream(const STATSTG *elem)
692 /* The presentation streams have names of the form "\002OlePresXXX",
693 * where XXX goes from 000 to 999. */
694 static const WCHAR OlePres[] = { 2,'O','l','e','P','r','e','s' };
696 LPCWSTR name = elem->pwcsName;
698 return (elem->type == STGTY_STREAM)
699 && (elem->cbSize.s.LowPart >= sizeof(PresentationDataHeader))
700 && (strlenW(name) == 11)
701 && (strncmpW(name, OlePres, 8) == 0)
702 && (name[8] >= '0') && (name[8] <= '9')
703 && (name[9] >= '0') && (name[9] <= '9')
704 && (name[10] >= '0') && (name[10] <= '9');
707 /************************************************************************
708 * DataCache_OpenPresStream
710 * This method will find the stream for the given presentation. It makes
711 * no attempt at fallback.
713 * Param:
714 * this - Pointer to the DataCache object
715 * drawAspect - The aspect of the object that we wish to draw.
716 * pStm - A returned stream. It points to the beginning of the
717 * - presentation data, including the header.
719 * Errors:
720 * S_OK The requested stream has been opened.
721 * OLE_E_BLANK The requested stream could not be found.
722 * Quite a few others I'm too lazy to map correctly.
724 * Notes:
725 * Algorithm: Scan the elements of the presentation storage, looking
726 * for presentation streams. For each presentation stream,
727 * load the header and check to see if the aspect maches.
729 * If a fallback is desired, just opening the first presentation stream
730 * is a possibility.
732 static HRESULT DataCache_OpenPresStream(
733 DataCache *this,
734 DWORD drawAspect,
735 IStream **ppStm)
737 STATSTG elem;
738 IEnumSTATSTG *pEnum;
739 HRESULT hr;
741 if (!ppStm) return E_POINTER;
743 hr = IStorage_EnumElements(this->presentationStorage, 0, NULL, 0, &pEnum);
744 if (FAILED(hr)) return hr;
746 while ((hr = IEnumSTATSTG_Next(pEnum, 1, &elem, NULL)) == S_OK)
748 if (DataCache_IsPresentationStream(&elem))
750 IStream *pStm;
752 hr = IStorage_OpenStream(this->presentationStorage, elem.pwcsName,
753 NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0,
754 &pStm);
755 if (SUCCEEDED(hr))
757 PresentationDataHeader header;
758 ULONG actual_read;
760 hr = IStream_Read(pStm, &header, sizeof(header), &actual_read);
762 /* can't use SUCCEEDED(hr): S_FALSE counts as an error */
763 if (hr == S_OK && actual_read == sizeof(header)
764 && header.dvAspect == drawAspect)
766 /* Rewind the stream before returning it. */
767 LARGE_INTEGER offset;
768 offset.s.LowPart = 0;
769 offset.s.HighPart = 0;
770 IStream_Seek(pStm, offset, STREAM_SEEK_SET, NULL);
772 *ppStm = pStm;
774 CoTaskMemFree(elem.pwcsName);
775 IEnumSTATSTG_Release(pEnum);
777 return S_OK;
780 IStream_Release(pStm);
784 CoTaskMemFree(elem.pwcsName);
787 IEnumSTATSTG_Release(pEnum);
789 return (hr == S_FALSE ? OLE_E_BLANK : hr);
792 /************************************************************************
793 * DataCache_ReadPresentationData
795 * This method will read information for the requested presentation
796 * into the given structure.
798 * Param:
799 * this - Pointer to the DataCache object
800 * drawAspect - The aspect of the object that we wish to draw.
802 * Returns:
803 * This method returns a metafile handle if it is successful.
804 * it will return 0 if not.
806 static HMETAFILE DataCache_ReadPresMetafile(
807 DataCache* this,
808 DWORD drawAspect)
810 LARGE_INTEGER offset;
811 IStream* presStream = NULL;
812 HRESULT hres;
813 void* metafileBits;
814 STATSTG streamInfo;
815 HMETAFILE newMetafile = 0;
818 * Open the presentation stream.
820 hres = DataCache_OpenPresStream(
821 this,
822 drawAspect,
823 &presStream);
825 if (FAILED(hres))
826 return (HMETAFILE)hres;
829 * Get the size of the stream.
831 hres = IStream_Stat(presStream,
832 &streamInfo,
833 STATFLAG_NONAME);
836 * Skip the header
838 offset.s.HighPart = 0;
839 offset.s.LowPart = sizeof(PresentationDataHeader);
841 hres = IStream_Seek(
842 presStream,
843 offset,
844 STREAM_SEEK_SET,
845 NULL);
847 streamInfo.cbSize.s.LowPart -= offset.s.LowPart;
850 * Allocate a buffer for the metafile bits.
852 metafileBits = HeapAlloc(GetProcessHeap(),
854 streamInfo.cbSize.s.LowPart);
857 * Read the metafile bits.
859 hres = IStream_Read(
860 presStream,
861 metafileBits,
862 streamInfo.cbSize.s.LowPart,
863 NULL);
866 * Create a metafile with those bits.
868 if (SUCCEEDED(hres))
870 newMetafile = SetMetaFileBitsEx(streamInfo.cbSize.s.LowPart, metafileBits);
874 * Cleanup.
876 HeapFree(GetProcessHeap(), 0, metafileBits);
877 IStream_Release(presStream);
879 if (newMetafile==0)
880 hres = E_FAIL;
882 return newMetafile;
885 /*********************************************************
886 * Method implementation for the non delegating IUnknown
887 * part of the DataCache class.
890 /************************************************************************
891 * DataCache_NDIUnknown_QueryInterface (IUnknown)
893 * See Windows documentation for more details on IUnknown methods.
895 * This version of QueryInterface will not delegate it's implementation
896 * to the outer unknown.
898 static HRESULT WINAPI DataCache_NDIUnknown_QueryInterface(
899 IUnknown* iface,
900 REFIID riid,
901 void** ppvObject)
903 _ICOM_THIS_From_NDIUnknown(DataCache, iface);
906 * Perform a sanity check on the parameters.
908 if ( (this==0) || (ppvObject==0) )
909 return E_INVALIDARG;
912 * Initialize the return parameter.
914 *ppvObject = 0;
917 * Compare the riid with the interface IDs implemented by this object.
919 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
921 *ppvObject = iface;
923 else if (memcmp(&IID_IDataObject, riid, sizeof(IID_IDataObject)) == 0)
925 *ppvObject = (IDataObject*)&(this->lpvtbl1);
927 else if ( (memcmp(&IID_IPersistStorage, riid, sizeof(IID_IPersistStorage)) == 0) ||
928 (memcmp(&IID_IPersist, riid, sizeof(IID_IPersist)) == 0) )
930 *ppvObject = (IPersistStorage*)&(this->lpvtbl3);
932 else if ( (memcmp(&IID_IViewObject, riid, sizeof(IID_IViewObject)) == 0) ||
933 (memcmp(&IID_IViewObject2, riid, sizeof(IID_IViewObject2)) == 0) )
935 *ppvObject = (IViewObject2*)&(this->lpvtbl4);
937 else if ( (memcmp(&IID_IOleCache, riid, sizeof(IID_IOleCache)) == 0) ||
938 (memcmp(&IID_IOleCache2, riid, sizeof(IID_IOleCache2)) == 0) )
940 *ppvObject = (IOleCache2*)&(this->lpvtbl5);
942 else if (memcmp(&IID_IOleCacheControl, riid, sizeof(IID_IOleCacheControl)) == 0)
944 *ppvObject = (IOleCacheControl*)&(this->lpvtbl6);
948 * Check that we obtained an interface.
950 if ((*ppvObject)==0)
952 WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid));
953 return E_NOINTERFACE;
957 * Query Interface always increases the reference count by one when it is
958 * successful.
960 IUnknown_AddRef((IUnknown*)*ppvObject);
962 return S_OK;
965 /************************************************************************
966 * DataCache_NDIUnknown_AddRef (IUnknown)
968 * See Windows documentation for more details on IUnknown methods.
970 * This version of QueryInterface will not delegate it's implementation
971 * to the outer unknown.
973 static ULONG WINAPI DataCache_NDIUnknown_AddRef(
974 IUnknown* iface)
976 _ICOM_THIS_From_NDIUnknown(DataCache, iface);
978 this->ref++;
980 return this->ref;
983 /************************************************************************
984 * DataCache_NDIUnknown_Release (IUnknown)
986 * See Windows documentation for more details on IUnknown methods.
988 * This version of QueryInterface will not delegate it's implementation
989 * to the outer unknown.
991 static ULONG WINAPI DataCache_NDIUnknown_Release(
992 IUnknown* iface)
994 _ICOM_THIS_From_NDIUnknown(DataCache, iface);
997 * Decrease the reference count on this object.
999 this->ref--;
1002 * If the reference count goes down to 0, perform suicide.
1004 if (this->ref==0)
1006 DataCache_Destroy(this);
1008 return 0;
1011 return this->ref;
1014 /*********************************************************
1015 * Method implementation for the IDataObject
1016 * part of the DataCache class.
1019 /************************************************************************
1020 * DataCache_IDataObject_QueryInterface (IUnknown)
1022 * See Windows documentation for more details on IUnknown methods.
1024 static HRESULT WINAPI DataCache_IDataObject_QueryInterface(
1025 IDataObject* iface,
1026 REFIID riid,
1027 void** ppvObject)
1029 _ICOM_THIS_From_IDataObject(DataCache, iface);
1031 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1034 /************************************************************************
1035 * DataCache_IDataObject_AddRef (IUnknown)
1037 * See Windows documentation for more details on IUnknown methods.
1039 static ULONG WINAPI DataCache_IDataObject_AddRef(
1040 IDataObject* iface)
1042 _ICOM_THIS_From_IDataObject(DataCache, iface);
1044 return IUnknown_AddRef(this->outerUnknown);
1047 /************************************************************************
1048 * DataCache_IDataObject_Release (IUnknown)
1050 * See Windows documentation for more details on IUnknown methods.
1052 static ULONG WINAPI DataCache_IDataObject_Release(
1053 IDataObject* iface)
1055 _ICOM_THIS_From_IDataObject(DataCache, iface);
1057 return IUnknown_Release(this->outerUnknown);
1060 /************************************************************************
1061 * DataCache_GetData
1063 * Get Data from a source dataobject using format pformatetcIn->cfFormat
1064 * See Windows documentation for more details on GetData.
1065 * TODO: Currently only CF_METAFILEPICT is implemented
1067 static HRESULT WINAPI DataCache_GetData(
1068 IDataObject* iface,
1069 LPFORMATETC pformatetcIn,
1070 STGMEDIUM* pmedium)
1072 HRESULT hr = 0;
1073 HRESULT hrRet = E_UNEXPECTED;
1074 IPersistStorage *pPersistStorage = 0;
1075 IStorage *pStorage = 0;
1076 IStream *pStream = 0;
1077 OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
1078 HGLOBAL hGlobalMF = 0;
1079 void *mfBits = 0;
1080 PresentationDataHeader pdh;
1081 METAFILEPICT *mfPict;
1082 HMETAFILE hMetaFile = 0;
1084 if (pformatetcIn->cfFormat == CF_METAFILEPICT)
1086 /* Get the Persist Storage */
1088 hr = IDataObject_QueryInterface(iface, &IID_IPersistStorage, (void**)&pPersistStorage);
1090 if (hr != S_OK)
1091 goto cleanup;
1093 /* Create a doc file to copy the doc to a storage */
1095 hr = StgCreateDocfile(NULL, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &pStorage);
1097 if (hr != S_OK)
1098 goto cleanup;
1100 /* Save it to storage */
1102 hr = OleSave(pPersistStorage, pStorage, FALSE);
1104 if (hr != S_OK)
1105 goto cleanup;
1107 /* Open the Presentation data srteam */
1109 hr = IStorage_OpenStream(pStorage, name, 0, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &pStream);
1111 if (hr != S_OK)
1112 goto cleanup;
1114 /* Read the presentation header */
1116 hr = IStream_Read(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
1118 if (hr != S_OK)
1119 goto cleanup;
1121 mfBits = HeapAlloc(GetProcessHeap(), 0, pdh.dwSize);
1123 /* Read the Metafile bits */
1125 hr = IStream_Read(pStream, mfBits, pdh.dwSize, NULL);
1127 if (hr != S_OK)
1128 goto cleanup;
1130 /* Create the metafile and place it in the STGMEDIUM structure */
1132 hMetaFile = SetMetaFileBitsEx(pdh.dwSize, mfBits);
1134 hGlobalMF = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, sizeof(METAFILEPICT));
1135 mfPict = (METAFILEPICT *)GlobalLock(hGlobalMF);
1136 mfPict->hMF = hMetaFile;
1138 GlobalUnlock(hGlobalMF);
1140 pmedium->u.hGlobal = hGlobalMF;
1141 pmedium->tymed = TYMED_MFPICT;
1142 hrRet = S_OK;
1144 cleanup:
1146 if (mfBits)
1147 HeapFree(GetProcessHeap(), 0, mfBits);
1149 if (pStream)
1150 IStream_Release(pStream);
1152 if (pStorage)
1153 IStorage_Release(pStorage);
1155 if (pPersistStorage)
1156 IPersistStorage_Release(pPersistStorage);
1158 return hrRet;
1161 /* TODO: Other formats are not implemented */
1163 return E_NOTIMPL;
1166 static HRESULT WINAPI DataCache_GetDataHere(
1167 IDataObject* iface,
1168 LPFORMATETC pformatetc,
1169 STGMEDIUM* pmedium)
1171 FIXME("stub\n");
1172 return E_NOTIMPL;
1175 static HRESULT WINAPI DataCache_QueryGetData(
1176 IDataObject* iface,
1177 LPFORMATETC pformatetc)
1179 FIXME("stub\n");
1180 return E_NOTIMPL;
1183 /************************************************************************
1184 * DataCache_EnumFormatEtc (IDataObject)
1186 * The data cache doesn't implement this method.
1188 * See Windows documentation for more details on IDataObject methods.
1190 static HRESULT WINAPI DataCache_GetCanonicalFormatEtc(
1191 IDataObject* iface,
1192 LPFORMATETC pformatectIn,
1193 LPFORMATETC pformatetcOut)
1195 TRACE("()\n");
1196 return E_NOTIMPL;
1199 /************************************************************************
1200 * DataCache_IDataObject_SetData (IDataObject)
1202 * This method is delegated to the IOleCache2 implementation.
1204 * See Windows documentation for more details on IDataObject methods.
1206 static HRESULT WINAPI DataCache_IDataObject_SetData(
1207 IDataObject* iface,
1208 LPFORMATETC pformatetc,
1209 STGMEDIUM* pmedium,
1210 BOOL fRelease)
1212 IOleCache2* oleCache = NULL;
1213 HRESULT hres;
1215 TRACE("(%p, %p, %p, %d)\n", iface, pformatetc, pmedium, fRelease);
1217 hres = IDataObject_QueryInterface(iface, &IID_IOleCache2, (void**)&oleCache);
1219 if (FAILED(hres))
1220 return E_UNEXPECTED;
1222 hres = IOleCache2_SetData(oleCache, pformatetc, pmedium, fRelease);
1224 IOleCache2_Release(oleCache);
1226 return hres;
1229 /************************************************************************
1230 * DataCache_EnumFormatEtc (IDataObject)
1232 * The data cache doesn't implement this method.
1234 * See Windows documentation for more details on IDataObject methods.
1236 static HRESULT WINAPI DataCache_EnumFormatEtc(
1237 IDataObject* iface,
1238 DWORD dwDirection,
1239 IEnumFORMATETC** ppenumFormatEtc)
1241 TRACE("()\n");
1242 return E_NOTIMPL;
1245 /************************************************************************
1246 * DataCache_DAdvise (IDataObject)
1248 * The data cache doesn't support connections.
1250 * See Windows documentation for more details on IDataObject methods.
1252 static HRESULT WINAPI DataCache_DAdvise(
1253 IDataObject* iface,
1254 FORMATETC* pformatetc,
1255 DWORD advf,
1256 IAdviseSink* pAdvSink,
1257 DWORD* pdwConnection)
1259 TRACE("()\n");
1260 return OLE_E_ADVISENOTSUPPORTED;
1263 /************************************************************************
1264 * DataCache_DUnadvise (IDataObject)
1266 * The data cache doesn't support connections.
1268 * See Windows documentation for more details on IDataObject methods.
1270 static HRESULT WINAPI DataCache_DUnadvise(
1271 IDataObject* iface,
1272 DWORD dwConnection)
1274 TRACE("()\n");
1275 return OLE_E_NOCONNECTION;
1278 /************************************************************************
1279 * DataCache_EnumDAdvise (IDataObject)
1281 * The data cache doesn't support connections.
1283 * See Windows documentation for more details on IDataObject methods.
1285 static HRESULT WINAPI DataCache_EnumDAdvise(
1286 IDataObject* iface,
1287 IEnumSTATDATA** ppenumAdvise)
1289 TRACE("()\n");
1290 return OLE_E_ADVISENOTSUPPORTED;
1293 /*********************************************************
1294 * Method implementation for the IDataObject
1295 * part of the DataCache class.
1298 /************************************************************************
1299 * DataCache_IPersistStorage_QueryInterface (IUnknown)
1301 * See Windows documentation for more details on IUnknown methods.
1303 static HRESULT WINAPI DataCache_IPersistStorage_QueryInterface(
1304 IPersistStorage* iface,
1305 REFIID riid,
1306 void** ppvObject)
1308 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1310 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1313 /************************************************************************
1314 * DataCache_IPersistStorage_AddRef (IUnknown)
1316 * See Windows documentation for more details on IUnknown methods.
1318 static ULONG WINAPI DataCache_IPersistStorage_AddRef(
1319 IPersistStorage* iface)
1321 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1323 return IUnknown_AddRef(this->outerUnknown);
1326 /************************************************************************
1327 * DataCache_IPersistStorage_Release (IUnknown)
1329 * See Windows documentation for more details on IUnknown methods.
1331 static ULONG WINAPI DataCache_IPersistStorage_Release(
1332 IPersistStorage* iface)
1334 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1336 return IUnknown_Release(this->outerUnknown);
1339 /************************************************************************
1340 * DataCache_GetClassID (IPersistStorage)
1342 * The data cache doesn't implement this method.
1344 * See Windows documentation for more details on IPersistStorage methods.
1346 static HRESULT WINAPI DataCache_GetClassID(
1347 IPersistStorage* iface,
1348 CLSID* pClassID)
1350 TRACE("(%p, %p)\n", iface, pClassID);
1351 return E_NOTIMPL;
1354 /************************************************************************
1355 * DataCache_IsDirty (IPersistStorage)
1357 * Until we actully connect to a running object and retrieve new
1358 * information to it, we never get dirty.
1360 * See Windows documentation for more details on IPersistStorage methods.
1362 static HRESULT WINAPI DataCache_IsDirty(
1363 IPersistStorage* iface)
1365 TRACE("(%p)\n", iface);
1367 return S_FALSE;
1370 /************************************************************************
1371 * DataCache_InitNew (IPersistStorage)
1373 * The data cache implementation of IPersistStorage_InitNew simply stores
1374 * the storage pointer.
1376 * See Windows documentation for more details on IPersistStorage methods.
1378 static HRESULT WINAPI DataCache_InitNew(
1379 IPersistStorage* iface,
1380 IStorage* pStg)
1382 TRACE("(%p, %p)\n", iface, pStg);
1384 return DataCache_Load(iface, pStg);
1387 /************************************************************************
1388 * DataCache_Load (IPersistStorage)
1390 * The data cache implementation of IPersistStorage_Load doesn't
1391 * actually load anything. Instead, it holds on to the storage pointer
1392 * and it will load the presentation information when the
1393 * IDataObject_GetData or IViewObject2_Draw methods are called.
1395 * See Windows documentation for more details on IPersistStorage methods.
1397 static HRESULT WINAPI DataCache_Load(
1398 IPersistStorage* iface,
1399 IStorage* pStg)
1401 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1403 TRACE("(%p, %p)\n", iface, pStg);
1405 if (this->presentationStorage != NULL)
1407 IStorage_Release(this->presentationStorage);
1410 this->presentationStorage = pStg;
1412 if (this->presentationStorage != NULL)
1414 IStorage_AddRef(this->presentationStorage);
1416 return S_OK;
1419 /************************************************************************
1420 * DataCache_Save (IPersistStorage)
1422 * Until we actully connect to a running object and retrieve new
1423 * information to it, we never have to save anything. However, it is
1424 * our responsability to copy the information when saving to a new
1425 * storage.
1427 * See Windows documentation for more details on IPersistStorage methods.
1429 static HRESULT WINAPI DataCache_Save(
1430 IPersistStorage* iface,
1431 IStorage* pStg,
1432 BOOL fSameAsLoad)
1434 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1436 TRACE("(%p, %p, %d)\n", iface, pStg, fSameAsLoad);
1438 if ( (!fSameAsLoad) &&
1439 (this->presentationStorage!=NULL) )
1441 return IStorage_CopyTo(this->presentationStorage,
1443 NULL,
1444 NULL,
1445 pStg);
1448 return S_OK;
1451 /************************************************************************
1452 * DataCache_SaveCompleted (IPersistStorage)
1454 * This method is called to tell the cache to release the storage
1455 * pointer it's currentlu holding.
1457 * See Windows documentation for more details on IPersistStorage methods.
1459 static HRESULT WINAPI DataCache_SaveCompleted(
1460 IPersistStorage* iface,
1461 IStorage* pStgNew)
1463 TRACE("(%p, %p)\n", iface, pStgNew);
1465 if (pStgNew)
1468 * First, make sure we get our hands off any storage we have.
1471 DataCache_HandsOffStorage(iface);
1474 * Then, attach to the new storage.
1477 DataCache_Load(iface, pStgNew);
1480 return S_OK;
1483 /************************************************************************
1484 * DataCache_HandsOffStorage (IPersistStorage)
1486 * This method is called to tell the cache to release the storage
1487 * pointer it's currentlu holding.
1489 * See Windows documentation for more details on IPersistStorage methods.
1491 static HRESULT WINAPI DataCache_HandsOffStorage(
1492 IPersistStorage* iface)
1494 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1496 TRACE("(%p)\n", iface);
1498 if (this->presentationStorage != NULL)
1500 IStorage_Release(this->presentationStorage);
1501 this->presentationStorage = NULL;
1504 return S_OK;
1507 /*********************************************************
1508 * Method implementation for the IViewObject2
1509 * part of the DataCache class.
1512 /************************************************************************
1513 * DataCache_IViewObject2_QueryInterface (IUnknown)
1515 * See Windows documentation for more details on IUnknown methods.
1517 static HRESULT WINAPI DataCache_IViewObject2_QueryInterface(
1518 IViewObject2* iface,
1519 REFIID riid,
1520 void** ppvObject)
1522 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1524 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1527 /************************************************************************
1528 * DataCache_IViewObject2_AddRef (IUnknown)
1530 * See Windows documentation for more details on IUnknown methods.
1532 static ULONG WINAPI DataCache_IViewObject2_AddRef(
1533 IViewObject2* iface)
1535 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1537 return IUnknown_AddRef(this->outerUnknown);
1540 /************************************************************************
1541 * DataCache_IViewObject2_Release (IUnknown)
1543 * See Windows documentation for more details on IUnknown methods.
1545 static ULONG WINAPI DataCache_IViewObject2_Release(
1546 IViewObject2* iface)
1548 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1550 return IUnknown_Release(this->outerUnknown);
1553 /************************************************************************
1554 * DataCache_Draw (IViewObject2)
1556 * This method will draw the cached representation of the object
1557 * to the given device context.
1559 * See Windows documentation for more details on IViewObject2 methods.
1561 static HRESULT WINAPI DataCache_Draw(
1562 IViewObject2* iface,
1563 DWORD dwDrawAspect,
1564 LONG lindex,
1565 void* pvAspect,
1566 DVTARGETDEVICE* ptd,
1567 HDC hdcTargetDev,
1568 HDC hdcDraw,
1569 LPCRECTL lprcBounds,
1570 LPCRECTL lprcWBounds,
1571 BOOL (CALLBACK *pfnContinue)(ULONG_PTR dwContinue),
1572 DWORD dwContinue)
1574 PresentationDataHeader presData;
1575 HMETAFILE presMetafile = 0;
1576 HRESULT hres;
1578 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1580 TRACE("(%p, %lx, %ld, %p, %p, %p, %p, %p, %p, %lx)\n",
1581 iface,
1582 dwDrawAspect,
1583 lindex,
1584 pvAspect,
1585 hdcTargetDev,
1586 hdcDraw,
1587 lprcBounds,
1588 lprcWBounds,
1589 pfnContinue,
1590 dwContinue);
1593 * Sanity check
1595 if (lprcBounds==NULL)
1596 return E_INVALIDARG;
1599 * First, we need to retrieve the dimensions of the
1600 * image in the metafile.
1602 hres = DataCache_ReadPresentationData(this,
1603 dwDrawAspect,
1604 &presData);
1606 if (FAILED(hres))
1607 return hres;
1610 * Then, we can extract the metafile itself from the cached
1611 * data.
1613 * FIXME Unless it isn't a metafile. I think it could be any CF_XXX type,
1614 * particularly CF_DIB.
1616 presMetafile = DataCache_ReadPresMetafile(this,
1617 dwDrawAspect);
1620 * If we have a metafile, just draw baby...
1621 * We have to be careful not to modify the state of the
1622 * DC.
1624 if (presMetafile!=0)
1626 INT prevMapMode = SetMapMode(hdcDraw, MM_ANISOTROPIC);
1627 SIZE oldWindowExt;
1628 SIZE oldViewportExt;
1629 POINT oldViewportOrg;
1631 SetWindowExtEx(hdcDraw,
1632 presData.dwObjectExtentX,
1633 presData.dwObjectExtentY,
1634 &oldWindowExt);
1636 SetViewportExtEx(hdcDraw,
1637 lprcBounds->right - lprcBounds->left,
1638 lprcBounds->bottom - lprcBounds->top,
1639 &oldViewportExt);
1641 SetViewportOrgEx(hdcDraw,
1642 lprcBounds->left,
1643 lprcBounds->top,
1644 &oldViewportOrg);
1646 PlayMetaFile(hdcDraw, presMetafile);
1648 SetWindowExtEx(hdcDraw,
1649 oldWindowExt.cx,
1650 oldWindowExt.cy,
1651 NULL);
1653 SetViewportExtEx(hdcDraw,
1654 oldViewportExt.cx,
1655 oldViewportExt.cy,
1656 NULL);
1658 SetViewportOrgEx(hdcDraw,
1659 oldViewportOrg.x,
1660 oldViewportOrg.y,
1661 NULL);
1663 SetMapMode(hdcDraw, prevMapMode);
1665 DeleteMetaFile(presMetafile);
1668 return S_OK;
1671 static HRESULT WINAPI DataCache_GetColorSet(
1672 IViewObject2* iface,
1673 DWORD dwDrawAspect,
1674 LONG lindex,
1675 void* pvAspect,
1676 DVTARGETDEVICE* ptd,
1677 HDC hicTargetDevice,
1678 LOGPALETTE** ppColorSet)
1680 FIXME("stub\n");
1681 return E_NOTIMPL;
1684 static HRESULT WINAPI DataCache_Freeze(
1685 IViewObject2* iface,
1686 DWORD dwDrawAspect,
1687 LONG lindex,
1688 void* pvAspect,
1689 DWORD* pdwFreeze)
1691 FIXME("stub\n");
1692 return E_NOTIMPL;
1695 static HRESULT WINAPI DataCache_Unfreeze(
1696 IViewObject2* iface,
1697 DWORD dwFreeze)
1699 FIXME("stub\n");
1700 return E_NOTIMPL;
1703 /************************************************************************
1704 * DataCache_SetAdvise (IViewObject2)
1706 * This sets-up an advisory sink with the data cache. When the object's
1707 * view changes, this sink is called.
1709 * See Windows documentation for more details on IViewObject2 methods.
1711 static HRESULT WINAPI DataCache_SetAdvise(
1712 IViewObject2* iface,
1713 DWORD aspects,
1714 DWORD advf,
1715 IAdviseSink* pAdvSink)
1717 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1719 TRACE("(%p, %lx, %lx, %p)\n", iface, aspects, advf, pAdvSink);
1722 * A call to this function removes the previous sink
1724 if (this->sinkInterface != NULL)
1726 IAdviseSink_Release(this->sinkInterface);
1727 this->sinkInterface = NULL;
1728 this->sinkAspects = 0;
1729 this->sinkAdviseFlag = 0;
1733 * Now, setup the new one.
1735 if (pAdvSink!=NULL)
1737 this->sinkInterface = pAdvSink;
1738 this->sinkAspects = aspects;
1739 this->sinkAdviseFlag = advf;
1741 IAdviseSink_AddRef(this->sinkInterface);
1745 * When the ADVF_PRIMEFIRST flag is set, we have to advise the
1746 * sink immediately.
1748 if (advf & ADVF_PRIMEFIRST)
1750 DataCache_FireOnViewChange(this,
1751 DVASPECT_CONTENT,
1752 -1);
1755 return S_OK;
1758 /************************************************************************
1759 * DataCache_GetAdvise (IViewObject2)
1761 * This method queries the current state of the advise sink
1762 * installed on the data cache.
1764 * See Windows documentation for more details on IViewObject2 methods.
1766 static HRESULT WINAPI DataCache_GetAdvise(
1767 IViewObject2* iface,
1768 DWORD* pAspects,
1769 DWORD* pAdvf,
1770 IAdviseSink** ppAdvSink)
1772 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1774 TRACE("(%p, %p, %p, %p)\n", iface, pAspects, pAdvf, ppAdvSink);
1777 * Just copy all the requested values.
1779 if (pAspects!=NULL)
1780 *pAspects = this->sinkAspects;
1782 if (pAdvf!=NULL)
1783 *pAdvf = this->sinkAdviseFlag;
1785 if (ppAdvSink!=NULL)
1787 IAdviseSink_QueryInterface(this->sinkInterface,
1788 &IID_IAdviseSink,
1789 (void**)ppAdvSink);
1792 return S_OK;
1795 /************************************************************************
1796 * DataCache_GetExtent (IViewObject2)
1798 * This method retrieves the "natural" size of this cached object.
1800 * See Windows documentation for more details on IViewObject2 methods.
1802 static HRESULT WINAPI DataCache_GetExtent(
1803 IViewObject2* iface,
1804 DWORD dwDrawAspect,
1805 LONG lindex,
1806 DVTARGETDEVICE* ptd,
1807 LPSIZEL lpsizel)
1809 PresentationDataHeader presData;
1810 HRESULT hres = E_FAIL;
1812 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1814 TRACE("(%p, %lx, %ld, %p, %p)\n",
1815 iface, dwDrawAspect, lindex, ptd, lpsizel);
1818 * Sanity check
1820 if (lpsizel==NULL)
1821 return E_POINTER;
1824 * Initialize the out parameter.
1826 lpsizel->cx = 0;
1827 lpsizel->cy = 0;
1830 * This flag should be set to -1.
1832 if (lindex!=-1)
1833 FIXME("Unimplemented flag lindex = %ld\n", lindex);
1836 * Right now, we support only the callback from
1837 * the default handler.
1839 if (ptd!=NULL)
1840 FIXME("Unimplemented ptd = %p\n", ptd);
1843 * Get the presentation information from the
1844 * cache.
1846 hres = DataCache_ReadPresentationData(this,
1847 dwDrawAspect,
1848 &presData);
1850 if (SUCCEEDED(hres))
1852 lpsizel->cx = presData.dwObjectExtentX;
1853 lpsizel->cy = presData.dwObjectExtentY;
1857 * This method returns OLE_E_BLANK when it fails.
1859 if (FAILED(hres))
1860 hres = OLE_E_BLANK;
1862 return hres;
1866 /*********************************************************
1867 * Method implementation for the IOleCache2
1868 * part of the DataCache class.
1871 /************************************************************************
1872 * DataCache_IOleCache2_QueryInterface (IUnknown)
1874 * See Windows documentation for more details on IUnknown methods.
1876 static HRESULT WINAPI DataCache_IOleCache2_QueryInterface(
1877 IOleCache2* iface,
1878 REFIID riid,
1879 void** ppvObject)
1881 _ICOM_THIS_From_IOleCache2(DataCache, iface);
1883 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1886 /************************************************************************
1887 * DataCache_IOleCache2_AddRef (IUnknown)
1889 * See Windows documentation for more details on IUnknown methods.
1891 static ULONG WINAPI DataCache_IOleCache2_AddRef(
1892 IOleCache2* iface)
1894 _ICOM_THIS_From_IOleCache2(DataCache, iface);
1896 return IUnknown_AddRef(this->outerUnknown);
1899 /************************************************************************
1900 * DataCache_IOleCache2_Release (IUnknown)
1902 * See Windows documentation for more details on IUnknown methods.
1904 static ULONG WINAPI DataCache_IOleCache2_Release(
1905 IOleCache2* iface)
1907 _ICOM_THIS_From_IOleCache2(DataCache, iface);
1909 return IUnknown_Release(this->outerUnknown);
1912 static HRESULT WINAPI DataCache_Cache(
1913 IOleCache2* iface,
1914 FORMATETC* pformatetc,
1915 DWORD advf,
1916 DWORD* pdwConnection)
1918 FIXME("stub\n");
1919 return E_NOTIMPL;
1922 static HRESULT WINAPI DataCache_Uncache(
1923 IOleCache2* iface,
1924 DWORD dwConnection)
1926 FIXME("stub\n");
1927 return E_NOTIMPL;
1930 static HRESULT WINAPI DataCache_EnumCache(
1931 IOleCache2* iface,
1932 IEnumSTATDATA** ppenumSTATDATA)
1934 FIXME("stub\n");
1935 return E_NOTIMPL;
1938 static HRESULT WINAPI DataCache_InitCache(
1939 IOleCache2* iface,
1940 IDataObject* pDataObject)
1942 FIXME("stub\n");
1943 return E_NOTIMPL;
1946 static HRESULT WINAPI DataCache_IOleCache2_SetData(
1947 IOleCache2* iface,
1948 FORMATETC* pformatetc,
1949 STGMEDIUM* pmedium,
1950 BOOL fRelease)
1952 FIXME("stub\n");
1953 return E_NOTIMPL;
1956 static HRESULT WINAPI DataCache_UpdateCache(
1957 IOleCache2* iface,
1958 LPDATAOBJECT pDataObject,
1959 DWORD grfUpdf,
1960 LPVOID pReserved)
1962 FIXME("stub\n");
1963 return E_NOTIMPL;
1966 static HRESULT WINAPI DataCache_DiscardCache(
1967 IOleCache2* iface,
1968 DWORD dwDiscardOptions)
1970 FIXME("stub\n");
1971 return E_NOTIMPL;
1975 /*********************************************************
1976 * Method implementation for the IOleCacheControl
1977 * part of the DataCache class.
1980 /************************************************************************
1981 * DataCache_IOleCacheControl_QueryInterface (IUnknown)
1983 * See Windows documentation for more details on IUnknown methods.
1985 static HRESULT WINAPI DataCache_IOleCacheControl_QueryInterface(
1986 IOleCacheControl* iface,
1987 REFIID riid,
1988 void** ppvObject)
1990 _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
1992 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1995 /************************************************************************
1996 * DataCache_IOleCacheControl_AddRef (IUnknown)
1998 * See Windows documentation for more details on IUnknown methods.
2000 static ULONG WINAPI DataCache_IOleCacheControl_AddRef(
2001 IOleCacheControl* iface)
2003 _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
2005 return IUnknown_AddRef(this->outerUnknown);
2008 /************************************************************************
2009 * DataCache_IOleCacheControl_Release (IUnknown)
2011 * See Windows documentation for more details on IUnknown methods.
2013 static ULONG WINAPI DataCache_IOleCacheControl_Release(
2014 IOleCacheControl* iface)
2016 _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
2018 return IUnknown_Release(this->outerUnknown);
2021 static HRESULT WINAPI DataCache_OnRun(
2022 IOleCacheControl* iface,
2023 LPDATAOBJECT pDataObject)
2025 FIXME("stub\n");
2026 return E_NOTIMPL;
2029 static HRESULT WINAPI DataCache_OnStop(
2030 IOleCacheControl* iface)
2032 FIXME("stub\n");
2033 return E_NOTIMPL;