source: trunk/src/ole32/old/datacache.cpp

Last change on this file was 5601, checked in by sandervl, 24 years ago

created

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