windows-nt/Source/XPSP1/NT/shell/explorer/classfac.cpp
2020-09-26 16:20:57 +08:00

131 lines
3.4 KiB
C++

#include "cabinet.h"
///////////////////////////////////////////////////////////////////////////////////////
//
// class factory for explorer.exe
//
// These objects do not exist in the registry but rather are registered dynamically at
// runtime. Since ClassFactory_Start is called on the the tray's thread, all objects
// will be registered on that thread.
//
///////////////////////////////////////////////////////////////////////////////////////
typedef HRESULT (*LPFNCREATEOBJINSTANCE)(IUnknown* pUnkOuter, IUnknown** ppunk);
class CDynamicClassFactory : public IClassFactory
{
public:
// *** IUnknown ***
STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
{
static const QITAB qit[] =
{
QITABENT(CDynamicClassFactory, IClassFactory),
{ 0 },
};
return QISearch(this, qit, riid, ppv);
}
STDMETHODIMP_(ULONG) AddRef() { return ++_cRef; }
STDMETHODIMP_(ULONG) Release()
{
if (--_cRef > 0)
{
return _cRef;
}
delete this;
return 0;
}
// *** IClassFactory ***
STDMETHODIMP CreateInstance(IUnknown *punkOuter, REFIID riid, void **ppv)
{
*ppv = NULL;
IUnknown *punk;
HRESULT hr = _pfnCreate(punkOuter, &punk);
if (SUCCEEDED(hr))
{
hr = punk->QueryInterface(riid, ppv);
punk->Release();
}
return hr;
}
STDMETHODIMP LockServer(BOOL) { return S_OK; }
// *** misc public methods ***
HRESULT Register()
{
return CoRegisterClassObject(*_pclsid, this, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
REGCLS_MULTIPLEUSE, &_dwClassObject);
}
HRESULT Revoke()
{
HRESULT hr = CoRevokeClassObject(_dwClassObject);
_dwClassObject = 0;
return hr;
}
CDynamicClassFactory(CLSID const* pclsid, LPFNCREATEOBJINSTANCE pfnCreate) : _pclsid(pclsid),
_pfnCreate(pfnCreate), _cRef(1) {}
private:
CLSID const* _pclsid;
LPFNCREATEOBJINSTANCE _pfnCreate;
DWORD _dwClassObject;
ULONG _cRef;
};
HRESULT CTaskBand_CreateInstance(IUnknown* punkOuter, IUnknown** ppunk);
HRESULT CTrayBandSiteService_CreateInstance(IUnknown* punkOuter, IUnknown** ppunk);
HRESULT CTrayNotifyStub_CreateInstance(IUnknown* punkOuter, IUnknown** ppunk);
static const struct
{
CLSID const* pclsid;
LPFNCREATEOBJINSTANCE pfnCreate;
}
c_ClassParams[] =
{
{ &CLSID_TaskBand, CTaskBand_CreateInstance },
{ &CLSID_TrayBandSiteService, CTrayBandSiteService_CreateInstance },
{ &CLSID_TrayNotify, CTrayNotifyStub_CreateInstance },
};
CDynamicClassFactory* g_rgpcf[ARRAYSIZE(c_ClassParams)] = {0};
void ClassFactory_Start()
{
for (int i = 0; i < ARRAYSIZE(c_ClassParams); i++)
{
g_rgpcf[i] = new CDynamicClassFactory(c_ClassParams[i].pclsid, c_ClassParams[i].pfnCreate);
if (g_rgpcf[i])
{
g_rgpcf[i]->Register();
}
}
}
void ClassFactory_Stop()
{
for (int i = 0; i < ARRAYSIZE(c_ClassParams); i++)
{
if (g_rgpcf[i])
{
g_rgpcf[i]->Revoke();
g_rgpcf[i]->Release();
g_rgpcf[i] = NULL;
}
}
}