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&r1=68202&r2=68203&view=diff
==============================================================================
--- 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
 {


Reply via email to