Author: tfaber Date: Sat Jun 20 12:08:13 2015 New Revision: 68203
URL: http://svn.reactos.org/svn/reactos?rev=68203&view=rev Log: [ATL] - Implement CComClassFactorySingleton
Modified: trunk/reactos/lib/atl/atlcom.h
Modified: trunk/reactos/lib/atl/atlcom.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/atl/atlcom.h?rev=68203&... ============================================================================== --- trunk/reactos/lib/atl/atlcom.h [iso-8859-1] (original) +++ trunk/reactos/lib/atl/atlcom.h [iso-8859-1] Sat Jun 20 12:08:13 2015 @@ -29,6 +29,7 @@
#define DECLARE_CLASSFACTORY_EX(cf) typedef ATL::CComCreator<ATL::CComObjectCached<cf> > _ClassFactoryCreatorClass; #define DECLARE_CLASSFACTORY() DECLARE_CLASSFACTORY_EX(ATL::CComClassFactory) +#define DECLARE_CLASSFACTORY_SINGLETON(obj) DECLARE_CLASSFACTORY_EX(ATL::CComClassFactorySingleton<obj>)
class CComObjectRootBase { @@ -470,6 +471,11 @@ { }
+ virtual ~CComObjectCached() + { + this->FinalRelease(); + } + STDMETHOD_(ULONG, AddRef)() { ULONG newRefCount; @@ -495,6 +501,38 @@ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObject) { return this->_InternalQueryInterface(iid, ppvObject); + } + + static HRESULT WINAPI CreateInstance(CComObjectCached<Base> **pp) + { + CComObjectCached<Base> *newInstance; + HRESULT hResult; + + ATLASSERT(pp != NULL); + if (pp == NULL) + return E_POINTER; + + hResult = E_OUTOFMEMORY; + newInstance = NULL; + ATLTRY(newInstance = new CComObjectCached<Base>()) + if (newInstance != NULL) + { + newInstance->SetVoid(NULL); + newInstance->InternalFinalConstructAddRef(); + hResult = newInstance->_AtlInitialConstruct(); + if (SUCCEEDED(hResult)) + hResult = newInstance->FinalConstruct(); + if (SUCCEEDED(hResult)) + hResult = newInstance->_AtlFinalConstruct(); + newInstance->InternalFinalConstructRelease(); + if (hResult != S_OK) + { + delete newInstance; + newInstance = NULL; + } + } + *pp = newInstance; + return hResult; } };
@@ -670,6 +708,62 @@ END_COM_MAP() };
+template <class T> +class CComClassFactorySingleton : + public CComClassFactory +{ +public: + HRESULT m_hrCreate; + IUnknown *m_spObj; + +public: + CComClassFactorySingleton() : + m_hrCreate(S_OK), + m_spObj(NULL) + { + } + + STDMETHOD(CreateInstance)(LPUNKNOWN pUnkOuter, REFIID riid, void **ppvObj) + { + HRESULT hResult; + + if (ppvObj == NULL) + return E_POINTER; + *ppvObj = NULL; + + if (pUnkOuter != NULL) + hResult = CLASS_E_NOAGGREGATION; + else if (m_hrCreate == S_OK && m_spObj == NULL) + { + _SEH2_TRY + { + Lock(); + if (m_hrCreate == S_OK && m_spObj == NULL) + { + CComObjectCached<T> *pObj; + m_hrCreate = CComObjectCached<T>::CreateInstance(&pObj); + if (SUCCEEDED(m_hrCreate)) + { + m_hrCreate = pObj->QueryInterface(IID_IUnknown, reinterpret_cast<PVOID *>(&m_spObj)); + if (FAILED(m_hrCreate)) + delete pObj; + } + } + } + _SEH2_FINALLY + { + Unlock(); + } + _SEH2_END; + } + if (m_hrCreate == S_OK) + hResult = m_spObj->QueryInterface(riid, ppvObj); + else + hResult = m_hrCreate; + return hResult; + } +}; + template <class T, const CLSID *pclsid = &CLSID_NULL> class CComCoClass {