Correctness for const pointer casts.
[wine/multimedia.git] / dlls / ole32 / datacache.c
blob298defbf89be6b455955e2565959e39383d4e55e
1 /*
2 * OLE 2 Data cache
4 * Copyright 1999 Francis Beaudet
5 * Copyright 2000 Abey George
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.
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.
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
21 * NOTES:
22 * The OLE2 data cache supports a whole whack of
23 * interfaces including:
24 * IDataObject, IPersistStorage, IViewObject2,
25 * IOleCache2 and IOleCacheControl.
27 * Most of the implementation details are taken from: Inside OLE
28 * second edition by Kraig Brockschmidt,
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.
46 #include <assert.h>
47 #include <stdarg.h>
48 #include <string.h>
50 #define COBJMACROS
51 #define NONAMELESSUNION
52 #define NONAMELESSSTRUCT
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"
63 WINE_DEFAULT_DEBUG_CHANNEL(ole);
65 /****************************************************************************
66 * PresentationDataHeader
68 * This structure represents the header of the \002OlePresXXX stream in
69 * the OLE object strorage.
71 * Most fields are still unknown.
73 typedef struct PresentationDataHeader
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 */
81 DWORD unknown6;
82 DWORD unknown7; /* 0 */
83 DWORD dwObjectExtentX;
84 DWORD dwObjectExtentY;
85 DWORD dwSize;
86 } PresentationDataHeader;
88 /****************************************************************************
89 * DataCache
91 struct DataCache
94 * List all interface VTables here
96 IDataObjectVtbl* lpvtbl1;
97 IUnknownVtbl* lpvtbl2;
98 IPersistStorageVtbl* lpvtbl3;
99 IViewObject2Vtbl* lpvtbl4;
100 IOleCache2Vtbl* lpvtbl5;
101 IOleCacheControlVtbl* lpvtbl6;
104 * Reference count of this object
106 ULONG ref;
109 * IUnknown implementation of the outer object.
111 IUnknown* outerUnknown;
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.
118 IStorage* presentationStorage;
121 * The user of this object can setup ONE advise sink
122 * connection with the object. These parameters describe
123 * that connection.
125 DWORD sinkAspects;
126 DWORD sinkAdviseFlag;
127 IAdviseSink* sinkInterface;
131 typedef struct DataCache DataCache;
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.
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*))
147 * Prototypes for the methods of the DataCache class.
149 static DataCache* DataCache_Construct(REFCLSID clsid,
150 LPUNKNOWN pUnkOuter);
151 static HRESULT DataCache_OpenPresStream(DataCache *this,
152 DWORD drawAspect,
153 IStream **pStm);
155 static void DataCache_Destroy(
156 DataCache* ptrToDestroy)
158 TRACE("()\n");
160 if (ptrToDestroy->sinkInterface != NULL)
162 IAdviseSink_Release(ptrToDestroy->sinkInterface);
163 ptrToDestroy->sinkInterface = NULL;
166 if (ptrToDestroy->presentationStorage != NULL)
168 IStorage_Release(ptrToDestroy->presentationStorage);
169 ptrToDestroy->presentationStorage = NULL;
173 * Free the datacache pointer.
175 HeapFree(GetProcessHeap(), 0, ptrToDestroy);
178 /************************************************************************
179 * DataCache_ReadPresentationData
181 * This method will read information for the requested presentation
182 * into the given structure.
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.
190 static HRESULT DataCache_ReadPresentationData(
191 DataCache* this,
192 DWORD drawAspect,
193 PresentationDataHeader* header)
195 IStream* presStream = NULL;
196 HRESULT hres;
199 * Open the presentation stream.
201 hres = DataCache_OpenPresStream(
202 this,
203 drawAspect,
204 &presStream);
206 if (FAILED(hres))
207 return hres;
210 * Read the header.
213 hres = IStream_Read(
214 presStream,
215 header,
216 sizeof(PresentationDataHeader),
217 NULL);
220 * Cleanup.
222 IStream_Release(presStream);
225 * We don't want to propagate any other error
226 * code than a failure.
228 if (hres!=S_OK)
229 hres = E_FAIL;
231 return hres;
234 /************************************************************************
235 * DataCache_FireOnViewChange
237 * This method will fire an OnViewChange notification to the advise
238 * sink registered with the datacache.
240 * See IAdviseSink::OnViewChange for more details.
242 static void DataCache_FireOnViewChange(
243 DataCache* this,
244 DWORD aspect,
245 LONG lindex)
247 TRACE("(%p, %lx, %ld)\n", this, aspect, lindex);
250 * The sink supplies a filter when it registers
251 * we make sure we only send the notifications when that
252 * filter matches.
254 if ((this->sinkAspects & aspect) != 0)
256 if (this->sinkInterface != NULL)
258 IAdviseSink_OnViewChange(this->sinkInterface,
259 aspect,
260 lindex);
263 * Some sinks want to be unregistered automatically when
264 * the first notification goes out.
266 if ( (this->sinkAdviseFlag & ADVF_ONLYONCE) != 0)
268 IAdviseSink_Release(this->sinkInterface);
270 this->sinkInterface = NULL;
271 this->sinkAspects = 0;
272 this->sinkAdviseFlag = 0;
278 /* Helper for DataCache_OpenPresStream */
279 static BOOL DataCache_IsPresentationStream(const STATSTG *elem)
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' };
285 LPCWSTR name = elem->pwcsName;
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');
296 /************************************************************************
297 * DataCache_OpenPresStream
299 * This method will find the stream for the given presentation. It makes
300 * no attempt at fallback.
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.
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.
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.
318 * If a fallback is desired, just opening the first presentation stream
319 * is a possibility.
321 static HRESULT DataCache_OpenPresStream(
322 DataCache *this,
323 DWORD drawAspect,
324 IStream **ppStm)
326 STATSTG elem;
327 IEnumSTATSTG *pEnum;
328 HRESULT hr;
330 if (!ppStm) return E_POINTER;
332 hr = IStorage_EnumElements(this->presentationStorage, 0, NULL, 0, &pEnum);
333 if (FAILED(hr)) return hr;
335 while ((hr = IEnumSTATSTG_Next(pEnum, 1, &elem, NULL)) == S_OK)
337 if (DataCache_IsPresentationStream(&elem))
339 IStream *pStm;
341 hr = IStorage_OpenStream(this->presentationStorage, elem.pwcsName,
342 NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0,
343 &pStm);
344 if (SUCCEEDED(hr))
346 PresentationDataHeader header;
347 ULONG actual_read;
349 hr = IStream_Read(pStm, &header, sizeof(header), &actual_read);
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)
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);
361 *ppStm = pStm;
363 CoTaskMemFree(elem.pwcsName);
364 IEnumSTATSTG_Release(pEnum);
366 return S_OK;
369 IStream_Release(pStm);
373 CoTaskMemFree(elem.pwcsName);
376 IEnumSTATSTG_Release(pEnum);
378 return (hr == S_FALSE ? OLE_E_BLANK : hr);
381 /************************************************************************
382 * DataCache_ReadPresentationData
384 * This method will read information for the requested presentation
385 * into the given structure.
387 * Param:
388 * this - Pointer to the DataCache object
389 * drawAspect - The aspect of the object that we wish to draw.
391 * Returns:
392 * This method returns a metafile handle if it is successful.
393 * it will return 0 if not.
395 static HMETAFILE DataCache_ReadPresMetafile(
396 DataCache* this,
397 DWORD drawAspect)
399 LARGE_INTEGER offset;
400 IStream* presStream = NULL;
401 HRESULT hres;
402 void* metafileBits;
403 STATSTG streamInfo;
404 HMETAFILE newMetafile = 0;
407 * Open the presentation stream.
409 hres = DataCache_OpenPresStream(
410 this,
411 drawAspect,
412 &presStream);
414 if (FAILED(hres))
415 return (HMETAFILE)hres;
418 * Get the size of the stream.
420 hres = IStream_Stat(presStream,
421 &streamInfo,
422 STATFLAG_NONAME);
425 * Skip the header
427 offset.u.HighPart = 0;
428 offset.u.LowPart = sizeof(PresentationDataHeader);
430 hres = IStream_Seek(
431 presStream,
432 offset,
433 STREAM_SEEK_SET,
434 NULL);
436 streamInfo.cbSize.u.LowPart -= offset.u.LowPart;
439 * Allocate a buffer for the metafile bits.
441 metafileBits = HeapAlloc(GetProcessHeap(),
443 streamInfo.cbSize.u.LowPart);
446 * Read the metafile bits.
448 hres = IStream_Read(
449 presStream,
450 metafileBits,
451 streamInfo.cbSize.u.LowPart,
452 NULL);
455 * Create a metafile with those bits.
457 if (SUCCEEDED(hres))
459 newMetafile = SetMetaFileBitsEx(streamInfo.cbSize.u.LowPart, metafileBits);
463 * Cleanup.
465 HeapFree(GetProcessHeap(), 0, metafileBits);
466 IStream_Release(presStream);
468 if (newMetafile==0)
469 hres = E_FAIL;
471 return newMetafile;
474 /*********************************************************
475 * Method implementation for the non delegating IUnknown
476 * part of the DataCache class.
479 /************************************************************************
480 * DataCache_NDIUnknown_QueryInterface (IUnknown)
482 * See Windows documentation for more details on IUnknown methods.
484 * This version of QueryInterface will not delegate it's implementation
485 * to the outer unknown.
487 static HRESULT WINAPI DataCache_NDIUnknown_QueryInterface(
488 IUnknown* iface,
489 REFIID riid,
490 void** ppvObject)
492 _ICOM_THIS_From_NDIUnknown(DataCache, iface);
495 * Perform a sanity check on the parameters.
497 if ( (this==0) || (ppvObject==0) )
498 return E_INVALIDARG;
501 * Initialize the return parameter.
503 *ppvObject = 0;
506 * Compare the riid with the interface IDs implemented by this object.
508 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
510 *ppvObject = iface;
512 else if (memcmp(&IID_IDataObject, riid, sizeof(IID_IDataObject)) == 0)
514 *ppvObject = (IDataObject*)&(this->lpvtbl1);
516 else if ( (memcmp(&IID_IPersistStorage, riid, sizeof(IID_IPersistStorage)) == 0) ||
517 (memcmp(&IID_IPersist, riid, sizeof(IID_IPersist)) == 0) )
519 *ppvObject = (IPersistStorage*)&(this->lpvtbl3);
521 else if ( (memcmp(&IID_IViewObject, riid, sizeof(IID_IViewObject)) == 0) ||
522 (memcmp(&IID_IViewObject2, riid, sizeof(IID_IViewObject2)) == 0) )
524 *ppvObject = (IViewObject2*)&(this->lpvtbl4);
526 else if ( (memcmp(&IID_IOleCache, riid, sizeof(IID_IOleCache)) == 0) ||
527 (memcmp(&IID_IOleCache2, riid, sizeof(IID_IOleCache2)) == 0) )
529 *ppvObject = (IOleCache2*)&(this->lpvtbl5);
531 else if (memcmp(&IID_IOleCacheControl, riid, sizeof(IID_IOleCacheControl)) == 0)
533 *ppvObject = (IOleCacheControl*)&(this->lpvtbl6);
537 * Check that we obtained an interface.
539 if ((*ppvObject)==0)
541 WARN( "() : asking for unsupported interface %s\n", debugstr_guid(riid));
542 return E_NOINTERFACE;
546 * Query Interface always increases the reference count by one when it is
547 * successful.
549 IUnknown_AddRef((IUnknown*)*ppvObject);
551 return S_OK;
554 /************************************************************************
555 * DataCache_NDIUnknown_AddRef (IUnknown)
557 * See Windows documentation for more details on IUnknown methods.
559 * This version of QueryInterface will not delegate it's implementation
560 * to the outer unknown.
562 static ULONG WINAPI DataCache_NDIUnknown_AddRef(
563 IUnknown* iface)
565 _ICOM_THIS_From_NDIUnknown(DataCache, iface);
566 return InterlockedIncrement(&this->ref);
569 /************************************************************************
570 * DataCache_NDIUnknown_Release (IUnknown)
572 * See Windows documentation for more details on IUnknown methods.
574 * This version of QueryInterface will not delegate it's implementation
575 * to the outer unknown.
577 static ULONG WINAPI DataCache_NDIUnknown_Release(
578 IUnknown* iface)
580 _ICOM_THIS_From_NDIUnknown(DataCache, iface);
581 ULONG ref;
584 * Decrease the reference count on this object.
586 ref = InterlockedDecrement(&this->ref);
589 * If the reference count goes down to 0, perform suicide.
591 if (ref == 0) DataCache_Destroy(this);
593 return ref;
596 /*********************************************************
597 * Method implementation for the IDataObject
598 * part of the DataCache class.
601 /************************************************************************
602 * DataCache_IDataObject_QueryInterface (IUnknown)
604 * See Windows documentation for more details on IUnknown methods.
606 static HRESULT WINAPI DataCache_IDataObject_QueryInterface(
607 IDataObject* iface,
608 REFIID riid,
609 void** ppvObject)
611 _ICOM_THIS_From_IDataObject(DataCache, iface);
613 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
616 /************************************************************************
617 * DataCache_IDataObject_AddRef (IUnknown)
619 * See Windows documentation for more details on IUnknown methods.
621 static ULONG WINAPI DataCache_IDataObject_AddRef(
622 IDataObject* iface)
624 _ICOM_THIS_From_IDataObject(DataCache, iface);
626 return IUnknown_AddRef(this->outerUnknown);
629 /************************************************************************
630 * DataCache_IDataObject_Release (IUnknown)
632 * See Windows documentation for more details on IUnknown methods.
634 static ULONG WINAPI DataCache_IDataObject_Release(
635 IDataObject* iface)
637 _ICOM_THIS_From_IDataObject(DataCache, iface);
639 return IUnknown_Release(this->outerUnknown);
642 /************************************************************************
643 * DataCache_GetData
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
649 static HRESULT WINAPI DataCache_GetData(
650 IDataObject* iface,
651 LPFORMATETC pformatetcIn,
652 STGMEDIUM* pmedium)
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;
666 if (pformatetcIn->cfFormat == CF_METAFILEPICT)
668 /* Get the Persist Storage */
670 hr = IDataObject_QueryInterface(iface, &IID_IPersistStorage, (void**)&pPersistStorage);
672 if (hr != S_OK)
673 goto cleanup;
675 /* Create a doc file to copy the doc to a storage */
677 hr = StgCreateDocfile(NULL, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &pStorage);
679 if (hr != S_OK)
680 goto cleanup;
682 /* Save it to storage */
684 hr = OleSave(pPersistStorage, pStorage, FALSE);
686 if (hr != S_OK)
687 goto cleanup;
689 /* Open the Presentation data srteam */
691 hr = IStorage_OpenStream(pStorage, name, 0, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &pStream);
693 if (hr != S_OK)
694 goto cleanup;
696 /* Read the presentation header */
698 hr = IStream_Read(pStream, &pdh, sizeof(PresentationDataHeader), NULL);
700 if (hr != S_OK)
701 goto cleanup;
703 mfBits = HeapAlloc(GetProcessHeap(), 0, pdh.dwSize);
705 /* Read the Metafile bits */
707 hr = IStream_Read(pStream, mfBits, pdh.dwSize, NULL);
709 if (hr != S_OK)
710 goto cleanup;
712 /* Create the metafile and place it in the STGMEDIUM structure */
714 hMetaFile = SetMetaFileBitsEx(pdh.dwSize, mfBits);
716 hGlobalMF = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, sizeof(METAFILEPICT));
717 mfPict = (METAFILEPICT *)GlobalLock(hGlobalMF);
718 mfPict->hMF = hMetaFile;
720 GlobalUnlock(hGlobalMF);
722 pmedium->u.hGlobal = hGlobalMF;
723 pmedium->tymed = TYMED_MFPICT;
724 hrRet = S_OK;
726 cleanup:
728 HeapFree(GetProcessHeap(), 0, mfBits);
730 if (pStream)
731 IStream_Release(pStream);
733 if (pStorage)
734 IStorage_Release(pStorage);
736 if (pPersistStorage)
737 IPersistStorage_Release(pPersistStorage);
739 return hrRet;
742 /* TODO: Other formats are not implemented */
744 return E_NOTIMPL;
747 static HRESULT WINAPI DataCache_GetDataHere(
748 IDataObject* iface,
749 LPFORMATETC pformatetc,
750 STGMEDIUM* pmedium)
752 FIXME("stub\n");
753 return E_NOTIMPL;
756 static HRESULT WINAPI DataCache_QueryGetData(
757 IDataObject* iface,
758 LPFORMATETC pformatetc)
760 FIXME("stub\n");
761 return E_NOTIMPL;
764 /************************************************************************
765 * DataCache_EnumFormatEtc (IDataObject)
767 * The data cache doesn't implement this method.
769 * See Windows documentation for more details on IDataObject methods.
771 static HRESULT WINAPI DataCache_GetCanonicalFormatEtc(
772 IDataObject* iface,
773 LPFORMATETC pformatectIn,
774 LPFORMATETC pformatetcOut)
776 TRACE("()\n");
777 return E_NOTIMPL;
780 /************************************************************************
781 * DataCache_IDataObject_SetData (IDataObject)
783 * This method is delegated to the IOleCache2 implementation.
785 * See Windows documentation for more details on IDataObject methods.
787 static HRESULT WINAPI DataCache_IDataObject_SetData(
788 IDataObject* iface,
789 LPFORMATETC pformatetc,
790 STGMEDIUM* pmedium,
791 BOOL fRelease)
793 IOleCache2* oleCache = NULL;
794 HRESULT hres;
796 TRACE("(%p, %p, %p, %d)\n", iface, pformatetc, pmedium, fRelease);
798 hres = IDataObject_QueryInterface(iface, &IID_IOleCache2, (void**)&oleCache);
800 if (FAILED(hres))
801 return E_UNEXPECTED;
803 hres = IOleCache2_SetData(oleCache, pformatetc, pmedium, fRelease);
805 IOleCache2_Release(oleCache);
807 return hres;
810 /************************************************************************
811 * DataCache_EnumFormatEtc (IDataObject)
813 * The data cache doesn't implement this method.
815 * See Windows documentation for more details on IDataObject methods.
817 static HRESULT WINAPI DataCache_EnumFormatEtc(
818 IDataObject* iface,
819 DWORD dwDirection,
820 IEnumFORMATETC** ppenumFormatEtc)
822 TRACE("()\n");
823 return E_NOTIMPL;
826 /************************************************************************
827 * DataCache_DAdvise (IDataObject)
829 * The data cache doesn't support connections.
831 * See Windows documentation for more details on IDataObject methods.
833 static HRESULT WINAPI DataCache_DAdvise(
834 IDataObject* iface,
835 FORMATETC* pformatetc,
836 DWORD advf,
837 IAdviseSink* pAdvSink,
838 DWORD* pdwConnection)
840 TRACE("()\n");
841 return OLE_E_ADVISENOTSUPPORTED;
844 /************************************************************************
845 * DataCache_DUnadvise (IDataObject)
847 * The data cache doesn't support connections.
849 * See Windows documentation for more details on IDataObject methods.
851 static HRESULT WINAPI DataCache_DUnadvise(
852 IDataObject* iface,
853 DWORD dwConnection)
855 TRACE("()\n");
856 return OLE_E_NOCONNECTION;
859 /************************************************************************
860 * DataCache_EnumDAdvise (IDataObject)
862 * The data cache doesn't support connections.
864 * See Windows documentation for more details on IDataObject methods.
866 static HRESULT WINAPI DataCache_EnumDAdvise(
867 IDataObject* iface,
868 IEnumSTATDATA** ppenumAdvise)
870 TRACE("()\n");
871 return OLE_E_ADVISENOTSUPPORTED;
874 /*********************************************************
875 * Method implementation for the IDataObject
876 * part of the DataCache class.
879 /************************************************************************
880 * DataCache_IPersistStorage_QueryInterface (IUnknown)
882 * See Windows documentation for more details on IUnknown methods.
884 static HRESULT WINAPI DataCache_IPersistStorage_QueryInterface(
885 IPersistStorage* iface,
886 REFIID riid,
887 void** ppvObject)
889 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
891 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
894 /************************************************************************
895 * DataCache_IPersistStorage_AddRef (IUnknown)
897 * See Windows documentation for more details on IUnknown methods.
899 static ULONG WINAPI DataCache_IPersistStorage_AddRef(
900 IPersistStorage* iface)
902 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
904 return IUnknown_AddRef(this->outerUnknown);
907 /************************************************************************
908 * DataCache_IPersistStorage_Release (IUnknown)
910 * See Windows documentation for more details on IUnknown methods.
912 static ULONG WINAPI DataCache_IPersistStorage_Release(
913 IPersistStorage* iface)
915 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
917 return IUnknown_Release(this->outerUnknown);
920 /************************************************************************
921 * DataCache_GetClassID (IPersistStorage)
923 * The data cache doesn't implement this method.
925 * See Windows documentation for more details on IPersistStorage methods.
927 static HRESULT WINAPI DataCache_GetClassID(
928 IPersistStorage* iface,
929 CLSID* pClassID)
931 TRACE("(%p, %p)\n", iface, pClassID);
932 return E_NOTIMPL;
935 /************************************************************************
936 * DataCache_IsDirty (IPersistStorage)
938 * Until we actully connect to a running object and retrieve new
939 * information to it, we never get dirty.
941 * See Windows documentation for more details on IPersistStorage methods.
943 static HRESULT WINAPI DataCache_IsDirty(
944 IPersistStorage* iface)
946 TRACE("(%p)\n", iface);
948 return S_FALSE;
951 /************************************************************************
952 * DataCache_InitNew (IPersistStorage)
954 * The data cache implementation of IPersistStorage_InitNew simply stores
955 * the storage pointer.
957 * See Windows documentation for more details on IPersistStorage methods.
959 static HRESULT WINAPI DataCache_InitNew(
960 IPersistStorage* iface,
961 IStorage* pStg)
963 TRACE("(%p, %p)\n", iface, pStg);
965 return IPersistStorage_Load(iface, pStg);
968 /************************************************************************
969 * DataCache_Load (IPersistStorage)
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.
976 * See Windows documentation for more details on IPersistStorage methods.
978 static HRESULT WINAPI DataCache_Load(
979 IPersistStorage* iface,
980 IStorage* pStg)
982 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
984 TRACE("(%p, %p)\n", iface, pStg);
986 if (this->presentationStorage != NULL)
988 IStorage_Release(this->presentationStorage);
991 this->presentationStorage = pStg;
993 if (this->presentationStorage != NULL)
995 IStorage_AddRef(this->presentationStorage);
997 return S_OK;
1000 /************************************************************************
1001 * DataCache_Save (IPersistStorage)
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.
1008 * See Windows documentation for more details on IPersistStorage methods.
1010 static HRESULT WINAPI DataCache_Save(
1011 IPersistStorage* iface,
1012 IStorage* pStg,
1013 BOOL fSameAsLoad)
1015 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1017 TRACE("(%p, %p, %d)\n", iface, pStg, fSameAsLoad);
1019 if ( (!fSameAsLoad) &&
1020 (this->presentationStorage!=NULL) )
1022 return IStorage_CopyTo(this->presentationStorage,
1024 NULL,
1025 NULL,
1026 pStg);
1029 return S_OK;
1032 /************************************************************************
1033 * DataCache_SaveCompleted (IPersistStorage)
1035 * This method is called to tell the cache to release the storage
1036 * pointer it's currentlu holding.
1038 * See Windows documentation for more details on IPersistStorage methods.
1040 static HRESULT WINAPI DataCache_SaveCompleted(
1041 IPersistStorage* iface,
1042 IStorage* pStgNew)
1044 TRACE("(%p, %p)\n", iface, pStgNew);
1046 if (pStgNew)
1049 * First, make sure we get our hands off any storage we have.
1052 IPersistStorage_HandsOffStorage(iface);
1055 * Then, attach to the new storage.
1058 DataCache_Load(iface, pStgNew);
1061 return S_OK;
1064 /************************************************************************
1065 * DataCache_HandsOffStorage (IPersistStorage)
1067 * This method is called to tell the cache to release the storage
1068 * pointer it's currentlu holding.
1070 * See Windows documentation for more details on IPersistStorage methods.
1072 static HRESULT WINAPI DataCache_HandsOffStorage(
1073 IPersistStorage* iface)
1075 _ICOM_THIS_From_IPersistStorage(DataCache, iface);
1077 TRACE("(%p)\n", iface);
1079 if (this->presentationStorage != NULL)
1081 IStorage_Release(this->presentationStorage);
1082 this->presentationStorage = NULL;
1085 return S_OK;
1088 /*********************************************************
1089 * Method implementation for the IViewObject2
1090 * part of the DataCache class.
1093 /************************************************************************
1094 * DataCache_IViewObject2_QueryInterface (IUnknown)
1096 * See Windows documentation for more details on IUnknown methods.
1098 static HRESULT WINAPI DataCache_IViewObject2_QueryInterface(
1099 IViewObject2* iface,
1100 REFIID riid,
1101 void** ppvObject)
1103 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1105 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1108 /************************************************************************
1109 * DataCache_IViewObject2_AddRef (IUnknown)
1111 * See Windows documentation for more details on IUnknown methods.
1113 static ULONG WINAPI DataCache_IViewObject2_AddRef(
1114 IViewObject2* iface)
1116 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1118 return IUnknown_AddRef(this->outerUnknown);
1121 /************************************************************************
1122 * DataCache_IViewObject2_Release (IUnknown)
1124 * See Windows documentation for more details on IUnknown methods.
1126 static ULONG WINAPI DataCache_IViewObject2_Release(
1127 IViewObject2* iface)
1129 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1131 return IUnknown_Release(this->outerUnknown);
1134 /************************************************************************
1135 * DataCache_Draw (IViewObject2)
1137 * This method will draw the cached representation of the object
1138 * to the given device context.
1140 * See Windows documentation for more details on IViewObject2 methods.
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)
1155 PresentationDataHeader presData;
1156 HMETAFILE presMetafile = 0;
1157 HRESULT hres;
1159 _ICOM_THIS_From_IViewObject2(DataCache, iface);
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);
1174 * Sanity check
1176 if (lprcBounds==NULL)
1177 return E_INVALIDARG;
1180 * First, we need to retrieve the dimensions of the
1181 * image in the metafile.
1183 hres = DataCache_ReadPresentationData(this,
1184 dwDrawAspect,
1185 &presData);
1187 if (FAILED(hres))
1188 return hres;
1191 * Then, we can extract the metafile itself from the cached
1192 * data.
1194 * FIXME Unless it isn't a metafile. I think it could be any CF_XXX type,
1195 * particularly CF_DIB.
1197 presMetafile = DataCache_ReadPresMetafile(this,
1198 dwDrawAspect);
1201 * If we have a metafile, just draw baby...
1202 * We have to be careful not to modify the state of the
1203 * DC.
1205 if (presMetafile!=0)
1207 INT prevMapMode = SetMapMode(hdcDraw, MM_ANISOTROPIC);
1208 SIZE oldWindowExt;
1209 SIZE oldViewportExt;
1210 POINT oldViewportOrg;
1212 SetWindowExtEx(hdcDraw,
1213 presData.dwObjectExtentX,
1214 presData.dwObjectExtentY,
1215 &oldWindowExt);
1217 SetViewportExtEx(hdcDraw,
1218 lprcBounds->right - lprcBounds->left,
1219 lprcBounds->bottom - lprcBounds->top,
1220 &oldViewportExt);
1222 SetViewportOrgEx(hdcDraw,
1223 lprcBounds->left,
1224 lprcBounds->top,
1225 &oldViewportOrg);
1227 PlayMetaFile(hdcDraw, presMetafile);
1229 SetWindowExtEx(hdcDraw,
1230 oldWindowExt.cx,
1231 oldWindowExt.cy,
1232 NULL);
1234 SetViewportExtEx(hdcDraw,
1235 oldViewportExt.cx,
1236 oldViewportExt.cy,
1237 NULL);
1239 SetViewportOrgEx(hdcDraw,
1240 oldViewportOrg.x,
1241 oldViewportOrg.y,
1242 NULL);
1244 SetMapMode(hdcDraw, prevMapMode);
1246 DeleteMetaFile(presMetafile);
1249 return S_OK;
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)
1261 FIXME("stub\n");
1262 return E_NOTIMPL;
1265 static HRESULT WINAPI DataCache_Freeze(
1266 IViewObject2* iface,
1267 DWORD dwDrawAspect,
1268 LONG lindex,
1269 void* pvAspect,
1270 DWORD* pdwFreeze)
1272 FIXME("stub\n");
1273 return E_NOTIMPL;
1276 static HRESULT WINAPI DataCache_Unfreeze(
1277 IViewObject2* iface,
1278 DWORD dwFreeze)
1280 FIXME("stub\n");
1281 return E_NOTIMPL;
1284 /************************************************************************
1285 * DataCache_SetAdvise (IViewObject2)
1287 * This sets-up an advisory sink with the data cache. When the object's
1288 * view changes, this sink is called.
1290 * See Windows documentation for more details on IViewObject2 methods.
1292 static HRESULT WINAPI DataCache_SetAdvise(
1293 IViewObject2* iface,
1294 DWORD aspects,
1295 DWORD advf,
1296 IAdviseSink* pAdvSink)
1298 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1300 TRACE("(%p, %lx, %lx, %p)\n", iface, aspects, advf, pAdvSink);
1303 * A call to this function removes the previous sink
1305 if (this->sinkInterface != NULL)
1307 IAdviseSink_Release(this->sinkInterface);
1308 this->sinkInterface = NULL;
1309 this->sinkAspects = 0;
1310 this->sinkAdviseFlag = 0;
1314 * Now, setup the new one.
1316 if (pAdvSink!=NULL)
1318 this->sinkInterface = pAdvSink;
1319 this->sinkAspects = aspects;
1320 this->sinkAdviseFlag = advf;
1322 IAdviseSink_AddRef(this->sinkInterface);
1326 * When the ADVF_PRIMEFIRST flag is set, we have to advise the
1327 * sink immediately.
1329 if (advf & ADVF_PRIMEFIRST)
1331 DataCache_FireOnViewChange(this,
1332 DVASPECT_CONTENT,
1333 -1);
1336 return S_OK;
1339 /************************************************************************
1340 * DataCache_GetAdvise (IViewObject2)
1342 * This method queries the current state of the advise sink
1343 * installed on the data cache.
1345 * See Windows documentation for more details on IViewObject2 methods.
1347 static HRESULT WINAPI DataCache_GetAdvise(
1348 IViewObject2* iface,
1349 DWORD* pAspects,
1350 DWORD* pAdvf,
1351 IAdviseSink** ppAdvSink)
1353 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1355 TRACE("(%p, %p, %p, %p)\n", iface, pAspects, pAdvf, ppAdvSink);
1358 * Just copy all the requested values.
1360 if (pAspects!=NULL)
1361 *pAspects = this->sinkAspects;
1363 if (pAdvf!=NULL)
1364 *pAdvf = this->sinkAdviseFlag;
1366 if (ppAdvSink!=NULL)
1368 IAdviseSink_QueryInterface(this->sinkInterface,
1369 &IID_IAdviseSink,
1370 (void**)ppAdvSink);
1373 return S_OK;
1376 /************************************************************************
1377 * DataCache_GetExtent (IViewObject2)
1379 * This method retrieves the "natural" size of this cached object.
1381 * See Windows documentation for more details on IViewObject2 methods.
1383 static HRESULT WINAPI DataCache_GetExtent(
1384 IViewObject2* iface,
1385 DWORD dwDrawAspect,
1386 LONG lindex,
1387 DVTARGETDEVICE* ptd,
1388 LPSIZEL lpsizel)
1390 PresentationDataHeader presData;
1391 HRESULT hres = E_FAIL;
1393 _ICOM_THIS_From_IViewObject2(DataCache, iface);
1395 TRACE("(%p, %lx, %ld, %p, %p)\n",
1396 iface, dwDrawAspect, lindex, ptd, lpsizel);
1399 * Sanity check
1401 if (lpsizel==NULL)
1402 return E_POINTER;
1405 * Initialize the out parameter.
1407 lpsizel->cx = 0;
1408 lpsizel->cy = 0;
1411 * This flag should be set to -1.
1413 if (lindex!=-1)
1414 FIXME("Unimplemented flag lindex = %ld\n", lindex);
1417 * Right now, we support only the callback from
1418 * the default handler.
1420 if (ptd!=NULL)
1421 FIXME("Unimplemented ptd = %p\n", ptd);
1424 * Get the presentation information from the
1425 * cache.
1427 hres = DataCache_ReadPresentationData(this,
1428 dwDrawAspect,
1429 &presData);
1431 if (SUCCEEDED(hres))
1433 lpsizel->cx = presData.dwObjectExtentX;
1434 lpsizel->cy = presData.dwObjectExtentY;
1438 * This method returns OLE_E_BLANK when it fails.
1440 if (FAILED(hres))
1441 hres = OLE_E_BLANK;
1443 return hres;
1447 /*********************************************************
1448 * Method implementation for the IOleCache2
1449 * part of the DataCache class.
1452 /************************************************************************
1453 * DataCache_IOleCache2_QueryInterface (IUnknown)
1455 * See Windows documentation for more details on IUnknown methods.
1457 static HRESULT WINAPI DataCache_IOleCache2_QueryInterface(
1458 IOleCache2* iface,
1459 REFIID riid,
1460 void** ppvObject)
1462 _ICOM_THIS_From_IOleCache2(DataCache, iface);
1464 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1467 /************************************************************************
1468 * DataCache_IOleCache2_AddRef (IUnknown)
1470 * See Windows documentation for more details on IUnknown methods.
1472 static ULONG WINAPI DataCache_IOleCache2_AddRef(
1473 IOleCache2* iface)
1475 _ICOM_THIS_From_IOleCache2(DataCache, iface);
1477 return IUnknown_AddRef(this->outerUnknown);
1480 /************************************************************************
1481 * DataCache_IOleCache2_Release (IUnknown)
1483 * See Windows documentation for more details on IUnknown methods.
1485 static ULONG WINAPI DataCache_IOleCache2_Release(
1486 IOleCache2* iface)
1488 _ICOM_THIS_From_IOleCache2(DataCache, iface);
1490 return IUnknown_Release(this->outerUnknown);
1493 static HRESULT WINAPI DataCache_Cache(
1494 IOleCache2* iface,
1495 FORMATETC* pformatetc,
1496 DWORD advf,
1497 DWORD* pdwConnection)
1499 FIXME("stub\n");
1500 return E_NOTIMPL;
1503 static HRESULT WINAPI DataCache_Uncache(
1504 IOleCache2* iface,
1505 DWORD dwConnection)
1507 FIXME("stub\n");
1508 return E_NOTIMPL;
1511 static HRESULT WINAPI DataCache_EnumCache(
1512 IOleCache2* iface,
1513 IEnumSTATDATA** ppenumSTATDATA)
1515 FIXME("stub\n");
1516 return E_NOTIMPL;
1519 static HRESULT WINAPI DataCache_InitCache(
1520 IOleCache2* iface,
1521 IDataObject* pDataObject)
1523 FIXME("stub\n");
1524 return E_NOTIMPL;
1527 static HRESULT WINAPI DataCache_IOleCache2_SetData(
1528 IOleCache2* iface,
1529 FORMATETC* pformatetc,
1530 STGMEDIUM* pmedium,
1531 BOOL fRelease)
1533 FIXME("stub\n");
1534 return E_NOTIMPL;
1537 static HRESULT WINAPI DataCache_UpdateCache(
1538 IOleCache2* iface,
1539 LPDATAOBJECT pDataObject,
1540 DWORD grfUpdf,
1541 LPVOID pReserved)
1543 FIXME("stub\n");
1544 return E_NOTIMPL;
1547 static HRESULT WINAPI DataCache_DiscardCache(
1548 IOleCache2* iface,
1549 DWORD dwDiscardOptions)
1551 FIXME("stub\n");
1552 return E_NOTIMPL;
1556 /*********************************************************
1557 * Method implementation for the IOleCacheControl
1558 * part of the DataCache class.
1561 /************************************************************************
1562 * DataCache_IOleCacheControl_QueryInterface (IUnknown)
1564 * See Windows documentation for more details on IUnknown methods.
1566 static HRESULT WINAPI DataCache_IOleCacheControl_QueryInterface(
1567 IOleCacheControl* iface,
1568 REFIID riid,
1569 void** ppvObject)
1571 _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
1573 return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject);
1576 /************************************************************************
1577 * DataCache_IOleCacheControl_AddRef (IUnknown)
1579 * See Windows documentation for more details on IUnknown methods.
1581 static ULONG WINAPI DataCache_IOleCacheControl_AddRef(
1582 IOleCacheControl* iface)
1584 _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
1586 return IUnknown_AddRef(this->outerUnknown);
1589 /************************************************************************
1590 * DataCache_IOleCacheControl_Release (IUnknown)
1592 * See Windows documentation for more details on IUnknown methods.
1594 static ULONG WINAPI DataCache_IOleCacheControl_Release(
1595 IOleCacheControl* iface)
1597 _ICOM_THIS_From_IOleCacheControl(DataCache, iface);
1599 return IUnknown_Release(this->outerUnknown);
1602 static HRESULT WINAPI DataCache_OnRun(
1603 IOleCacheControl* iface,
1604 LPDATAOBJECT pDataObject)
1606 FIXME("stub\n");
1607 return E_NOTIMPL;
1610 static HRESULT WINAPI DataCache_OnStop(
1611 IOleCacheControl* iface)
1613 FIXME("stub\n");
1614 return E_NOTIMPL;
1618 * Virtual function tables for the DataCache class.
1620 static IUnknownVtbl DataCache_NDIUnknown_VTable =
1622 DataCache_NDIUnknown_QueryInterface,
1623 DataCache_NDIUnknown_AddRef,
1624 DataCache_NDIUnknown_Release
1627 static IDataObjectVtbl DataCache_IDataObject_VTable =
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
1643 static IPersistStorageVtbl DataCache_IPersistStorage_VTable =
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
1657 static IViewObject2Vtbl DataCache_IViewObject2_VTable =
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
1671 static IOleCache2Vtbl DataCache_IOleCache2_VTable =
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
1685 static IOleCacheControlVtbl DataCache_IOleCacheControl_VTable =
1687 DataCache_IOleCacheControl_QueryInterface,
1688 DataCache_IOleCacheControl_AddRef,
1689 DataCache_IOleCacheControl_Release,
1690 DataCache_OnRun,
1691 DataCache_OnStop
1694 /******************************************************************************
1695 * CreateDataCache [OLE32.@]
1697 HRESULT WINAPI CreateDataCache(
1698 LPUNKNOWN pUnkOuter,
1699 REFCLSID rclsid,
1700 REFIID riid,
1701 LPVOID* ppvObj)
1703 DataCache* newCache = NULL;
1704 HRESULT hr = S_OK;
1706 TRACE("(%s, %p, %s, %p)\n", debugstr_guid(rclsid), pUnkOuter, debugstr_guid(riid), ppvObj);
1709 * Sanity check
1711 if (ppvObj==0)
1712 return E_POINTER;
1714 *ppvObj = 0;
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.
1722 if ( (pUnkOuter!=NULL) &&
1723 (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) != 0) )
1724 return CLASS_E_NOAGGREGATION;
1727 * Try to construct a new instance of the class.
1729 newCache = DataCache_Construct(rclsid,
1730 pUnkOuter);
1732 if (newCache == 0)
1733 return E_OUTOFMEMORY;
1736 * Make sure it supports the interface required by the caller.
1738 hr = IUnknown_QueryInterface((IUnknown*)&(newCache->lpvtbl2), riid, ppvObj);
1741 * Release the reference obtained in the constructor. If
1742 * the QueryInterface was unsuccessful, it will free the class.
1744 IUnknown_Release((IUnknown*)&(newCache->lpvtbl2));
1746 return hr;
1749 /*********************************************************
1750 * Method implementation for DataCache class.
1752 static DataCache* DataCache_Construct(
1753 REFCLSID clsid,
1754 LPUNKNOWN pUnkOuter)
1756 DataCache* newObject = 0;
1759 * Allocate space for the object.
1761 newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(DataCache));
1763 if (newObject==0)
1764 return newObject;
1767 * Initialize the virtual function table.
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;
1777 * Start with one reference count. The caller of this function
1778 * must release the interface pointer when it is done.
1780 newObject->ref = 1;
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.
1788 if (pUnkOuter==NULL)
1789 pUnkOuter = (IUnknown*)&(newObject->lpvtbl2);
1791 newObject->outerUnknown = pUnkOuter;
1794 * Initialize the other members of the structure.
1796 newObject->presentationStorage = NULL;
1797 newObject->sinkAspects = 0;
1798 newObject->sinkAdviseFlag = 0;
1799 newObject->sinkInterface = 0;
1801 return newObject;