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