windows-nt/Source/XPSP1/NT/shell/cpls/appwzdui/sccls.c
2020-09-26 16:20:57 +08:00

146 lines
3.6 KiB
C

#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,
#ifndef DOWNLEVEL_PLATFORM
&c_CFVtbl, &CLSID_DarwinAppPublisher, CDarwinAppPublisher_CreateInstance,
COCREATEONLY,
#endif //DOWNLEVEL_PLATFORM
&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;
}