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