// //************************************************************************** // // BOleFact.cpp -- Implements the server-side helper for allowing OLE2 to // create objects made available by Bolero server apps. // // Copyright (c) 1993,94 by Borland International, Inc. All rights reserved // //************************************************************************** #include "BOleFact.h" #include "BOleSvc.h" #include "BOleIPS.h" #include "BOleCMan.h" // // DllGetClassObject // // // // STDAPI DllGetClassObject(REFCLSID clsid, REFIID iid, void FAR* FAR* ppv) { HRESULT hRes = ResultFromScode(E_OUTOFMEMORY); return hRes; } STDAPI DllCanUnloadNow() { return ResultFromScode( S_OK ); } BOleFact::BOleFact(BOleClassManager * pFact, IBUnknownMain *pOuter): RefCnt (1), pObjCM(NULL), hReg (0L), regId (0), dwRegisterActiveObject (0), id (CLSID_NULL), BOleComponent(pFact, (IBUnknownMain *) this), pIPEFact (NULL) { } BOleFact::~BOleFact() { if (pIPEFact) { pIPEFact->Release(); pIPEFact = NULL; } } HRESULT _IFUNC BOleFact::QueryInterfaceMain(REFIID iid, LPVOID FAR* ppv) { HRESULT hr = ResultFromScode(E_NOINTERFACE); *ppv = NULL; // interfaces SUCCEEDED(hr = IBClass_QueryInterface(this, iid, ppv)) // base classes || SUCCEEDED(hr = BOleComponent::QueryInterfaceMain(iid, ppv)) // helpers ; return hr; } HRESULT _IFUNC BOleFact::Init (BOOL fInProc, LPCOLESTR szProgId, IBClassMgr *pCM, BCID rid) { pObjCM = pCM; regId = rid; // If the user's object is capable of being instantiated in its own // container, create a special BOleInProcFactory // if (fInProc) { pIPEFact = new BOleInProcFactory (pFactory, this, id); if (!pIPEFact) return ResultFromScode(E_OUTOFMEMORY); } return CLSIDFromProgID(szProgId, &id); } HRESULT _IFUNC BOleFact::Register (BOOL fSingleUse) { HRESULT hErr; // register the class factory for this id // if (!SUCCEEDED(hErr = CoRegisterClassObject( id, (IClassFactory *)this, CLSCTX_LOCAL_SERVER, fSingleUse ? REGCLS_SINGLEUSE : REGCLS_MULTI_SEPARATE, &hReg))) { OLEHRES("Failed Registering", hErr); } // Register the embedding helper factory if we embed in ourselves if (pIPEFact) { if (!SUCCEEDED(hErr = pIPEFact->Register (fSingleUse))) return hErr; } // The online dox for CoLockObjectExternal say we should do this here // if (SUCCEEDED(hErr)) { LPCLASSFACTORY pWorkAround = this; CoLockObjectExternal (pWorkAround, TRUE, TRUE); } // if the class manager supports automation let's register it as "Active" // IDispatch *pDispatch; if (SUCCEEDED(pObjCM->QueryInterface(IID_IDispatch, &(LPVOID)pDispatch))) { RegisterActiveObject (pDispatch, id, NULL, &dwRegisterActiveObject); pDispatch->Release(); } return hErr; } HRESULT _IFUNC BOleFact::Revoke () { if (hReg) { LPCLASSFACTORY pWorkAround = this; CoLockObjectExternal (pWorkAround, FALSE, TRUE); CoRevokeClassObject( hReg); hReg = 0; } if (dwRegisterActiveObject) { RevokeActiveObject (dwRegisterActiveObject, NULL); dwRegisterActiveObject = 0; } if (pIPEFact) { pIPEFact->Revoke (); pIPEFact->Release (); pIPEFact = NULL; } return NOERROR; } HRESULT _IFUNC BOleFact::GetClassID (LPCLSID pClass) { *pClass = id; return NOERROR; } BOOL _IFUNC BOleFact::IsA (REFCLSID cid) { return IsEqualCLSID(cid, id); } HRESULT _IFUNC BOleFact::CreateInstance(IUnknown FAR* pUnk, REFIID iid, LPVOID FAR* ppv) { HRESULT hr = ResultFromScode(E_FAIL); *ppv = 0L; PIUnknown pObj; IBClassMgr * pICM; if (SUCCEEDED(pObjCM->QueryInterface(IID_IBClassMgr, &(LPVOID)pICM))) { if (SUCCEEDED(pICM->ComponentCreate(&pObj, pUnk, regId))) { if (pUnk && iid == IID_IUnknown) { hr = NOERROR; *ppv = pObj; // always give out main IUnknown } else { hr = pObj->QueryInterface(iid, ppv); pObj->Release(); // QI bumps } } pICM->Release(); } return hr; } HRESULT _IFUNC BOleFact::LockServer( BOOL fLock ) { LPCLASSFACTORY pICF = this; CoLockObjectExternal(pICF, fLock, TRUE); pFactory->ServerCount( fLock ? 1L : -1L); return NOERROR; } // Used by DllGetClassObject to return the interface to the factory which // creates the default handler which will create the in-proc server object. // HRESULT _IFUNC BOleFact::GetEmbeddingHelperFactory (LPUNKNOWN *ppF) { if (pIPEFact) { *ppF = pIPEFact; (*ppF)->AddRef(); return NOERROR; } else { *ppF = NULL; return ResultFromScode(E_FAIL); } } // When Bolero container-side dialog boxes need to know whether to put the // CLSID for our own factories in the dialog box, this is how they find out // BOOL _IFUNC BOleFact::AllowEmbedFromSelf () { return pIPEFact ? TRUE : FALSE; } //************************************************************************** // // BOleInProcFactory -- The role of this factory is to load the default // handler on the server side when the container // side of an app needs to instantiate an object it // serves. // // If we don't do this, the RPC/handler system // creates the server object as if it were an inproc // server with no handler, but our EXE-based objects // must use the default handler. // //************************************************************************** //*********************************** // // Implementation methods // //*********************************** BOleInProcFactory::BOleInProcFactory (BOleClassManager *pCM, BOleFact FAR *pF, REFIID iid) : BOleComponent(pCM, NULL), iidServer (iid), nRef (1), pRealFactory (pF), regCookie (0) { pF->AddRef(); } BOleInProcFactory::~BOleInProcFactory () { if (pRealFactory) { pRealFactory->Release(); pRealFactory = NULL; } } HRESULT _IFUNC BOleInProcFactory::Register (BOOL fSingleUse) { HRESULT hr = ::CoRegisterClassObject ( iidServer, this, CLSCTX_INPROC_SERVER, fSingleUse ? REGCLS_SINGLEUSE : REGCLS_MULTI_SEPARATE, ®Cookie); if (SUCCEEDED(hr)) { LPCLASSFACTORY pWorkAround = this; CoLockObjectExternal (pWorkAround, TRUE, TRUE); } return hr; } HRESULT _IFUNC BOleInProcFactory::Revoke () { if (regCookie) { LPCLASSFACTORY pWorkAround = this; CoLockObjectExternal (pWorkAround, FALSE, TRUE); return ::CoRevokeClassObject (regCookie); } if (pRealFactory) { // this breaks a cycle when we're pRealFactory->Release(); // in the embed from file "registered case" pRealFactory = NULL; } // if we don't register we expect releasing BOleInProcFactory // to release BOleFact (since BOleInProcFactory is returned // from DllGetClassObject) // return ResultFromScode (E_FAIL); } //*********************************** // // IUnknown methods // //*********************************** HRESULT _IFUNC BOleInProcFactory::QueryInterfaceMain(REFIID riid, LPVOID FAR *ppObj) { HRESULT hr; *ppObj = NULL; if (SUCCEEDED(hr = IClassFactory_QueryInterface (this, riid, ppObj))) { } else if (SUCCEEDED(hr = BOleComponent::QueryInterfaceMain(riid, ppObj))) { } return hr; } //*********************************** // // IClassFactory methods // //*********************************** HRESULT _IFUNC BOleInProcFactory::CreateInstance (LPUNKNOWN pUnkOuter, REFIID iidContainer, LPVOID FAR* ppv) { // We ask OLE2 to create an instance // of the default handler. The default handler uses pRealFactory to // call back to us when it's time to create the real server object. // return ::OleCreateEmbeddingHelper (iidServer, pUnkOuter, EMBDHLP_INPROC_SERVER | EMBDHLP_DELAYCREATE, pRealFactory, iidContainer, ppv); } HRESULT _IFUNC BOleInProcFactory::LockServer (BOOL fLock) { ::CoLockObjectExternal (this, fLock, TRUE); pFactory->ServerCount (fLock ? 1L : -1L); return NOERROR; }