source: trunk/src/ole32/datacache.c@ 6496

Last change on this file since 6496 was 5602, checked in by sandervl, 24 years ago

resync with Wine 20010418

File size: 53.2 KB
Line 
1/*
2 * OLE 2 Data cache
3 *
4 * Copyright 1999 Francis Beaudet
5 * Copyright 2000 Abey George
6 *
7 * NOTES:
8 * The OLE2 data cache supports a whole whack of
9 * interfaces including:
10 * IDataObject, IPersistStorage, IViewObject2,
11 * IOleCache2 and IOleCacheControl.
12 *
13 * Most of the implementation details are taken from: Inside OLE
14 * second edition by Kraig Brockschmidt,
15 *
16 * NOTES
17 * - This implementation of the datacache will let your application
18 * load documents that have embedded OLE objects in them and it will
19 * also retrieve the metafile representation of those objects.
20 * - This implementation of the datacache will also allow your
21 * application to save new documents with OLE objects in them.
22 * - The main thing that it doesn't do is allow you to activate
23 * or modify the OLE objects in any way.
24 * - I haven't found any good documentation on the real usage of
25 * the streams created by the data cache. In particular, How to
26 * determine what the XXX stands for in the stream name
27 * "\002OlePresXXX". It appears to just be a counter.
28 * - Also, I don't know the real content of the presentation stream
29 * header. I was able to figure-out where the extent of the object
30 * was stored and the aspect, but that's about it.
31 */
32#include <assert.h>
33#include <string.h>
34#include "windef.h"
35#include "winbase.h"
36#include "wingdi.h"
37#include "winuser.h"
38#include "winerror.h"
39#include "wine/obj_base.h"
40#include "wine/obj_misc.h"
41#include "wine/obj_storage.h"
42#include "wine/obj_moniker.h"
43#include "wine/obj_dataobject.h"
44#include "wine/obj_oleview.h"
45#include "wine/obj_cache.h"
46#include "wine/unicode.h"
47#include "ole2.h"
48#include "debugtools.h"
49
50DEFAULT_DEBUG_CHANNEL(ole);
51
52/****************************************************************************
53 * PresentationDataHeader
54 *
55 * This structure represents the header of the \002OlePresXXX stream in
56 * the OLE object strorage.
57 *
58 * Most fields are still unknown.
59 */
60typedef struct PresentationDataHeader
61{
62 DWORD unknown1; /* -1 */
63 DWORD unknown2; /* 3, possibly CF_METAFILEPICT */
64 DWORD unknown3; /* 4, possibly TYMED_ISTREAM */
65 DVASPECT dvAspect;
66 DWORD unknown5; /* -1 */
67
68 DWORD unknown6;
69 DWORD unknown7; /* 0 */
70 DWORD dwObjectExtentX;
71 DWORD dwObjectExtentY;
72 DWORD dwSize;
73} PresentationDataHeader;
74
75/****************************************************************************
76 * DataCache
77 */
78struct DataCache
79{
80 /*
81 * List all interface VTables here
82 */
83 ICOM_VTABLE(IDataObject)* lpvtbl1;
84 ICOM_VTABLE(IUnknown)* lpvtbl2;
85 ICOM_VTABLE(IPersistStorage)* lpvtbl3;
86 ICOM_VTABLE(IViewObject2)* lpvtbl4;
87 ICOM_VTABLE(IOleCache2)* lpvtbl5;
88 ICOM_VTABLE(IOleCacheControl)* lpvtbl6;
89
90 /*
91 * Reference count of this object
92 */
93 ULONG ref;
94
95 /*
96 * IUnknown implementation of the outer object.
97 */
98 IUnknown* outerUnknown;
99
100 /*
101 * This storage pointer is set through a call to
102 * IPersistStorage_Load. This is where the visual
103 * representation of the object is stored.
104 */
105 IStorage* presentationStorage;
106
107 /*
108 * The user of this object can setup ONE advise sink
109 * connection with the object. These parameters describe
110 * that connection.
111 */
112 DWORD sinkAspects;
113 DWORD sinkAdviseFlag;
114 IAdviseSink* sinkInterface;
115
116};
117
118typedef struct DataCache DataCache;
119
120/*
121 * Here, I define utility macros to help with the casting of the
122 * "this" parameter.
123 * There is a version to accomodate all of the VTables implemented
124 * by this object.
125 */
126#define _ICOM_THIS_From_IDataObject(class,name) class* this = (class*)name;
127#define _ICOM_THIS_From_NDIUnknown(class, name) class* this = (class*)(((char*)name)-sizeof(void*));
128#define _ICOM_THIS_From_IPersistStorage(class, name) class* this = (class*)(((char*)name)-2*sizeof(void*));
129#define _ICOM_THIS_From_IViewObject2(class, name) class* this = (class*)(((char*)name)-3*sizeof(void*));
130#define _ICOM_THIS_From_IOleCache2(class, name) class* this = (class*)(((char*)name)-4*sizeof(void*));
131#define _ICOM_THIS_From_IOleCacheControl(class, name) class* this = (class*)(((char*)name)-5*sizeof(void*));
132
133/*
134 * Prototypes for the methods of the DataCache class.
135 */
136static DataCache* DataCache_Construct(REFCLSID clsid,
137 LPUNKNOWN pUnkOuter);
138static void DataCache_Destroy(DataCache* ptrToDestroy);
139static HRESULT DataCache_ReadPresentationData(DataCache* this,
140 DWORD drawAspect,
141 PresentationDataHeader* header);
142static HRESULT DataCache_OpenPresStream(DataCache *this,
143 DWORD drawAspect,
144 IStream **pStm);
145static HMETAFILE DataCache_ReadPresMetafile(DataCache* this,
146 DWORD drawAspect);
147static void DataCache_FireOnViewChange(DataCache* this,
148 DWORD aspect,
149 LONG lindex);
150
151/*
152 * Prototypes for the methods of the DataCache class
153 * that implement non delegating IUnknown methods.
154 */
155static HRESULT WINAPI DataCache_NDIUnknown_QueryInterface(
156 IUnknown* iface,
157 REFIID riid,
158 void** ppvObject);
159static ULONG WINAPI DataCache_NDIUnknown_AddRef(
160 IUnknown* iface);
161static ULONG WINAPI DataCache_NDIUnknown_Release(
162 IUnknown* iface);
163
164/*
165 * Prototypes for the methods of the DataCache class
166 * that implement IDataObject methods.
167 */
168static HRESULT WINAPI DataCache_IDataObject_QueryInterface(
169 IDataObject* iface,
170 REFIID riid,
171 void** ppvObject);
172static ULONG WINAPI DataCache_IDataObject_AddRef(
173 IDataObject* iface);
174static ULONG WINAPI DataCache_IDataObject_Release(
175 IDataObject* iface);
176static HRESULT WINAPI DataCache_GetData(
177 IDataObject* iface,
178 LPFORMATETC pformatetcIn,
179 STGMEDIUM* pmedium);
180static HRESULT WINAPI DataCache_GetDataHere(
181 IDataObject* iface,
182 LPFORMATETC pformatetc,
183 STGMEDIUM* pmedium);
184static HRESULT WINAPI DataCache_QueryGetData(
185 IDataObject* iface,
186 LPFORMATETC pformatetc);
187static HRESULT WINAPI DataCache_GetCanonicalFormatEtc(
188 IDataObject* iface,
189 LPFORMATETC pformatectIn,
190 LPFORMATETC pformatetcOut);
191static HRESULT WINAPI DataCache_IDataObject_SetData(
192 IDataObject* iface,
193 LPFORMATETC pformatetc,
194 STGMEDIUM* pmedium,
195 BOOL fRelease);
196static HRESULT WINAPI DataCache_EnumFormatEtc(
197 IDataObject* iface,
198 DWORD dwDirection,
199 IEnumFORMATETC** ppenumFormatEtc);
200static HRESULT WINAPI DataCache_DAdvise(
201 IDataObject* iface,
202 FORMATETC* pformatetc,
203 DWORD advf,
204 IAdviseSink* pAdvSink,
205 DWORD* pdwConnection);
206static HRESULT WINAPI DataCache_DUnadvise(
207 IDataObject* iface,
208 DWORD dwConnection);
209static HRESULT WINAPI DataCache_EnumDAdvise(
210 IDataObject* iface,
211 IEnumSTATDATA** ppenumAdvise);
212
213/*
214 * Prototypes for the methods of the DataCache class
215 * that implement IPersistStorage methods.
216 */
217static HRESULT WINAPI DataCache_IPersistStorage_QueryInterface(
218 IPersistStorage* iface,
219 REFIID riid,
220 void** ppvObject);
221static ULONG WINAPI DataCache_IPersistStorage_AddRef(
222 IPersistStorage* iface);
223static ULONG WINAPI DataCache_IPersistStorage_Release(
224 IPersistStorage* iface);
225static HRESULT WINAPI DataCache_GetClassID(
226 IPersistStorage* iface,
227 CLSID* pClassID);
228static HRESULT WINAPI DataCache_IsDirty(
229 IPersistStorage* iface);
230static HRESULT WINAPI DataCache_InitNew(
231 IPersistStorage* iface,
232 IStorage* pStg);
233static HRESULT WINAPI DataCache_Load(
234 IPersistStorage* iface,
235 IStorage* pStg);
236static HRESULT WINAPI DataCache_Save(
237 IPersistStorage* iface,
238 IStorage* pStg,
239 BOOL fSameAsLoad);
240static HRESULT WINAPI DataCache_SaveCompleted(
241 IPersistStorage* iface,
242 IStorage* pStgNew);
243static HRESULT WINAPI DataCache_HandsOffStorage(
244 IPersistStorage* iface);
245
246/*
247 * Prototypes for the methods of the DataCache class
248 * that implement IViewObject2 methods.
249 */
250static HRESULT WINAPI DataCache_IViewObject2_QueryInterface(
251 IViewObject2* iface,
252 REFIID riid,
253 void** ppvObject);
254static ULONG WINAPI DataCache_IViewObject2_AddRef(
255 IViewObject2* iface);
256static ULONG WINAPI DataCache_IViewObject2_Release(
257 IViewObject2* iface);
258static HRESULT WINAPI DataCache_Draw(
259 IViewObject2* iface,
260 DWORD dwDrawAspect,
261 LONG lindex,
262 void* pvAspect,
263 DVTARGETDEVICE* ptd,
264 HDC hdcTargetDev,
265 HDC hdcDraw,
266 LPCRECTL lprcBounds,
267 LPCRECTL lprcWBounds,
268 IVO_ContCallback pfnContinue,
269 DWORD dwContinue);
270static HRESULT WINAPI DataCache_GetColorSet(
271 IViewObject2* iface,
272 DWORD dwDrawAspect,
273 LONG lindex,
274 void* pvAspect,
275 DVTARGETDEVICE* ptd,
276 HDC hicTargetDevice,
277 LOGPALETTE** ppColorSet);
278static HRESULT WINAPI DataCache_Freeze(
279 IViewObject2* iface,
280 DWORD dwDrawAspect,
281 LONG lindex,
282 void* pvAspect,
283 DWORD* pdwFreeze);
284static HRESULT WINAPI DataCache_Unfreeze(
285 IViewObject2* iface,
286 DWORD dwFreeze);
287static HRESULT WINAPI DataCache_SetAdvise(
288 IViewObject2* iface,
289 DWORD aspects,
290 DWORD advf,
291 IAdviseSink* pAdvSink);
292static HRESULT WINAPI DataCache_GetAdvise(
293 IViewObject2* iface,
294 DWORD* pAspects,
295 DWORD* pAdvf,
296 IAdviseSink** ppAdvSink);
297static HRESULT WINAPI DataCache_GetExtent(
298 IViewObject2* iface,
299 DWORD dwDrawAspect,
300 LONG lindex,
301 DVTARGETDEVICE* ptd,
302 LPSIZEL lpsizel);
303
304/*
305 * Prototypes for the methods of the DataCache class
306 * that implement IOleCache2 methods.
307 */
308static HRESULT WINAPI DataCache_IOleCache2_QueryInterface(
309 IOleCache2* iface,
310 REFIID riid,
311 void** ppvObject);
312static ULONG WINAPI DataCache_IOleCache2_AddRef(
313 IOleCache2* iface);
314static ULONG WINAPI DataCache_IOleCache2_Release(
315 IOleCache2* iface);
316static HRESULT WINAPI DataCache_Cache(
317 IOleCache2* iface,
318 FORMATETC* pformatetc,
319 DWORD advf,
320 DWORD* pdwConnection);
321static HRESULT WINAPI DataCache_Uncache(
322 IOleCache2* iface,
323 DWORD dwConnection);
324static HRESULT WINAPI DataCache_EnumCache(
325 IOleCache2* iface,
326 IEnumSTATDATA** ppenumSTATDATA);
327static HRESULT WINAPI DataCache_InitCache(
328 IOleCache2* iface,
329 IDataObject* pDataObject);
330static HRESULT WINAPI DataCache_IOleCache2_SetData(
331 IOleCache2* iface,
332 FORMATETC* pformatetc,
333 STGMEDIUM* pmedium,
334 BOOL fRelease);
335static HRESULT WINAPI DataCache_UpdateCache(
336 IOleCache2* iface,
337 LPDATAOBJECT pDataObject,
338 DWORD grfUpdf,
339 LPVOID pReserved);
340static HRESULT WINAPI DataCache_DiscardCache(
341 IOleCache2* iface,
342 DWORD dwDiscardOptions);
343
344/*
345 * Prototypes for the methods of the DataCache class
346 * that implement IOleCacheControl methods.
347 */
348static HRESULT WINAPI DataCache_IOleCacheControl_QueryInterface(
349 IOleCacheControl* iface,
350 REFIID riid,
351 void** ppvObject);
352static ULONG WINAPI DataCache_IOleCacheControl_AddRef(
353 IOleCacheControl* iface);
354static ULONG WINAPI DataCache_IOleCacheControl_Release(
355 IOleCacheControl* iface);
356static HRESULT WINAPI DataCache_OnRun(
357 IOleCacheControl* iface,
358 LPDATAOBJECT pDataObject);
359static HRESULT WINAPI DataCache_OnStop(
360 IOleCacheControl* iface);
361
362/*
363 * Virtual function tables for the DataCache class.
364 */
365static ICOM_VTABLE(IUnknown) DataCache_NDIUnknown_VTable =
366{
367 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
368 DataCache_NDIUnknown_QueryInterface,
369 DataCache_NDIUnknown_AddRef,
370 DataCache_NDIUnknown_Release
371};
372
373static ICOM_VTABLE(IDataObject) DataCache_IDataObject_VTable =
374{
375 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
376 DataCache_IDataObject_QueryInterface,
377 DataCache_IDataObject_AddRef,
378 DataCache_IDataObject_Release,
379 DataCache_GetData,
380 DataCache_GetDataHere,
381 DataCache_QueryGetData,
382 DataCache_GetCanonicalFormatEtc,
383 DataCache_IDataObject_SetData,
384 DataCache_EnumFormatEtc,
385 DataCache_DAdvise,
386 DataCache_DUnadvise,
387 DataCache_EnumDAdvise
388};
389
390static ICOM_VTABLE(IPersistStorage) DataCache_IPersistStorage_VTable =
391{
392 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
393 DataCache_IPersistStorage_QueryInterface,
394 DataCache_IPersistStorage_AddRef,
395 DataCache_IPersistStorage_Release,
396 DataCache_GetClassID,
397 DataCache_IsDirty,
398 DataCache_InitNew,
399 DataCache_Load,
400 DataCache_Save,
401 DataCache_SaveCompleted,
402 DataCache_HandsOffStorage
403};
404
405static ICOM_VTABLE(IViewObject2) DataCache_IViewObject2_VTable =
406{
407 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
408 DataCache_IViewObject2_QueryInterface,
409 DataCache_IViewObject2_AddRef,
410 DataCache_IViewObject2_Release,
411 DataCache_Draw,
412 DataCache_GetColorSet,
413 DataCache_Freeze,
414 DataCache_Unfreeze,
415 DataCache_SetAdvise,
416 DataCache_GetAdvise,
417 DataCache_GetExtent
418};
419
420static ICOM_VTABLE(IOleCache2) DataCache_IOleCache2_VTable =
421{
422 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
423 DataCache_IOleCache2_QueryInterface,
424 DataCache_IOleCache2_AddRef,
425 DataCache_IOleCache2_Release,
426 DataCache_Cache,
427 DataCache_Uncache,
428 DataCache_EnumCache,
429 DataCache_InitCache,
430 DataCache_IOleCache2_SetData,
431 DataCache_UpdateCache,
432 DataCache_DiscardCache
433};
434
435static ICOM_VTABLE(IOleCacheControl) DataCache_IOleCacheControl_VTable =
436{
437 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
438 DataCache_IOleCacheControl_QueryInterface,
439 DataCache_IOleCacheControl_AddRef,
440 DataCache_IOleCacheControl_Release,
441 DataCache_OnRun,
442 DataCache_OnStop
443};
444
445/******************************************************************************
446 * CreateDataCache [OLE32.54]
447 */
448HRESULT WINAPI CreateDataCache(
449 LPUNKNOWN pUnkOuter,
450 REFCLSID rclsid,
451 REFIID riid,
452 LPVOID* ppvObj)
453{
454 DataCache* newCache = NULL;
455 HRESULT hr = S_OK;
456
457 TRACE("(%s, %p, %s, %p)\n", debugstr_guid(rclsid), pUnkOuter, debugstr_guid(riid), ppvObj);
458
459 /*
460 * Sanity check
461 */
462 if (ppvObj==0)
463 return E_POINTER;
464
465 *ppvObj = 0;
466
467 /*
468 * If this cache is constructed for aggregation, make sure
469 * the caller is requesting the IUnknown interface.
470 * This is necessary because it's the only time the non-delegating
471 * IUnknown pointer can be returned to the outside.
472 */
473 if ( (pUnkOuter!=NULL) &&
474 (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) != 0) )
475 return CLASS_E_NOAGGREGATION;
476
477 /*
478 * Try to construct a new instance of the class.
479 */
480 newCache = DataCache_Construct(rclsid,
481 pUnkOuter);
482
483 if (newCache == 0)
484 return E_OUTOFMEMORY;
485
486 /*
487 * Make sure it supports the interface required by the caller.
488 */
489 hr = IUnknown_QueryInterface((IUnknown*)&(newCache->lpvtbl2), riid, ppvObj);
490
491 /*
492 * Release the reference obtained in the constructor. If
493 * the QueryInterface was unsuccessful, it will free the class.
494 */
495 IUnknown_Release((IUnknown*)&(newCache->lpvtbl2));
496
497 return hr;
498}
499
500/*********************************************************
501 * Method implementation for DataCache class.
502 */
503static DataCache* DataCache_Construct(
504 REFCLSID clsid,
505 LPUNKNOWN pUnkOuter)
506{
507 DataCache* newObject = 0;
508
509 /*
510 * Allocate space for the object.
511 */
512 newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(DataCache));
513
514 if (newObject==0)
515 return newObject;
516
517 /*
518 * Initialize the virtual function table.
519 */
520 newObject->lpvtbl1 = &DataCache_IDataObject_VTable;
521 newObject->lpvtbl2 = &DataCache_NDIUnknown_VTable;
522 newObject->lpvtbl3 = &DataCache_IPersistStorage_VTable;
523 newObject->lpvtbl4 = &DataCache_IViewObject2_VTable;
524 newObject->lpvtbl5 = &DataCache_IOleCache2_VTable;
525 newObject->lpvtbl6 = &DataCache_IOleCacheControl_VTable;
526
527 /*
528 * Start with one reference count. The caller of this function
529 * must release the interface pointer when it is done.
530 */
531 newObject->ref = 1;
532
533 /*
534 * Initialize the outer unknown
535 * We don't keep a reference on the outer unknown since, the way
536 * aggregation works, our lifetime is at least as large as it's
537 * lifetime.
538 */
539 if (pUnkOuter==NULL)
540 pUnkOuter = (IUnknown*)&(newObject->lpvtbl2);
541
542 newObject->outerUnknown = pUnkOuter;
543
544 /*
545 * Initialize the other members of the structure.
546 */
547 newObject->presentationStorage = NULL;
548 newObject->sinkAspects = 0;
549 newObject->sinkAdviseFlag = 0;
550 newObject->sinkInterface = 0;
551
552 return newObject;
553}
554
555static void DataCache_Destroy(
556 DataCache* ptrToDestroy)
557{
558 TRACE("()\n");
559
560 if (ptrToDestroy->sinkInterface != NULL)
561 {
562 IAdviseSink_Release(ptrToDestroy->sinkInterface);
563 ptrToDestroy->sinkInterface = NULL;
564 }
565
566 if (ptrToDestroy->presentationStorage != NULL)
567 {
568 IStorage_Release(ptrToDestroy->presentationStorage);
569 ptrToDestroy->presentationStorage = NULL;
570 }
571
572 /*
573 * Free the datacache pointer.
574 */
575 HeapFree(GetProcessHeap(), 0, ptrToDestroy);
576}
577
578/************************************************************************
579 * DataCache_ReadPresentationData
580 *
581 * This method will read information for the requested presentation
582 * into the given structure.
583 *
584 * Param:
585 * this - Pointer to the DataCache object
586 * drawAspect - The aspect of the object that we wish to draw.
587 * header - The structure containing information about this
588 * aspect of the object.
589 */
590static HRESULT DataCache_ReadPresentationData(
591 DataCache* this,
592 DWORD drawAspect,
593 PresentationDataHeader* header)
594{
595 IStream* presStream = NULL;
596 HRESULT hres;
597
598 /*
599 * Open the presentation stream.
600 */
601 hres = DataCache_OpenPresStream(
602 this,
603 drawAspect,
604 &presStream);
605
606 if (FAILED(hres))
607 return hres;
608
609 /*
610 * Read the header.
611 */
612
613 hres = IStream_Read(
614 presStream,
615 header,
616 sizeof(PresentationDataHeader),
617 NULL);
618
619 /*
620 * Cleanup.
621 */
622 IStream_Release(presStream);
623
624 /*
625 * We don't want to propagate any other error
626 * code than a failure.
627 */
628 if (hres!=S_OK)
629 hres = E_FAIL;
630
631 return hres;
632}
633
634/************************************************************************
635 * DataCache_FireOnViewChange
636 *
637 * This method will fire an OnViewChange notification to the advise
638 * sink registered with the datacache.
639 *
640 * See IAdviseSink::OnViewChange for more details.
641 */
642static void DataCache_FireOnViewChange(
643 DataCache* this,
644 DWORD aspect,
645 LONG lindex)
646{
647 TRACE("(%p, %lx, %ld)\n", this, aspect, lindex);
648
649 /*
650 * The sink supplies a filter when it registers
651 * we make sure we only send the notifications when that
652 * filter matches.
653 */
654 if ((this->sinkAspects & aspect) != 0)
655 {
656 if (this->sinkInterface != NULL)
657 {
658 IAdviseSink_OnViewChange(this->sinkInterface,
659 aspect,
660 lindex);
661
662 /*
663 * Some sinks want to be unregistered automatically when
664 * the first notification goes out.
665 */
666 if ( (this->sinkAdviseFlag & ADVF_ONLYONCE) != 0)
667 {
668 IAdviseSink_Release(this->sinkInterface);
669
670 this->sinkInterface = NULL;
671 this->sinkAspects = 0;
672 this->sinkAdviseFlag = 0;
673 }
674 }
675 }
676}
677
678/* Helper for DataCache_OpenPresStream */
679static BOOL DataCache_IsPresentationStream(const STATSTG *elem)
680{
681 /* The presentation streams have names of the form "\002OlePresXXX",
682 * where XXX goes from 000 to 999. */
683 static const WCHAR OlePres[] = { 2,'O','l','e','P','r','e','s' };
684
685 LPCWSTR name = elem->pwcsName;
686
687 return (elem->type == STGTY_STREAM)
688 && (elem->cbSize.s.LowPart >= sizeof(PresentationDataHeader))
689 && (strlenW(name) == 11)
690 && (strncmpW(name, OlePres, 8) == 0)
691 && (name[8] >= '0') && (name[8] <= '9')
692 && (name[9] >= '0') && (name[9] <= '9')
693 && (name[10] >= '0') && (name[10] <= '9');
694}
695
696/************************************************************************
697 * DataCache_OpenPresStream
698 *
699 * This method will find the stream for the given presentation. It makes
700 * no attempt at fallback.
701 *
702 * Param:
703 * this - Pointer to the DataCache object
704 * drawAspect - The aspect of the object that we wish to draw.
705 * pStm - A returned stream. It points to the beginning of the
706 * - presentation data, including the header.
707 *
708 * Errors:
709 * S_OK The requested stream has been opened.
710 * OLE_E_BLANK The requested stream could not be found.
711 * Quite a few others I'm too lazy to map correctly.
712 *
713 * Notes:
714 * Algorithm: Scan the elements of the presentation storage, looking
715 * for presentation streams. For each presentation stream,
716 * load the header and check to see if the aspect maches.
717 *
718 * If a fallback is desired, just opening the first presentation stream
719 * is a possibility.
720 */
721static HRESULT DataCache_OpenPresStream(
722 DataCache *this,
723 DWORD drawAspect,
724 IStream **ppStm)
725{
726 STATSTG elem;
727 IEnumSTATSTG *pEnum;
728 HRESULT hr;
729
730 if (!ppStm) return E_POINTER;
731
732 hr = IStorage_EnumElements(this->presentationStorage, 0, NULL, 0, &pEnum);
733 if (FAILED(hr)) return hr;
734
735 while ((hr = IEnumSTATSTG_Next(pEnum, 1, &elem, NULL)) == S_OK)
736 {
737 if (DataCache_IsPresentationStream(&elem))
738 {
739 IStream *pStm;
740
741 hr = IStorage_OpenStream(this->presentationStorage, elem.pwcsName,
742 NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0,
743 &pStm);
744 if (SUCCEEDED(hr))
745 {
746 PresentationDataHeader header;
747 ULONG actual_read;
748
749 hr = IStream_Read(pStm, &header, sizeof(header), &actual_read);
750
751 /* can't use SUCCEEDED(hr): S_FALSE counts as an error */
752 if (hr == S_OK && actual_read == sizeof(header)
753 && header.dvAspect == drawAspect)
754 {
755 /* Rewind the stream before returning it. */
756 LARGE_INTEGER offset;
757 offset.s.LowPart = 0;
758 offset.s.HighPart = 0;
759 IStream_Seek(pStm, offset, STREAM_SEEK_SET, NULL);
760
761 *ppStm = pStm;
762
763 CoTaskMemFree(elem.pwcsName);
764 IEnumSTATSTG_Release(pEnum);
765
766 return S_OK;
767 }
768
769 IStream_Release(pStm);
770 }
771 }
772
773 CoTaskMemFree(elem.pwcsName);
774 }
775
776 IEnumSTATSTG_Release(pEnum);
777
778 return (hr == S_FALSE ? OLE_E_BLANK : hr);
779}
780
781/************************************************************************
782 * DataCache_ReadPresentationData
783 *
784 * This method will read information for the requested presentation
785 * into the given structure.
786 *
787 * Param:
788 * this - Pointer to the DataCache object
789 * drawAspect - The aspect of the object that we wish to draw.
790 *
791 * Returns:
792 * This method returns a metafile handle if it is successful.
793 * it will return 0 if not.
794 */
795static HMETAFILE DataCache_ReadPresMetafile(
796 DataCache* this,
797 DWORD drawAspect)
798{
799 LARGE_INTEGER offset;
800 IStream* presStream = NULL;
801 HRESULT hres;
802 void* metafileBits;
803 STATSTG streamInfo;
804 HMETAFILE newMetafile = 0;
805
806 /*
807 * Open the presentation stream.
808 */
809 hres = DataCache_OpenPresStream(
810 this,
811 drawAspect,
812 &presStream);
813
814 if (FAILED(hres))
815 return hres;
816
817 /*
818 * Get the size of the stream.
819 */
820 hres = IStream_Stat(presStream,
821 &streamInfo,
822 STATFLAG_NONAME);
823
824 /*
825 * Skip the header
826 */
827 offset.s.HighPart = 0;
828 offset.s.LowPart = sizeof(PresentationDataHeader);
829
830 hres = IStream_Seek(
831 presStream,
832 offset,
833 STREAM_SEEK_SET,
834 NULL);
835
836 streamInfo.cbSize.s.LowPart -= offset.s.LowPart;
837
838 /*
839 * Allocate a buffer for the metafile bits.
840 */
841 metafileBits = HeapAlloc(GetProcessHeap(),
842 0,
843 streamInfo.cbSize.s.LowPart);
844
845 /*
846 * Read the metafile bits.
847 */
848 hres = IStream_Read(
849 presStream,
850 metafileBits,
851 streamInfo.cbSize.s.LowPart,
852 NULL);
853
854 /*
855 * Create a metafile with those bits.
856 */
857 if (SUCCEEDED(hres))
858 {
859 newMetafile = SetMetaFileBitsEx(streamInfo.cbSize.s.LowPart, metafileBits);
860 }
861
862 /*
863 * Cleanup.
864 */
865 HeapFree(GetProcessHeap(), 0, metafileBits);
866 IStream_Release(presStream);
867
868 if (newMetafile==0)
869 hres = E_FAIL;
870
871 return newMetafile;
872}
873
874/*********************************************************
875 * Method implementation for the non delegating IUnknown
876 * part of the DataCache class.
877 */
878
879/************************************************************************
880 * DataCache_NDIUnknown_QueryInterface (IUnknown)
881 *
882 * See Windows documentation for more details on IUnknown methods.
883 *
884 * This version of QueryInterface will not delegate it's implementation
885 * to the outer unknown.
886 */
887static HRESULT WINAPI DataCache_NDIUnknown_QueryInterface(
888 IUnknown* iface,
889 REFIID riid,
890 void** ppvObject)
891{
892 _ICOM_THIS_From_NDIUnknown(DataCache, iface);
893
894 /*
895 * Perform a sanity check on the parameters.
896 */
897 if ( (this==0) || (ppvObject==0) )
898 return E_INVALIDARG;
899
900 /*
901 * Initialize the return parameter.
902 */
903 *ppvObject = 0;
904
905 /*
906 * Compare the riid with the interface IDs implemented by this object.
907 */
908 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
909 {
910 *ppvObject = iface;
911 }
912 else if (memcmp(&IID_IDataObject, riid, sizeof(IID_IDataObject)) == 0)
913 {
914 *ppvObject = (IDataObject*)&(this->lpvtbl1);
915 }
916 else if ( (memcmp(&IID_IPersistStorage, riid, sizeof(IID_IPersistStorage)) == 0) ||
917 (memcmp(&IID_IPersist, riid, sizeof(IID_IPersist)) == 0) )
918 {
919 *ppvObject = (IPersistStorage*)&(this->lpvtbl3);
920 }
921 else if ( (memcmp(&IID_IViewObject, riid, sizeof(IID_IViewObject)) == 0) ||
922 (memcmp(&IID_IViewObject2, riid, sizeof(IID_IViewObject2)) == 0) )
923 {
924 *ppvObject = (IViewObject2*)&(this->lpvtbl4);
925 }
926 else if ( (memcmp(&IID_IOleCache, riid, sizeof(IID_IOleCache)) == 0) ||
927 (memcmp(&IID_IOleCache2, riid, sizeof(IID_IOleCache2)) == 0) )
928 {
929 *ppvObject = (IOleCache2*)&(this->lpvtbl5);
930 }
931 else if (memcmp(&IID_IOleCacheControl, riid, sizeof(IID_IOleCacheControl)) == 0)
932 {
933 *ppvObject = (IOleCacheControl*)&(this->lpvtbl6);
934 }
935
936 /*
937 * Check that we obtained an interface.
938 */
939 if ((*ppvObject)==0)
940 {
941 WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid));
942 return E_NOINTERFACE;
943 }
944
945 /*
946 * Query Interface always increases the reference count by one when it is
947 * successful.
948 */
949 IUnknown_AddRef((IUnknown*)*ppvObject);
950
951 return S_OK;;
952}
953
954/************************************************************************
955 * DataCache_NDIUnknown_AddRef (IUnknown)
956 *
957 * See Windows documentation for more details on IUnknown methods.
958 *
959 * This version of QueryInterface will not delegate it's implementation
960 * to the outer unknown.
961 */
962static ULONG WINAPI DataCache_NDIUnknown_AddRef(
963 IUnknown* iface)
964{
965 _ICOM_THIS_From_NDIUnknown(DataCache, iface);
966
967 this->ref++;
968
969 return this->ref;
970}
971
972/************************************************************************
973 * DataCache_NDIUnknown_Release (IUnknown)
974 *
975 * See Windows documentation for more details on IUnknown methods.
976 *
977 * This version of QueryInterface will not delegate it's implementation
978 * to the outer unknown.
979 */
980static ULONG WINAPI DataCache_NDIUnknown_Release(
981 IUnknown* iface)
982{
983 _ICOM_THIS_From_NDIUnknown(DataCache, iface);
984
985 /*
986 * Decrease the reference count on this object.
987 */
988 this->ref--;
989
990 /*
991 * If the reference count goes down to 0, perform suicide.
992 */
993 if (this->ref==0)
994 {
995 DataCache_Destroy(this);
996
997 return 0;
998 }
999
1000 return this->ref;
1001}
1002
1003/*********************************************************
1004 * Method implementation for the IDataObject
1005 * part of the DataCache class.
1006 */
1007
1008/************************************************************************
1009 * DataCache_IDataObject_QueryInterface (IUnknown)
1010 *
1011 * See Windows documentation for more details on IUnknown methods.
1012 */
1013static HRESULT WINAPI DataCache_IDataObject_QueryInterface(
1014 IDataObject* iface,
1015 REFIID riid,
1016 void** ppvObject)
1017{
1018 _ICOM_THIS_From_IDataObject(DataCache, iface);
1019
1020 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1021}
1022
1023/************************************************************************
1024 * DataCache_IDataObject_AddRef (IUnknown)
1025 *
1026 * See Windows documentation for more details on IUnknown methods.
1027 */
1028static ULONG WINAPI DataCache_IDataObject_AddRef(
1029 IDataObject* iface)
1030{
1031 _ICOM_THIS_From_IDataObject(DataCache, iface);
1032
1033 return IUnknown_AddRef(this->outerUnknown);
1034}
1035
1036/************************************************************************
1037 * DataCache_IDataObject_Release (IUnknown)
1038 *
1039 * See Windows documentation for more details on IUnknown methods.
1040 */
1041static ULONG WINAPI DataCache_IDataObject_Release(
1042 IDataObject* iface)
1043{
1044 _ICOM_THIS_From_IDataObject(DataCache, iface);
1045
1046 return IUnknown_Release(this->outerUnknown);
1047}
1048
1049/************************************************************************
1050 * DataCache_GetData
1051 *
1052 * Get Data from a source dataobject using format pformatetcIn->cfFormat
1053 * See Windows documentation for more details on GetData.
1054 * TODO: Currently only CF_METAFILEPICT is implemented
1055 */
1056static HRESULT WINAPI DataCache_GetData(
1057 IDataObject* iface,
1058 LPFORMATETC pformatetcIn,
1059 STGMEDIUM* pmedium)
1060{
1061 HRESULT hr = 0;
1062 HRESULT hrRet = E_UNEXPECTED;
1063 IPersistStorage *pPersistStorage = 0;
1064 IStorage *pStorage = 0;
1065 IStream *pStream = 0;
1066 OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0};
1067 HGLOBAL hGlobalMF = 0;
1068 void *mfBits = 0;
1069 PresentationDataHeader pdh;
1070 METAFILEPICT *mfPict;
1071 HMETAFILE hMetaFile = 0;
1072
1073 if (pformatetcIn->cfFormat == CF_METAFILEPICT)
1074 {
1075 /* Get the Persist Storage */
1076
1077 hr = IDataObject_QueryInterface(iface, &IID_IPersistStorage, (void**)&pPersistStorage);
1078
1079 if (hr != S_OK)
1080 goto cleanup;
1081
1082 /* Create a doc file to copy the doc to a storage */
1083
1084 hr = StgCreateDocfile(NULL, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &pStorage);
1085
1086 if (hr != S_OK)
1087 goto cleanup;
1088
1089 /* Save it to storage */
1090
1091 hr = OleSave(pPersistStorage, pStorage, FALSE);
1092
1093 if (hr != S_OK)
1094 goto cleanup;
1095
1096 /* Open the Presentation data srteam */
1097
1098 hr = IStorage_OpenStream(pStorage, name, 0, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &pStream);
1099
1100 if (hr != S_OK)
1101 goto cleanup;
1102
1103 /* Read the presentation header */
1104
1105 hr = IStream_Read(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
1106
1107 if (hr != S_OK)
1108 goto cleanup;
1109
1110 mfBits = HeapAlloc(GetProcessHeap(), 0, pdh.dwSize);
1111
1112 /* Read the Metafile bits */
1113
1114 hr = IStream_Read(pStream, mfBits, pdh.dwSize, NULL);
1115
1116 if (hr != S_OK)
1117 goto cleanup;
1118
1119 /* Create the metafile and place it in the STGMEDIUM structure */
1120
1121 hMetaFile = SetMetaFileBitsEx(pdh.dwSize, mfBits);
1122
1123 hGlobalMF = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, sizeof(METAFILEPICT));
1124 mfPict = (METAFILEPICT *)GlobalLock(hGlobalMF);
1125 mfPict->hMF = hMetaFile;
1126
1127 GlobalUnlock(hGlobalMF);
1128
1129 pmedium->u.hGlobal = hGlobalMF;
1130 pmedium->tymed = TYMED_MFPICT;
1131 hrRet = S_OK;
1132
1133cleanup:
1134
1135 if (mfBits)
1136 HeapFree(GetProcessHeap(), 0, mfBits);
1137
1138 if (pStream)
1139 IStream_Release(pStream);
1140
1141 if (pStorage)
1142 IStorage_Release(pStorage);
1143
1144 if (pPersistStorage)
1145 IPersistStorage_Release(pPersistStorage);
1146
1147 return hrRet;
1148 }
1149
1150 /* TODO: Other formats are not implemented */
1151
1152 return E_NOTIMPL;
1153}
1154
1155static HRESULT WINAPI DataCache_GetDataHere(
1156 IDataObject* iface,
1157 LPFORMATETC pformatetc,
1158 STGMEDIUM* pmedium)
1159{
1160 FIXME("stub\n");
1161 return E_NOTIMPL;
1162}
1163
1164static HRESULT WINAPI DataCache_QueryGetData(
1165 IDataObject* iface,
1166 LPFORMATETC pformatetc)
1167{
1168 FIXME("stub\n");
1169 return E_NOTIMPL;
1170}
1171
1172/************************************************************************
1173 * DataCache_EnumFormatEtc (IDataObject)
1174 *
1175 * The data cache doesn't implement this method.
1176 *
1177 * See Windows documentation for more details on IDataObject methods.
1178 */
1179static HRESULT WINAPI DataCache_GetCanonicalFormatEtc(
1180 IDataObject* iface,
1181 LPFORMATETC pformatectIn,
1182 LPFORMATETC pformatetcOut)
1183{
1184 TRACE("()\n");
1185 return E_NOTIMPL;
1186}
1187
1188/************************************************************************
1189 * DataCache_IDataObject_SetData (IDataObject)
1190 *
1191 * This method is delegated to the IOleCache2 implementation.
1192 *
1193 * See Windows documentation for more details on IDataObject methods.
1194 */
1195static HRESULT WINAPI DataCache_IDataObject_SetData(
1196 IDataObject* iface,
1197 LPFORMATETC pformatetc,
1198 STGMEDIUM* pmedium,
1199 BOOL fRelease)
1200{
1201 IOleCache2* oleCache = NULL;
1202 HRESULT hres;
1203
1204 TRACE("(%p, %p, %p, %d)\n", iface, pformatetc, pmedium, fRelease);
1205
1206 hres = IDataObject_QueryInterface(iface, &IID_IOleCache2, (void**)&oleCache);
1207
1208 if (FAILED(hres))
1209 return E_UNEXPECTED;
1210
1211 hres = IOleCache2_SetData(oleCache, pformatetc, pmedium, fRelease);
1212
1213 IOleCache2_Release(oleCache);
1214
1215 return hres;;
1216}
1217
1218/************************************************************************
1219 * DataCache_EnumFormatEtc (IDataObject)
1220 *
1221 * The data cache doesn't implement this method.
1222 *
1223 * See Windows documentation for more details on IDataObject methods.
1224 */
1225static HRESULT WINAPI DataCache_EnumFormatEtc(
1226 IDataObject* iface,
1227 DWORD dwDirection,
1228 IEnumFORMATETC** ppenumFormatEtc)
1229{
1230 TRACE("()\n");
1231 return E_NOTIMPL;
1232}
1233
1234/************************************************************************
1235 * DataCache_DAdvise (IDataObject)
1236 *
1237 * The data cache doesn't support connections.
1238 *
1239 * See Windows documentation for more details on IDataObject methods.
1240 */
1241static HRESULT WINAPI DataCache_DAdvise(
1242 IDataObject* iface,
1243 FORMATETC* pformatetc,
1244 DWORD advf,
1245 IAdviseSink* pAdvSink,
1246 DWORD* pdwConnection)
1247{
1248 TRACE("()\n");
1249 return OLE_E_ADVISENOTSUPPORTED;
1250}
1251
1252/************************************************************************
1253 * DataCache_DUnadvise (IDataObject)
1254 *
1255 * The data cache doesn't support connections.
1256 *
1257 * See Windows documentation for more details on IDataObject methods.
1258 */
1259static HRESULT WINAPI DataCache_DUnadvise(
1260 IDataObject* iface,
1261 DWORD dwConnection)
1262{
1263 TRACE("()\n");
1264 return OLE_E_NOCONNECTION;
1265}
1266
1267/************************************************************************
1268 * DataCache_EnumDAdvise (IDataObject)
1269 *
1270 * The data cache doesn't support connections.
1271 *
1272 * See Windows documentation for more details on IDataObject methods.
1273 */
1274static HRESULT WINAPI DataCache_EnumDAdvise(
1275 IDataObject* iface,
1276 IEnumSTATDATA** ppenumAdvise)
1277{
1278 TRACE("()\n");
1279 return OLE_E_ADVISENOTSUPPORTED;
1280}
1281
1282/*********************************************************
1283 * Method implementation for the IDataObject
1284 * part of the DataCache class.
1285 */
1286
1287/************************************************************************
1288 * DataCache_IPersistStorage_QueryInterface (IUnknown)
1289 *
1290 * See Windows documentation for more details on IUnknown methods.
1291 */
1292static HRESULT WINAPI DataCache_IPersistStorage_QueryInterface(
1293 IPersistStorage* iface,
1294 REFIID riid,
1295 void** ppvObject)
1296{
1297 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1298
1299 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1300}
1301
1302/************************************************************************
1303 * DataCache_IPersistStorage_AddRef (IUnknown)
1304 *
1305 * See Windows documentation for more details on IUnknown methods.
1306 */
1307static ULONG WINAPI DataCache_IPersistStorage_AddRef(
1308 IPersistStorage* iface)
1309{
1310 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1311
1312 return IUnknown_AddRef(this->outerUnknown);
1313}
1314
1315/************************************************************************
1316 * DataCache_IPersistStorage_Release (IUnknown)
1317 *
1318 * See Windows documentation for more details on IUnknown methods.
1319 */
1320static ULONG WINAPI DataCache_IPersistStorage_Release(
1321 IPersistStorage* iface)
1322{
1323 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1324
1325 return IUnknown_Release(this->outerUnknown);
1326}
1327
1328/************************************************************************
1329 * DataCache_GetClassID (IPersistStorage)
1330 *
1331 * The data cache doesn't implement this method.
1332 *
1333 * See Windows documentation for more details on IPersistStorage methods.
1334 */
1335static HRESULT WINAPI DataCache_GetClassID(
1336 IPersistStorage* iface,
1337 CLSID* pClassID)
1338{
1339 TRACE("(%p, %p)\n", iface, pClassID);
1340 return E_NOTIMPL;
1341}
1342
1343/************************************************************************
1344 * DataCache_IsDirty (IPersistStorage)
1345 *
1346 * Until we actully connect to a running object and retrieve new
1347 * information to it, we never get dirty.
1348 *
1349 * See Windows documentation for more details on IPersistStorage methods.
1350 */
1351static HRESULT WINAPI DataCache_IsDirty(
1352 IPersistStorage* iface)
1353{
1354 TRACE("(%p)\n", iface);
1355
1356 return S_FALSE;
1357}
1358
1359/************************************************************************
1360 * DataCache_InitNew (IPersistStorage)
1361 *
1362 * The data cache implementation of IPersistStorage_InitNew simply stores
1363 * the storage pointer.
1364 *
1365 * See Windows documentation for more details on IPersistStorage methods.
1366 */
1367static HRESULT WINAPI DataCache_InitNew(
1368 IPersistStorage* iface,
1369 IStorage* pStg)
1370{
1371 TRACE("(%p, %p)\n", iface, pStg);
1372
1373 return DataCache_Load(iface, pStg);
1374}
1375
1376/************************************************************************
1377 * DataCache_Load (IPersistStorage)
1378 *
1379 * The data cache implementation of IPersistStorage_Load doesn't
1380 * actually load anything. Instead, it holds on to the storage pointer
1381 * and it will load the presentation information when the
1382 * IDataObject_GetData or IViewObject2_Draw methods are called.
1383 *
1384 * See Windows documentation for more details on IPersistStorage methods.
1385 */
1386static HRESULT WINAPI DataCache_Load(
1387 IPersistStorage* iface,
1388 IStorage* pStg)
1389{
1390 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1391
1392 TRACE("(%p, %p)\n", iface, pStg);
1393
1394 if (this->presentationStorage != NULL)
1395 {
1396 IStorage_Release(this->presentationStorage);
1397 }
1398
1399 this->presentationStorage = pStg;
1400
1401 if (this->presentationStorage != NULL)
1402 {
1403 IStorage_AddRef(this->presentationStorage);
1404 }
1405 return S_OK;
1406}
1407
1408/************************************************************************
1409 * DataCache_Save (IPersistStorage)
1410 *
1411 * Until we actully connect to a running object and retrieve new
1412 * information to it, we never have to save anything. However, it is
1413 * our responsability to copy the information when saving to a new
1414 * storage.
1415 *
1416 * See Windows documentation for more details on IPersistStorage methods.
1417 */
1418static HRESULT WINAPI DataCache_Save(
1419 IPersistStorage* iface,
1420 IStorage* pStg,
1421 BOOL fSameAsLoad)
1422{
1423 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1424
1425 TRACE("(%p, %p, %d)\n", iface, pStg, fSameAsLoad);
1426
1427 if ( (!fSameAsLoad) &&
1428 (this->presentationStorage!=NULL) )
1429 {
1430 return IStorage_CopyTo(this->presentationStorage,
1431 0,
1432 NULL,
1433 NULL,
1434 pStg);
1435 }
1436
1437 return S_OK;
1438}
1439
1440/************************************************************************
1441 * DataCache_SaveCompleted (IPersistStorage)
1442 *
1443 * This method is called to tell the cache to release the storage
1444 * pointer it's currentlu holding.
1445 *
1446 * See Windows documentation for more details on IPersistStorage methods.
1447 */
1448static HRESULT WINAPI DataCache_SaveCompleted(
1449 IPersistStorage* iface,
1450 IStorage* pStgNew)
1451{
1452 TRACE("(%p, %p)\n", iface, pStgNew);
1453
1454 if (pStgNew)
1455 {
1456 /*
1457 * First, make sure we get our hands off any storage we have.
1458 */
1459
1460 DataCache_HandsOffStorage(iface);
1461
1462 /*
1463 * Then, attach to the new storage.
1464 */
1465
1466 DataCache_Load(iface, pStgNew);
1467 }
1468
1469 return S_OK;
1470}
1471
1472/************************************************************************
1473 * DataCache_HandsOffStorage (IPersistStorage)
1474 *
1475 * This method is called to tell the cache to release the storage
1476 * pointer it's currentlu holding.
1477 *
1478 * See Windows documentation for more details on IPersistStorage methods.
1479 */
1480static HRESULT WINAPI DataCache_HandsOffStorage(
1481 IPersistStorage* iface)
1482{
1483 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1484
1485 TRACE("(%p)\n", iface);
1486
1487 if (this->presentationStorage != NULL)
1488 {
1489 IStorage_Release(this->presentationStorage);
1490 this->presentationStorage = NULL;
1491 }
1492
1493 return S_OK;
1494}
1495
1496/*********************************************************
1497 * Method implementation for the IViewObject2
1498 * part of the DataCache class.
1499 */
1500
1501/************************************************************************
1502 * DataCache_IViewObject2_QueryInterface (IUnknown)
1503 *
1504 * See Windows documentation for more details on IUnknown methods.
1505 */
1506static HRESULT WINAPI DataCache_IViewObject2_QueryInterface(
1507 IViewObject2* iface,
1508 REFIID riid,
1509 void** ppvObject)
1510{
1511 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1512
1513 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1514}
1515
1516/************************************************************************
1517 * DataCache_IViewObject2_AddRef (IUnknown)
1518 *
1519 * See Windows documentation for more details on IUnknown methods.
1520 */
1521static ULONG WINAPI DataCache_IViewObject2_AddRef(
1522 IViewObject2* iface)
1523{
1524 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1525
1526 return IUnknown_AddRef(this->outerUnknown);
1527}
1528
1529/************************************************************************
1530 * DataCache_IViewObject2_Release (IUnknown)
1531 *
1532 * See Windows documentation for more details on IUnknown methods.
1533 */
1534static ULONG WINAPI DataCache_IViewObject2_Release(
1535 IViewObject2* iface)
1536{
1537 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1538
1539 return IUnknown_Release(this->outerUnknown);
1540}
1541
1542/************************************************************************
1543 * DataCache_Draw (IViewObject2)
1544 *
1545 * This method will draw the cached representation of the object
1546 * to the given device context.
1547 *
1548 * See Windows documentation for more details on IViewObject2 methods.
1549 */
1550static HRESULT WINAPI DataCache_Draw(
1551 IViewObject2* iface,
1552 DWORD dwDrawAspect,
1553 LONG lindex,
1554 void* pvAspect,
1555 DVTARGETDEVICE* ptd,
1556 HDC hdcTargetDev,
1557 HDC hdcDraw,
1558 LPCRECTL lprcBounds,
1559 LPCRECTL lprcWBounds,
1560 IVO_ContCallback pfnContinue,
1561 DWORD dwContinue)
1562{
1563 PresentationDataHeader presData;
1564 HMETAFILE presMetafile = 0;
1565 HRESULT hres;
1566
1567 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1568
1569 TRACE("(%p, %lx, %ld, %p, %x, %x, %p, %p, %p, %lx)\n",
1570 iface,
1571 dwDrawAspect,
1572 lindex,
1573 pvAspect,
1574 hdcTargetDev,
1575 hdcDraw,
1576 lprcBounds,
1577 lprcWBounds,
1578 pfnContinue,
1579 dwContinue);
1580
1581 /*
1582 * Sanity check
1583 */
1584 if (lprcBounds==NULL)
1585 return E_INVALIDARG;
1586
1587 /*
1588 * First, we need to retrieve the dimensions of the
1589 * image in the metafile.
1590 */
1591 hres = DataCache_ReadPresentationData(this,
1592 dwDrawAspect,
1593 &presData);
1594
1595 if (FAILED(hres))
1596 return hres;
1597
1598 /*
1599 * Then, we can extract the metafile itself from the cached
1600 * data.
1601 *
1602 * FIXME Unless it isn't a metafile. I think it could be any CF_XXX type,
1603 * particularly CF_DIB.
1604 */
1605 presMetafile = DataCache_ReadPresMetafile(this,
1606 dwDrawAspect);
1607
1608 /*
1609 * If we have a metafile, just draw baby...
1610 * We have to be careful not to modify the state of the
1611 * DC.
1612 */
1613 if (presMetafile!=0)
1614 {
1615 INT prevMapMode = SetMapMode(hdcDraw, MM_ANISOTROPIC);
1616 SIZE oldWindowExt;
1617 SIZE oldViewportExt;
1618 POINT oldViewportOrg;
1619
1620 SetWindowExtEx(hdcDraw,
1621 presData.dwObjectExtentX,
1622 presData.dwObjectExtentY,
1623 &oldWindowExt);
1624
1625 SetViewportExtEx(hdcDraw,
1626 lprcBounds->right - lprcBounds->left,
1627 lprcBounds->bottom - lprcBounds->top,
1628 &oldViewportExt);
1629
1630 SetViewportOrgEx(hdcDraw,
1631 lprcBounds->left,
1632 lprcBounds->top,
1633 &oldViewportOrg);
1634
1635 PlayMetaFile(hdcDraw, presMetafile);
1636
1637 SetWindowExtEx(hdcDraw,
1638 oldWindowExt.cx,
1639 oldWindowExt.cy,
1640 NULL);
1641
1642 SetViewportExtEx(hdcDraw,
1643 oldViewportExt.cx,
1644 oldViewportExt.cy,
1645 NULL);
1646
1647 SetViewportOrgEx(hdcDraw,
1648 oldViewportOrg.x,
1649 oldViewportOrg.y,
1650 NULL);
1651
1652 SetMapMode(hdcDraw, prevMapMode);
1653
1654 DeleteMetaFile(presMetafile);
1655 }
1656
1657 return S_OK;
1658}
1659
1660static HRESULT WINAPI DataCache_GetColorSet(
1661 IViewObject2* iface,
1662 DWORD dwDrawAspect,
1663 LONG lindex,
1664 void* pvAspect,
1665 DVTARGETDEVICE* ptd,
1666 HDC hicTargetDevice,
1667 LOGPALETTE** ppColorSet)
1668{
1669 FIXME("stub\n");
1670 return E_NOTIMPL;
1671}
1672
1673static HRESULT WINAPI DataCache_Freeze(
1674 IViewObject2* iface,
1675 DWORD dwDrawAspect,
1676 LONG lindex,
1677 void* pvAspect,
1678 DWORD* pdwFreeze)
1679{
1680 FIXME("stub\n");
1681 return E_NOTIMPL;
1682}
1683
1684static HRESULT WINAPI DataCache_Unfreeze(
1685 IViewObject2* iface,
1686 DWORD dwFreeze)
1687{
1688 FIXME("stub\n");
1689 return E_NOTIMPL;
1690}
1691
1692/************************************************************************
1693 * DataCache_SetAdvise (IViewObject2)
1694 *
1695 * This sets-up an advisory sink with the data cache. When the object's
1696 * view changes, this sink is called.
1697 *
1698 * See Windows documentation for more details on IViewObject2 methods.
1699 */
1700static HRESULT WINAPI DataCache_SetAdvise(
1701 IViewObject2* iface,
1702 DWORD aspects,
1703 DWORD advf,
1704 IAdviseSink* pAdvSink)
1705{
1706 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1707
1708 TRACE("(%p, %lx, %lx, %p)\n", iface, aspects, advf, pAdvSink);
1709
1710 /*
1711 * A call to this function removes the previous sink
1712 */
1713 if (this->sinkInterface != NULL)
1714 {
1715 IAdviseSink_Release(this->sinkInterface);
1716 this->sinkInterface = NULL;
1717 this->sinkAspects = 0;
1718 this->sinkAdviseFlag = 0;
1719 }
1720
1721 /*
1722 * Now, setup the new one.
1723 */
1724 if (pAdvSink!=NULL)
1725 {
1726 this->sinkInterface = pAdvSink;
1727 this->sinkAspects = aspects;
1728 this->sinkAdviseFlag = advf;
1729
1730 IAdviseSink_AddRef(this->sinkInterface);
1731 }
1732
1733 /*
1734 * When the ADVF_PRIMEFIRST flag is set, we have to advise the
1735 * sink immediately.
1736 */
1737 if (advf & ADVF_PRIMEFIRST)
1738 {
1739 DataCache_FireOnViewChange(this,
1740 DVASPECT_CONTENT,
1741 -1);
1742 }
1743
1744 return S_OK;
1745}
1746
1747/************************************************************************
1748 * DataCache_GetAdvise (IViewObject2)
1749 *
1750 * This method queries the current state of the advise sink
1751 * installed on the data cache.
1752 *
1753 * See Windows documentation for more details on IViewObject2 methods.
1754 */
1755static HRESULT WINAPI DataCache_GetAdvise(
1756 IViewObject2* iface,
1757 DWORD* pAspects,
1758 DWORD* pAdvf,
1759 IAdviseSink** ppAdvSink)
1760{
1761 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1762
1763 TRACE("(%p, %p, %p, %p)\n", iface, pAspects, pAdvf, ppAdvSink);
1764
1765 /*
1766 * Just copy all the requested values.
1767 */
1768 if (pAspects!=NULL)
1769 *pAspects = this->sinkAspects;
1770
1771 if (pAdvf!=NULL)
1772 *pAdvf = this->sinkAdviseFlag;
1773
1774 if (ppAdvSink!=NULL)
1775 {
1776 IAdviseSink_QueryInterface(this->sinkInterface,
1777 &IID_IAdviseSink,
1778 (void**)ppAdvSink);
1779 }
1780
1781 return S_OK;
1782}
1783
1784/************************************************************************
1785 * DataCache_GetExtent (IViewObject2)
1786 *
1787 * This method retrieves the "natural" size of this cached object.
1788 *
1789 * See Windows documentation for more details on IViewObject2 methods.
1790 */
1791static HRESULT WINAPI DataCache_GetExtent(
1792 IViewObject2* iface,
1793 DWORD dwDrawAspect,
1794 LONG lindex,
1795 DVTARGETDEVICE* ptd,
1796 LPSIZEL lpsizel)
1797{
1798 PresentationDataHeader presData;
1799 HRESULT hres = E_FAIL;
1800
1801 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1802
1803 TRACE("(%p, %lx, %ld, %p, %p)\n",
1804 iface, dwDrawAspect, lindex, ptd, lpsizel);
1805
1806 /*
1807 * Sanity check
1808 */
1809 if (lpsizel==NULL)
1810 return E_POINTER;
1811
1812 /*
1813 * Initialize the out parameter.
1814 */
1815 lpsizel->cx = 0;
1816 lpsizel->cy = 0;
1817
1818 /*
1819 * This flag should be set to -1.
1820 */
1821 if (lindex!=-1)
1822 FIXME("Unimplemented flag lindex = %ld\n", lindex);
1823
1824 /*
1825 * Right now, we suport only the callback from
1826 * the default handler.
1827 */
1828 if (ptd!=NULL)
1829 FIXME("Unimplemented ptd = %p\n", ptd);
1830
1831 /*
1832 * Get the presentation information from the
1833 * cache.
1834 */
1835 hres = DataCache_ReadPresentationData(this,
1836 dwDrawAspect,
1837 &presData);
1838
1839 if (SUCCEEDED(hres))
1840 {
1841 lpsizel->cx = presData.dwObjectExtentX;
1842 lpsizel->cy = presData.dwObjectExtentY;
1843 }
1844
1845 /*
1846 * This method returns OLE_E_BLANK when it fails.
1847 */
1848 if (FAILED(hres))
1849 hres = OLE_E_BLANK;
1850
1851 return hres;
1852}
1853
1854
1855/*********************************************************
1856 * Method implementation for the IOleCache2
1857 * part of the DataCache class.
1858 */
1859
1860/************************************************************************
1861 * DataCache_IOleCache2_QueryInterface (IUnknown)
1862 *
1863 * See Windows documentation for more details on IUnknown methods.
1864 */
1865static HRESULT WINAPI DataCache_IOleCache2_QueryInterface(
1866 IOleCache2* iface,
1867 REFIID riid,
1868 void** ppvObject)
1869{
1870 _ICOM_THIS_From_IOleCache2(DataCache, iface);
1871
1872 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1873}
1874
1875/************************************************************************
1876 * DataCache_IOleCache2_AddRef (IUnknown)
1877 *
1878 * See Windows documentation for more details on IUnknown methods.
1879 */
1880static ULONG WINAPI DataCache_IOleCache2_AddRef(
1881 IOleCache2* iface)
1882{
1883 _ICOM_THIS_From_IOleCache2(DataCache, iface);
1884
1885 return IUnknown_AddRef(this->outerUnknown);
1886}
1887
1888/************************************************************************
1889 * DataCache_IOleCache2_Release (IUnknown)
1890 *
1891 * See Windows documentation for more details on IUnknown methods.
1892 */
1893static ULONG WINAPI DataCache_IOleCache2_Release(
1894 IOleCache2* iface)
1895{
1896 _ICOM_THIS_From_IOleCache2(DataCache, iface);
1897
1898 return IUnknown_Release(this->outerUnknown);
1899}
1900
1901static HRESULT WINAPI DataCache_Cache(
1902 IOleCache2* iface,
1903 FORMATETC* pformatetc,
1904 DWORD advf,
1905 DWORD* pdwConnection)
1906{
1907 FIXME("stub\n");
1908 return E_NOTIMPL;
1909}
1910
1911static HRESULT WINAPI DataCache_Uncache(
1912 IOleCache2* iface,
1913 DWORD dwConnection)
1914{
1915 FIXME("stub\n");
1916 return E_NOTIMPL;
1917}
1918
1919static HRESULT WINAPI DataCache_EnumCache(
1920 IOleCache2* iface,
1921 IEnumSTATDATA** ppenumSTATDATA)
1922{
1923 FIXME("stub\n");
1924 return E_NOTIMPL;
1925}
1926
1927static HRESULT WINAPI DataCache_InitCache(
1928 IOleCache2* iface,
1929 IDataObject* pDataObject)
1930{
1931 FIXME("stub\n");
1932 return E_NOTIMPL;
1933}
1934
1935static HRESULT WINAPI DataCache_IOleCache2_SetData(
1936 IOleCache2* iface,
1937 FORMATETC* pformatetc,
1938 STGMEDIUM* pmedium,
1939 BOOL fRelease)
1940{
1941 FIXME("stub\n");
1942 return E_NOTIMPL;
1943}
1944
1945static HRESULT WINAPI DataCache_UpdateCache(
1946 IOleCache2* iface,
1947 LPDATAOBJECT pDataObject,
1948 DWORD grfUpdf,
1949 LPVOID pReserved)
1950{
1951 FIXME("stub\n");
1952 return E_NOTIMPL;
1953}
1954
1955static HRESULT WINAPI DataCache_DiscardCache(
1956 IOleCache2* iface,
1957 DWORD dwDiscardOptions)
1958{
1959 FIXME("stub\n");
1960 return E_NOTIMPL;
1961}
1962
1963
1964/*********************************************************
1965 * Method implementation for the IOleCacheControl
1966 * part of the DataCache class.
1967 */
1968
1969/************************************************************************
1970 * DataCache_IOleCacheControl_QueryInterface (IUnknown)
1971 *
1972 * See Windows documentation for more details on IUnknown methods.
1973 */
1974static HRESULT WINAPI DataCache_IOleCacheControl_QueryInterface(
1975 IOleCacheControl* iface,
1976 REFIID riid,
1977 void** ppvObject)
1978{
1979 _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
1980
1981 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1982}
1983
1984/************************************************************************
1985 * DataCache_IOleCacheControl_AddRef (IUnknown)
1986 *
1987 * See Windows documentation for more details on IUnknown methods.
1988 */
1989static ULONG WINAPI DataCache_IOleCacheControl_AddRef(
1990 IOleCacheControl* iface)
1991{
1992 _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
1993
1994 return IUnknown_AddRef(this->outerUnknown);
1995}
1996
1997/************************************************************************
1998 * DataCache_IOleCacheControl_Release (IUnknown)
1999 *
2000 * See Windows documentation for more details on IUnknown methods.
2001 */
2002static ULONG WINAPI DataCache_IOleCacheControl_Release(
2003 IOleCacheControl* iface)
2004{
2005 _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
2006
2007 return IUnknown_Release(this->outerUnknown);
2008}
2009
2010static HRESULT WINAPI DataCache_OnRun(
2011 IOleCacheControl* iface,
2012 LPDATAOBJECT pDataObject)
2013{
2014 FIXME("stub\n");
2015 return E_NOTIMPL;
2016}
2017
2018static HRESULT WINAPI DataCache_OnStop(
2019 IOleCacheControl* iface)
2020{
2021 FIXME("stub\n");
2022 return E_NOTIMPL;
2023}
2024
2025
Note: See TracBrowser for help on using the repository browser.