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

Last change on this file since 6648 was 6648, checked in by bird, 24 years ago

Added $Id:$ keyword.

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