#include "priv.h" #include "dochost.h" #define DM_CACHEOLESERVER DM_TRACE #define HACK_CACHE_OBJECT_TOO class CClassHolder : IUnknown { public: CClassHolder(); HRESULT Initialize(const CLSID* pclsid); // *** IUnknown methods *** virtual STDMETHODIMP QueryInterface(REFIID riid, LPVOID * ppvObj); virtual STDMETHODIMP_(ULONG) AddRef(void) ; virtual STDMETHODIMP_(ULONG) Release(void); friend IUnknown* ClassHolder_Create(const CLSID* pclsid); protected: ~CClassHolder(); UINT _cRef; IClassFactory* _pcf; DWORD _dwAppHack; #ifdef HACK_CACHE_OBJECT_TOO IUnknown* _punk; #endif // HACK_CACHE_OBJECT_TOO }; HRESULT CClassHolder::QueryInterface(REFIID riid, LPVOID * ppvObj) { static const QITAB qit[] = { QITABENTMULTI(CClassHolder, IDiscardableBrowserProperty, IUnknown), { 0 }, }; return QISearch(this, qit, riid, ppvObj); } ULONG CClassHolder::AddRef() { _cRef++; return _cRef; } ULONG CClassHolder::Release() { _cRef--; if (_cRef > 0) return _cRef; delete this; return 0; } CClassHolder::CClassHolder() : _cRef(1) { } HRESULT CClassHolder::Initialize(const CLSID *pclsid) { // we need local server here for word, excel, ... HRESULT hr = CoGetClassObject(*pclsid, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, 0, IID_PPV_ARG(IClassFactory, &_pcf)); TraceMsg(DM_CACHEOLESERVER, "CCH::CCH Just called CoGetClassObject %x", hr); if (SUCCEEDED(hr)) { ::GetAppHackFlags(NULL, pclsid, &_dwAppHack); _pcf->LockServer(TRUE); #ifdef HACK_CACHE_OBJECT_TOO hr = _pcf->CreateInstance(NULL, IID_PPV_ARG(IUnknown, &_punk)); if ((_dwAppHack & BROWSERFLAG_INITNEWTOKEEP) && SUCCEEDED(hr)) { TraceMsg(TF_SHDAPPHACK, "CCH::CCH hack for Excel. Call InitNew to keep it running"); // // This InitNew keeps Excel running // IPersistStorage* pps; HRESULT hrT = _punk->QueryInterface(IID_PPV_ARG(IPersistStorage, &pps)); if (SUCCEEDED(hrT)) { IStorage* pstg; hrT = StgCreateDocfile(NULL, STGM_DIRECT | STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE, 0, &pstg); if (SUCCEEDED(hrT)) { TraceMsg(DM_TRACE, "CCLH::ctor calling InitNew()"); pps->InitNew(pstg); pstg->Release(); } else { TraceMsg(DM_TRACE, "CCLH::ctor StgCreateDocfile failed %x", hrT); } pps->Release(); } else { TraceMsg(DM_TRACE, "CCLH::ctor QI to IPersistStorage failed %x", hrT); } } #endif } return hr; } CClassHolder::~CClassHolder() { if (_pcf) { #ifdef HACK_CACHE_OBJECT_TOO if (_punk) { _punk->Release(); } #endif _pcf->LockServer(FALSE); ATOMICRELEASE(_pcf); } } IUnknown* ClassHolder_Create(const CLSID* pclsid) { IUnknown *punk = NULL; CClassHolder *pch = new CClassHolder(); if (pch) { if (SUCCEEDED(pch->Initialize(pclsid))) { pch->QueryInterface(IID_PPV_ARG(IUnknown, &punk)); } pch->Release(); } return punk; }