//+---------------------------------------------------------------------------- // // File: // olecache.h // // Contents: // Better implementation of Ole presentation cache // // Classes: // COleCache - ole presentation cache // CCacheEnum - enumerator for COleCache // // Functions: // // History: // Gopalk Creation Aug 23, 1996 //----------------------------------------------------------------------------- #ifndef _OLECACHE_H_ #define _OLECACHE_H_ #include #include //+---------------------------------------------------------------------------- // // Class: // COleCache // // Purpose: // Ole presentation cache maintains the presentations for // one embedding. // // For every unique FORMATETC, a cache node is created; cache // nodes encapsulate a presentation object and advise sink. // // COleCache handles persistence of cache nodes, saving (loading) // their presentation objects, format descriptions, and advise // options. // // Interface: // IUnknown (public IUnknown for aggregation purposes) // IOleCacheControl // IOleCache2 // IPersistStorage // IViewObject2 // IDataObject // m_UnkPrivate // the private IUnknown for aggregation purposes // // INTERNAL GetExtent(DWORD dwDrawAspect, LPSIZEL lpsizel); // returns the size of the aspect indicated // // Private Interface used by friend classes: // INTERNAL_(void) OnChange(DWORD dwAspect, LONG lindex, // BOOL fDirty); // CCacheNode instances use this to alert the cache to // changes to themselves so that the cache can be // marked dirty, if that is necessary // INTERNAL_(LPSTORAGE) GetStg(void); // CCacheNode uses this to obtain storage when cache // nodes are being saved // // INTERNAL_(void) DetachCacheEnum(CCacheEnum FAR* pCacheEnum); // When about to be destroyed, CCacheEnum instances // use this to request to be taken off // the list of cache enumerators that COleCache // maintains. // // Notes: // The constructor returns a pointer to the public IUnknown // of the object. The private one is available at m_UnkPrivate. // // The cache maintains its contents in an array. Ids of the // cache nodes, such as those returned from Cache(), start out // being the index of the node in the array. To detect // reuse of an array element, each id is incremented by the maximum // size of the array each time it is reused. To find an element by // id simply take (id % max_array_size). (id / max_array_size) // gives the number of times the array element has been used to // cache data. (We do not allocate all the array members at once, // but instead grow the array on demand, up to the maximum // compile-time array size, MAX_CACHELIST_ITEMS.) // If id's do not match // exactly, before taking the modulo value, we know that a // request has been made for an earlier generation of data that // no longer exists. // // The cache automatically maintains a "native format" node. // This node cannot be deleted by the user, and is always kept // up to date on disk. This node attempts to keep either a // CF_METAFILEPICT, or CF_DIB rendering, with preference in // this order. // REVIEW, it's not clear how this node ever gets loaded. // // History: // 31-Jan-95 t-ScottH add Dump method (_DEBUG only) // 11/15/93 - ChrisWe - file inspection and cleanup; // removed use of nested classes where possible; // got rid of obsolete declaration of GetOlePresStream; // moved presentation stream limits to ole2int.h; // coalesced many BOOL flags into a single unsigned // quantity // //----------------------------------------------------------------------------- // declare the array of cache node pointers // COleCache will maintain an array of these #define COLECACHEF_LOADEDSTATE 0x00000001 #define COLECACHEF_NOSCRIBBLEMODE 0x00000002 #define COLECACHEF_PBRUSHORMSDRAW 0x00000004 #define COLECACHEF_STATIC 0x00000008 #define COLECACHEF_FORMATKNOWN 0x00000010 #define COLECACHEF_OUTOFMEMORY 0x00000020 #define COLECACHEF_HANDSOFSTORAGE 0x00000040 #define COLECACHEF_CLEANEDUP 0x00000080 #define COLECACHEF_SAMEASLOAD 0x00000100 #define COLECACHEF_APICREATE 0x00000200 #ifdef _DEBUG // In debug builds, this flag is set if aggregated #define COLECACHEF_AGGREGATED 0x00001000 #endif // _DEBUG // The following flag is used for clearing out native COLECACHE FLAGS. // Remember to update the following when native formats are either // added or removed #define COLECACHEF_NATIVEFLAGS (COLECACHEF_STATIC | \ COLECACHEF_FORMATKNOWN | \ COLECACHEF_PBRUSHORMSDRAW) // TOC signature #define TOCSIGNATURE 1229865294 class COleCache : public IOleCacheControl, public IOleCache2, public IPersistStorage, public CRefExportCount, public CThreadCheck { public: COleCache(IUnknown* pUnkOuter, REFCLSID rclsid, DWORD dwCreateFlags=0); ~COleCache(); // *** IUnknown methods *** STDMETHOD(QueryInterface)(REFIID riid, LPVOID* ppv); STDMETHOD_(ULONG,AddRef)(void) ; STDMETHOD_(ULONG,Release)(void); // *** IOleCacheControl methods *** STDMETHOD(OnRun)(LPDATAOBJECT pDataObject); STDMETHOD(OnStop)(void); // *** IOleCache methods *** STDMETHOD(Cache)(LPFORMATETC lpFormatetc, DWORD advf, LPDWORD lpdwCacheId); STDMETHOD(Uncache)(DWORD dwCacheId); STDMETHOD(EnumCache)(LPENUMSTATDATA* ppenumStatData); STDMETHOD(InitCache)(LPDATAOBJECT pDataObject); STDMETHOD(SetData)(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium, BOOL fRelease); // *** IOleCache2 methods *** STDMETHOD(UpdateCache)(LPDATAOBJECT pDataObject, DWORD grfUpdf, LPVOID pReserved); STDMETHOD(DiscardCache)(DWORD dwDiscardOptions); // IPersist methods STDMETHOD(GetClassID)(LPCLSID pClassID); // IPersistStorage methods STDMETHOD(IsDirty)(void); STDMETHOD(InitNew)(LPSTORAGE pstg); STDMETHOD(Load)(LPSTORAGE pstg); STDMETHOD(Save)(LPSTORAGE pstgSave, BOOL fSameAsLoad); STDMETHOD(SaveCompleted)(LPSTORAGE pstgNew); STDMETHOD(HandsOffStorage)(void); // Other public methods, called by defhndlr and deflink HRESULT GetExtent(DWORD dwDrawAspect, LPSIZEL lpsizel); HRESULT Load(LPSTORAGE pstg, BOOL fCacheEmpty); HRESULT OnCrash(); BOOL IsEmpty() { return(!m_pCacheArray->Length()); } // Private IUnknown used in aggregation. // This has been implemented as a nested class because of // the member name collisions with the outer IUnknown. class CCacheUnkImpl : public IUnknown { public: // *** IUnknown methods *** STDMETHOD(QueryInterface)(REFIID riid, LPVOID* ppv); STDMETHOD_(ULONG,AddRef)(void) ; STDMETHOD_(ULONG,Release)(void); }; friend class CCacheUnkImpl; CCacheUnkImpl m_UnkPrivate; // vtable for private IUnknown // IDataObject implementation of the cache. // This has been implemented as a nested class because // IDataObject::SetData collides with IOleCache::SetData class CCacheDataImpl : public IDataObject { public: // IUnknown methods STDMETHOD(QueryInterface)(REFIID riid, LPVOID* ppv); STDMETHOD_(ULONG,AddRef)(void); STDMETHOD_(ULONG,Release)(void); // IDataObject methods STDMETHOD(GetData)(LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium); STDMETHOD(GetDataHere)(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium); STDMETHOD(QueryGetData)(LPFORMATETC pformatetc); STDMETHOD(GetCanonicalFormatEtc)(LPFORMATETC pformatetc, LPFORMATETC pformatetcOut); STDMETHOD(SetData)(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium, BOOL fRelease); STDMETHOD(EnumFormatEtc)(DWORD dwDirection, LPENUMFORMATETC* ppenumFormatEtc); STDMETHOD(DAdvise)(FORMATETC* pFormatetc, DWORD advf, IAdviseSink* pAdvSink, DWORD* pdwConnection); STDMETHOD(DUnadvise)(DWORD dwConnection); STDMETHOD(EnumDAdvise)(LPENUMSTATDATA* ppenumAdvise); }; friend class CCacheDataImpl; CCacheDataImpl m_Data; // vtable for IDataObject // Other public methods BOOL IsOutOfMemory() { return(m_ulFlags & COLECACHEF_OUTOFMEMORY); } private: // Private methods LPCACHENODE Locate(LPFORMATETC lpGivenForEtc, DWORD* lpdwCacheId=NULL); LPCACHENODE Locate(DWORD dwAspect, LONG lindex, DVTARGETDEVICE* ptd); LPCACHENODE UpdateCacheNodeForNative(void); void FindObjectFormat(LPSTORAGE pstg); HRESULT LoadTOC(LPSTREAM lpstream, LPSTORAGE pStg); HRESULT SaveTOC(LPSTORAGE pStg, BOOL fSameAsLoad); void AspectsUpdated(DWORD dwAspect); void CleanupFn(void); // IViewObject2 implementation of cache. // This has been implemented as a nested class because GetExtent // collides with the method on COleCache class CCacheViewImpl : public IViewObject2 { public: // IUnknown methods STDMETHOD(QueryInterface)(REFIID riid, LPVOID* ppv); STDMETHOD_(ULONG,AddRef)(void); STDMETHOD_(ULONG,Release)(void); // IViewObject methods STDMETHOD(Draw)(DWORD dwDrawAspect, LONG lindex, void FAR* pvAspect, DVTARGETDEVICE FAR* ptd, HDC hicTargetDev, HDC hdcDraw, LPCRECTL lprcBounds, LPCRECTL lprcWBounds, BOOL(CALLBACK *pfnContinue)(ULONG_PTR), ULONG_PTR dwContinue); STDMETHOD(GetColorSet)(DWORD dwDrawAspect, LONG lindex, void* pvAspect, DVTARGETDEVICE* ptd, HDC hicTargetDev, LPLOGPALETTE* ppColorSet); STDMETHOD(Freeze)(DWORD dwDrawAspect, LONG lindex, void* pvAspect, DWORD* pdwFreeze); STDMETHOD(Unfreeze)(DWORD dwFreeze); STDMETHOD(SetAdvise)(DWORD aspects, DWORD advf, LPADVISESINK pAdvSink); STDMETHOD(GetAdvise)(DWORD* pAspects, DWORD* pAdvf, LPADVISESINK* ppAdvSink); // IViewObject2 methods STDMETHOD(GetExtent)(DWORD dwDrawAspect, LONG lindex, DVTARGETDEVICE* ptd, LPSIZEL lpsizel); }; friend class CCacheViewImpl; CCacheViewImpl m_ViewObject; // vtable for IViewObject2 // IAdviseSink implementation // This has been implemented as a nested class because of the need that // the QueryInterface method on the Advise Sink should not return // cache interfaces class CAdviseSinkImpl : public IAdviseSink { public: // IUnknown methods STDMETHOD(QueryInterface)(REFIID riid, LPVOID* ppv); STDMETHOD_(ULONG,AddRef)(void); STDMETHOD_(ULONG,Release)(void); // IAdviseSink methods STDMETHOD_(void,OnDataChange)(FORMATETC* pFormatetc, STGMEDIUM* pStgmed); STDMETHOD_(void,OnViewChange)(DWORD aspect, LONG lindex); STDMETHOD_(void,OnRename)(IMoniker* pmk); STDMETHOD_(void,OnSave)(void); STDMETHOD_(void,OnClose)(void); }; friend class CAdviseSinkImpl; CAdviseSinkImpl m_AdviseSink; // Private member variables IUnknown* m_pUnkOuter; // Aggregating IUnknown LPSTORAGE m_pStg; // Storage for cache CLSID m_clsid; // CLSID of object CLIPFORMAT m_cfFormat; // Native clipformat of the object unsigned long m_ulFlags; // Cache flags CArray* m_pCacheArray; // Cache array IAdviseSink* m_pViewAdvSink; // IViewObject Advise Sink DWORD m_advfView; // IViewObject Advise control flags DWORD m_aspectsView; // Aspects notified for view changes DWORD m_dwFrozenAspects; // Frozen Aspects IDataObject* m_pDataObject; // non-NULL if running; not ref counted }; #endif //_OLECACHE_H_