source: trunk/src/ole32/datacache.c

Last change on this file was 21916, checked in by dmik, 14 years ago

Merge branch gcc-kmk to trunk.

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