#include "priv.h" #include "sccls.h" extern const IClassFactoryVtbl c_CFVtbl; // forward // // This array holds information needed for ClassFactory. // // PERF: this table should be ordered in most-to-least used order // const OBJECTINFO g_ObjectInfo[] = { &c_CFVtbl, &CLSID_ShellAppManager, CShellAppManager_CreateInstance, COCREATEONLY, &c_CFVtbl, &CLSID_DarwinAppPublisher, CDarwinAppPublisher_CreateInstance, COCREATEONLY, &c_CFVtbl, &CLSID_EnumInstalledApps, CEnumInstalledApps_CreateInstance, COCREATEONLY, NULL, NULL, NULL, NULL, NULL, 0, 0,0, } ; // static class factory (no allocs!) STDMETHODIMP CClassFactory_QueryInterface(IClassFactory *pcf, REFIID riid, void **ppvObj) { if (IsEqualIID(riid, &IID_IClassFactory) || IsEqualIID(riid, &IID_IUnknown)) { *ppvObj = (void *)pcf; DllAddRef(); return NOERROR; } *ppvObj = NULL; return E_NOINTERFACE; } STDMETHODIMP_(ULONG) CClassFactory_AddRef(IClassFactory *pcf) { DllAddRef(); return 2; } STDMETHODIMP_(ULONG) CClassFactory_Release(IClassFactory *pcf) { DllRelease(); return 1; } STDMETHODIMP CClassFactory_CreateInstance(IClassFactory *pcf, IUnknown *punkOuter, REFIID riid, void **ppv) { *ppv = NULL; if (punkOuter && !IsEqualIID(riid, &IID_IUnknown)) { // It is technically illegal to aggregate an object and request // any interface other than IUnknown. Enforce this. // return CLASS_E_NOAGGREGATION; } else { OBJECTINFO *this = IToClass(OBJECTINFO, cf, pcf); IUnknown *punk; HRESULT hres; if (punkOuter) { if (!(this->dwClassFactFlags & OIF_ALLOWAGGREGATION)) return CLASS_E_NOAGGREGATION; } // if we're aggregated, then we know we're looking for an // IUnknown so we should return punk directly. otherwise // we need to QI. // hres = this->pfnCreateInstance(punkOuter, &punk, this); if (SUCCEEDED(hres)) { if (punkOuter) { *ppv = (LPVOID)punk; } else { hres = punk->lpVtbl->QueryInterface(punk, riid, ppv); punk->lpVtbl->Release(punk); } } ASSERT(FAILED(hres) ? *ppv == NULL : TRUE); return hres; } } STDMETHODIMP CClassFactory_LockServer(IClassFactory *pcf, BOOL fLock) { extern LONG g_cRefThisDll; if (fLock) DllAddRef(); else DllRelease(); TraceMsg(DM_TRACE, "sccls: LockServer(%s) to %d", fLock ? TEXT("LOCK") : TEXT("UNLOCK"), g_cRefThisDll); return S_OK; } const IClassFactoryVtbl c_CFVtbl = { CClassFactory_QueryInterface, CClassFactory_AddRef, CClassFactory_Release, CClassFactory_CreateInstance, CClassFactory_LockServer }; STDAPI GetClassObject(REFCLSID rclsid, REFIID riid, void **ppv) { HRESULT hres = CLASS_E_CLASSNOTAVAILABLE; extern IClassFactory *CInstClassFactory_Create(const CLSID *pInstID); if (IsEqualIID(riid, &IID_IClassFactory) || IsEqualIID(riid, &IID_IUnknown)) { const OBJECTINFO *pcls; for (pcls = g_ObjectInfo; pcls->pclsid; pcls++) { if (IsEqualGUID(rclsid, pcls->pclsid)) { *ppv = (void *)&(pcls->cf); DllAddRef(); // class factory holds DLL ref count return NOERROR; } } } *ppv = NULL; return CLASS_E_CLASSNOTAVAILABLE; }