142 lines
3.6 KiB
C++
142 lines
3.6 KiB
C++
#include "priv.h"
|
|
#include "dochost.h"
|
|
|
|
#define DM_CACHEOLESERVER DM_TRACE
|
|
|
|
#define HACK_CACHE_OBJECT_TOO
|
|
// #define HACK_LOCKRUNNING_TOO
|
|
|
|
class CClassHolder : IUnknown
|
|
{
|
|
protected:
|
|
// *** 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);
|
|
|
|
CClassHolder(const CLSID* pclsid);
|
|
~CClassHolder();
|
|
|
|
UINT _cRef;
|
|
IClassFactory* _pcf;
|
|
DWORD _dwAppHack;
|
|
|
|
#ifdef HACK_CACHE_OBJECT_TOO
|
|
IUnknown* _punk;
|
|
#ifdef HACK_LOCKRUNNING_TOO
|
|
IRunnableObject* _pro;
|
|
#endif
|
|
#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(const CLSID* pclsid) : _cRef(1)
|
|
{
|
|
HRESULT hres;
|
|
hres = CoGetClassObject(*pclsid, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
|
|
0, IID_IClassFactory, (LPVOID*)&_pcf);
|
|
|
|
TraceMsg(DM_CACHEOLESERVER, "CCH::CCH Just called CoGetClassObject %x", hres);
|
|
|
|
if (SUCCEEDED(hres)) {
|
|
::GetAppHackFlags(NULL, pclsid, &_dwAppHack);
|
|
|
|
_pcf->LockServer(TRUE);
|
|
|
|
#ifdef HACK_CACHE_OBJECT_TOO
|
|
hres = _pcf->CreateInstance(NULL, IID_IUnknown, (LPVOID*)&_punk);
|
|
|
|
if ((_dwAppHack & BROWSERFLAG_INITNEWTOKEEP) && SUCCEEDED(hres)) {
|
|
|
|
TraceMsg(TF_SHDAPPHACK, "CCH::CCH hack for Excel. Call InitNew to keep it running");
|
|
|
|
//
|
|
// This InitNew keeps Excel running
|
|
//
|
|
IPersistStorage* pps;
|
|
HRESULT hresT;
|
|
hresT = _punk->QueryInterface(IID_IPersistStorage, (LPVOID*)&pps);
|
|
if (SUCCEEDED(hresT)) {
|
|
IStorage* pstg;
|
|
hresT = StgCreateDocfile(NULL,
|
|
STGM_DIRECT | STGM_CREATE | STGM_READWRITE
|
|
| STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE,
|
|
0, &pstg);
|
|
if (SUCCEEDED(hresT)) {
|
|
TraceMsg(DM_TRACE, "CCLH::ctor calling InitNew()");
|
|
pps->InitNew(pstg);
|
|
pstg->Release();
|
|
} else {
|
|
TraceMsg(DM_TRACE, "CCLH::ctor StgCreateDocfile failed %x", hresT);
|
|
}
|
|
pps->Release();
|
|
} else {
|
|
TraceMsg(DM_TRACE, "CCLH::ctor QI to IPersistStorage failed %x", hresT);
|
|
}
|
|
#ifdef HACK_LOCKRUNNING_TOO
|
|
hres = _punk->QueryInterface(IID_IRunnableObject, (LPVOID*)&_pro);
|
|
if (SUCCEEDED(hres)) {
|
|
TraceMsg(DM_CACHEOLESERVER, "CCH::CCH This is runnable. Keep it running %x", _pro);
|
|
OleRun(_pro);
|
|
OleLockRunning(_pro, TRUE, TRUE);
|
|
}
|
|
#endif
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
CClassHolder::~CClassHolder()
|
|
{
|
|
if (_pcf) {
|
|
#ifdef HACK_CACHE_OBJECT_TOO
|
|
if (_punk) {
|
|
#ifdef HACK_LOCKRUNNING_TOO
|
|
if (_pro) {
|
|
OleLockRunning(_pro, FALSE, TRUE);
|
|
_pro->Release();
|
|
}
|
|
#endif
|
|
_punk->Release();
|
|
}
|
|
#endif
|
|
_pcf->LockServer(FALSE);
|
|
ATOMICRELEASE(_pcf);
|
|
}
|
|
}
|
|
|
|
IUnknown* ClassHolder_Create(const CLSID* pclsid)
|
|
{
|
|
return new CClassHolder(pclsid);
|
|
}
|
|
|
|
|
|
|