[ATL]
[reactos.git] / reactos / lib / atl / atlcom.h
index b260e20..98d0ca0 100644 (file)
@@ -29,60 +29,61 @@ class CComEnum;
 
 #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
 {
 public:
-       LONG                                                                    m_dwRef;
+    LONG m_dwRef;
 public:
-       CComObjectRootBase()
-       {
-               m_dwRef = 0;
-       }
-
-       ~CComObjectRootBase()
-       {
-       }
-
-       void SetVoid(void *)
-       {
-       }
-
-       HRESULT _AtlFinalConstruct()
-       {
-               return S_OK;
-       }
-
-       HRESULT FinalConstruct()
-       {
-               return S_OK;
-       }
-
-       void InternalFinalConstructAddRef()
-       {
-       }
-
-       void InternalFinalConstructRelease()
-       {
-       }
-
-       void FinalRelease()
-       {
-       }
-
-       static void WINAPI ObjectMain(bool)
-       {
-       }
-
-       static const struct _ATL_CATMAP_ENTRY *GetCategoryMap()
-       {
-               return NULL;
-       }
-
-       static HRESULT WINAPI InternalQueryInterface(void *pThis, const _ATL_INTMAP_ENTRY *pEntries, REFIID iid, void **ppvObject)
-       {
-               return AtlInternalQueryInterface(pThis, pEntries, iid, ppvObject);
-       }
+    CComObjectRootBase()
+    {
+        m_dwRef = 0;
+    }
+
+    ~CComObjectRootBase()
+    {
+    }
+
+    void SetVoid(void *)
+    {
+    }
+
+    HRESULT _AtlFinalConstruct()
+    {
+        return S_OK;
+    }
+
+    HRESULT FinalConstruct()
+    {
+        return S_OK;
+    }
+
+    void InternalFinalConstructAddRef()
+    {
+    }
+
+    void InternalFinalConstructRelease()
+    {
+    }
+
+    void FinalRelease()
+    {
+    }
+
+    static void WINAPI ObjectMain(bool)
+    {
+    }
+
+    static const struct _ATL_CATMAP_ENTRY *GetCategoryMap()
+    {
+        return NULL;
+    }
+
+    static HRESULT WINAPI InternalQueryInterface(void *pThis, const _ATL_INTMAP_ENTRY *pEntries, REFIID iid, void **ppvObject)
+    {
+        return AtlInternalQueryInterface(pThis, pEntries, iid, ppvObject);
+    }
 
 };
 
@@ -90,106 +91,106 @@ template <class ThreadModel>
 class CComObjectRootEx : public CComObjectRootBase
 {
 private:
-       typename ThreadModel::AutoDeleteCriticalSection         m_critsec;
+    typename ThreadModel::AutoDeleteCriticalSection m_critsec;
 public:
-       ~CComObjectRootEx()
-       {
-       }
-
-       ULONG InternalAddRef()
-       {
-               ATLASSERT(m_dwRef >= 0);
-               return ThreadModel::Increment(&m_dwRef);
-       }
-
-       ULONG InternalRelease()
-       {
-               ATLASSERT(m_dwRef > 0);
-               return ThreadModel::Decrement(&m_dwRef);
-       }
-
-       void Lock()
-       {
-               m_critsec.Lock();
-       }
-
-       void Unlock()
-       {
-               m_critsec.Unlock();
-       }
-
-       HRESULT _AtlInitialConstruct()
-       {
-               return m_critsec.Init();
-       }
+    ~CComObjectRootEx()
+    {
+    }
+
+    ULONG InternalAddRef()
+    {
+        ATLASSERT(m_dwRef >= 0);
+        return ThreadModel::Increment(&m_dwRef);
+    }
+
+    ULONG InternalRelease()
+    {
+        ATLASSERT(m_dwRef > 0);
+        return ThreadModel::Decrement(&m_dwRef);
+    }
+
+    void Lock()
+    {
+        m_critsec.Lock();
+    }
+
+    void Unlock()
+    {
+        m_critsec.Unlock();
+    }
+
+    HRESULT _AtlInitialConstruct()
+    {
+        return m_critsec.Init();
+    }
 };
 
 template <class Base>
 class CComObject : public Base
 {
 public:
-       CComObject(void * = NULL)
-       {
-               _pAtlModule->Lock();
-       }
-
-       virtual ~CComObject()
-       {
-               this->FinalRelease();
-               _pAtlModule->Unlock();
-       }
-
-       STDMETHOD_(ULONG, AddRef)()
-       {
-               return this->InternalAddRef();
-       }
-
-       STDMETHOD_(ULONG, Release)()
-       {
-               ULONG                                                           newRefCount;
-
-               newRefCount = this->InternalRelease();
-               if (newRefCount == 0)
-                       delete this;
-               return newRefCount;
-       }
-
-       STDMETHOD(QueryInterface)(REFIID iid, void **ppvObject)
-       {
-               return this->_InternalQueryInterface(iid, ppvObject);
-       }
-
-       static HRESULT WINAPI CreateInstance(CComObject<Base> **pp)
-       {
-               CComObject<Base>                                        *newInstance;
-               HRESULT                                                         hResult;
-
-               ATLASSERT(pp != NULL);
-               if (pp == NULL)
-                       return E_POINTER;
-
-               hResult = E_OUTOFMEMORY;
-               newInstance = NULL;
-               ATLTRY(newInstance = new CComObject<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;
-       }
+    CComObject(void * = NULL)
+    {
+        _pAtlModule->Lock();
+    }
+
+    virtual ~CComObject()
+    {
+        this->FinalRelease();
+        _pAtlModule->Unlock();
+    }
+
+    STDMETHOD_(ULONG, AddRef)()
+    {
+        return this->InternalAddRef();
+    }
+
+    STDMETHOD_(ULONG, Release)()
+    {
+        ULONG newRefCount;
+
+        newRefCount = this->InternalRelease();
+        if (newRefCount == 0)
+            delete this;
+        return newRefCount;
+    }
+
+    STDMETHOD(QueryInterface)(REFIID iid, void **ppvObject)
+    {
+        return this->_InternalQueryInterface(iid, ppvObject);
+    }
+
+    static HRESULT WINAPI CreateInstance(CComObject<Base> **pp)
+    {
+        CComObject<Base> *newInstance;
+        HRESULT hResult;
+
+        ATLASSERT(pp != NULL);
+        if (pp == NULL)
+            return E_POINTER;
+
+        hResult = E_OUTOFMEMORY;
+        newInstance = NULL;
+        ATLTRY(newInstance = new CComObject<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;
+    }
 
 
 };
@@ -198,750 +199,843 @@ template <class Base>
 class CComContainedObject : public Base
 {
 public:
-       IUnknown* m_pUnkOuter;
-       CComContainedObject(void * pv = NULL) : m_pUnkOuter(static_cast<IUnknown*>(pv))
-       {
-       }
-
-       STDMETHOD_(ULONG, AddRef)()
-       {
-               return m_pUnkOuter->AddRef();
-       }
-
-       STDMETHOD_(ULONG, Release)()
-       {
-               return m_pUnkOuter->Release();
-       }
-
-       STDMETHOD(QueryInterface)(REFIID iid, void **ppvObject)
-       {
-               return m_pUnkOuter->QueryInterface(iid, ppvObject);
-       }
-
-       IUnknown* GetControllingUnknown()
-       {
-               return m_pUnkOuter;
-       }
+    IUnknown* m_pUnkOuter;
+    CComContainedObject(void * pv = NULL) : m_pUnkOuter(static_cast<IUnknown*>(pv))
+    {
+    }
+
+    STDMETHOD_(ULONG, AddRef)()
+    {
+        return m_pUnkOuter->AddRef();
+    }
+
+    STDMETHOD_(ULONG, Release)()
+    {
+        return m_pUnkOuter->Release();
+    }
+
+    STDMETHOD(QueryInterface)(REFIID iid, void **ppvObject)
+    {
+        return m_pUnkOuter->QueryInterface(iid, ppvObject);
+    }
+
+    IUnknown* GetControllingUnknown()
+    {
+        return m_pUnkOuter;
+    }
 };
 
 template <class contained>
 class CComAggObject : public contained
 {
 public:
-       CComContainedObject<contained> m_contained;
-
-       CComAggObject(void * pv = NULL) : m_contained(static_cast<contained*>(pv))
-       {
-               _pAtlModule->Lock();
-       }
-
-       virtual ~CComAggObject()
-       {
-               this->FinalRelease();
-               _pAtlModule->Unlock();
-       }
-
-       HRESULT FinalConstruct()
-       {
-               return m_contained.FinalConstruct();
-       }
-       void FinalRelease()
-       {
-               m_contained.FinalRelease();
-       }
-
-       STDMETHOD_(ULONG, AddRef)()
-       {
-               return this->InternalAddRef();
-       }
-
-       STDMETHOD_(ULONG, Release)()
-       {
-               ULONG newRefCount;
-               newRefCount = this->InternalRelease();
-               if (newRefCount == 0)
-                       delete this;
-               return newRefCount;
-       }
-
-       STDMETHOD(QueryInterface)(REFIID iid, void **ppvObject)
-       {
-               if (ppvObject == NULL)
-                       return E_POINTER;
-               if (iid == IID_IUnknown)
-                       *ppvObject = reinterpret_cast<void*>(this);
-               else
-                       return m_contained._InternalQueryInterface(iid, ppvObject);
-               return S_OK;
-       }
-
-       static HRESULT WINAPI CreateInstance(IUnknown * punkOuter, CComAggObject<contained> **pp)
-       {
-               CComAggObject<contained>        *newInstance;
-               HRESULT                                         hResult;
-
-               ATLASSERT(pp != NULL);
-               if (pp == NULL)
-                       return E_POINTER;
-
-               hResult = E_OUTOFMEMORY;
-               newInstance = NULL;
-               ATLTRY(newInstance = new CComAggObject<contained>(punkOuter))
-               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;
-       }
+    CComContainedObject<contained> m_contained;
+
+    CComAggObject(void * pv = NULL) : m_contained(static_cast<contained*>(pv))
+    {
+        _pAtlModule->Lock();
+    }
+
+    virtual ~CComAggObject()
+    {
+        this->FinalRelease();
+        _pAtlModule->Unlock();
+    }
+
+    HRESULT FinalConstruct()
+    {
+        return m_contained.FinalConstruct();
+    }
+    void FinalRelease()
+    {
+        m_contained.FinalRelease();
+    }
+
+    STDMETHOD_(ULONG, AddRef)()
+    {
+        return this->InternalAddRef();
+    }
+
+    STDMETHOD_(ULONG, Release)()
+    {
+        ULONG newRefCount;
+        newRefCount = this->InternalRelease();
+        if (newRefCount == 0)
+            delete this;
+        return newRefCount;
+    }
+
+    STDMETHOD(QueryInterface)(REFIID iid, void **ppvObject)
+    {
+        if (ppvObject == NULL)
+            return E_POINTER;
+        if (iid == IID_IUnknown)
+            *ppvObject = reinterpret_cast<void*>(this);
+        else
+            return m_contained._InternalQueryInterface(iid, ppvObject);
+        return S_OK;
+    }
+
+    static HRESULT WINAPI CreateInstance(IUnknown * punkOuter, CComAggObject<contained> **pp)
+    {
+        CComAggObject<contained> *newInstance;
+        HRESULT hResult;
+
+        ATLASSERT(pp != NULL);
+        if (pp == NULL)
+            return E_POINTER;
+
+        hResult = E_OUTOFMEMORY;
+        newInstance = NULL;
+        ATLTRY(newInstance = new CComAggObject<contained>(punkOuter))
+        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;
+    }
 };
 
 template <class contained>
 class CComPolyObject : public contained
 {
 public:
-       CComContainedObject<contained> m_contained;
-
-       CComPolyObject(void * pv = NULL)
-               : m_contained(pv ? static_cast<contained*>(pv) : this)
-       {
-               _pAtlModule->Lock();
-       }
-
-       virtual ~CComPolyObject()
-       {
-               this->FinalRelease();
-               _pAtlModule->Unlock();
-       }
-
-       HRESULT FinalConstruct()
-       {
-               return m_contained.FinalConstruct();
-       }
-       void FinalRelease()
-       {
-               m_contained.FinalRelease();
-       }
-
-       STDMETHOD_(ULONG, AddRef)()
-       {
-               return this->InternalAddRef();
-       }
-
-       STDMETHOD_(ULONG, Release)()
-       {
-               ULONG newRefCount;
-               newRefCount = this->InternalRelease();
-               if (newRefCount == 0)
-                       delete this;
-               return newRefCount;
-       }
-
-       STDMETHOD(QueryInterface)(REFIID iid, void **ppvObject)
-       {
-               if (ppvObject == NULL)
-                       return E_POINTER;
-               if (iid == IID_IUnknown)
-                       *ppvObject = reinterpret_cast<void*>(this);
-               else
-                       return m_contained._InternalQueryInterface(iid, ppvObject);
-               return S_OK;
-       }
-
-       static HRESULT WINAPI CreateInstance(IUnknown * punkOuter, CComPolyObject<contained> **pp)
-       {
-               CComPolyObject<contained>       *newInstance;
-               HRESULT                                         hResult;
-
-               ATLASSERT(pp != NULL);
-               if (pp == NULL)
-                       return E_POINTER;
-
-               hResult = E_OUTOFMEMORY;
-               newInstance = NULL;
-               ATLTRY(newInstance = new CComPolyObject<contained>(punkOuter))
-               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;
-       }
+    CComContainedObject<contained> m_contained;
+
+    CComPolyObject(void * pv = NULL)
+        : m_contained(pv ? static_cast<contained*>(pv) : this)
+    {
+        _pAtlModule->Lock();
+    }
+
+    virtual ~CComPolyObject()
+    {
+        this->FinalRelease();
+        _pAtlModule->Unlock();
+    }
+
+    HRESULT FinalConstruct()
+    {
+        return m_contained.FinalConstruct();
+    }
+    void FinalRelease()
+    {
+        m_contained.FinalRelease();
+    }
+
+    STDMETHOD_(ULONG, AddRef)()
+    {
+        return this->InternalAddRef();
+    }
+
+    STDMETHOD_(ULONG, Release)()
+    {
+        ULONG newRefCount;
+        newRefCount = this->InternalRelease();
+        if (newRefCount == 0)
+            delete this;
+        return newRefCount;
+    }
+
+    STDMETHOD(QueryInterface)(REFIID iid, void **ppvObject)
+    {
+        if (ppvObject == NULL)
+            return E_POINTER;
+        if (iid == IID_IUnknown)
+            *ppvObject = reinterpret_cast<void*>(this);
+        else
+            return m_contained._InternalQueryInterface(iid, ppvObject);
+        return S_OK;
+    }
+
+    static HRESULT WINAPI CreateInstance(IUnknown * punkOuter, CComPolyObject<contained> **pp)
+    {
+        CComPolyObject<contained> *newInstance;
+        HRESULT hResult;
+
+        ATLASSERT(pp != NULL);
+        if (pp == NULL)
+            return E_POINTER;
+
+        hResult = E_OUTOFMEMORY;
+        newInstance = NULL;
+        ATLTRY(newInstance = new CComPolyObject<contained>(punkOuter))
+        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;
+    }
 };
 
 template <HRESULT hResult>
 class CComFailCreator
 {
 public:
-       static HRESULT WINAPI CreateInstance(void *, REFIID, LPVOID *ppv)
-       {
-               ATLASSERT(ppv != NULL);
-               if (ppv == NULL)
-                       return E_POINTER;
-               *ppv = NULL;
-
-               return hResult;
-       }
+    static HRESULT WINAPI CreateInstance(void *, REFIID, LPVOID *ppv)
+    {
+        ATLASSERT(ppv != NULL);
+        if (ppv == NULL)
+            return E_POINTER;
+        *ppv = NULL;
+
+        return hResult;
+    }
 };
 
 template <class T1>
 class CComCreator
 {
 public:
-       static HRESULT WINAPI CreateInstance(void *pv, REFIID riid, LPVOID *ppv)
-       {
-               T1                                                                      *newInstance;
-               HRESULT                                                         hResult;
-
-               ATLASSERT(ppv != NULL);
-               if (ppv == NULL)
-                       return E_POINTER;
-               *ppv = NULL;
-
-               hResult = E_OUTOFMEMORY;
-               newInstance = NULL;
-               ATLTRY(newInstance = new T1(pv))
-               if (newInstance != NULL)
-               {
-                       newInstance->SetVoid(pv);
-                       newInstance->InternalFinalConstructAddRef();
-                       hResult = newInstance->_AtlInitialConstruct();
-                       if (SUCCEEDED(hResult))
-                               hResult = newInstance->FinalConstruct();
-                       if (SUCCEEDED(hResult))
-                               hResult = newInstance->_AtlFinalConstruct();
-                       newInstance->InternalFinalConstructRelease();
-                       if (SUCCEEDED(hResult))
-                               hResult = newInstance->QueryInterface(riid, ppv);
-                       if (FAILED(hResult))
-                       {
-                               delete newInstance;
-                               newInstance = NULL;
-                       }
-               }
-               return hResult;
-       }
+    static HRESULT WINAPI CreateInstance(void *pv, REFIID riid, LPVOID *ppv)
+    {
+        T1 *newInstance;
+        HRESULT hResult;
+
+        ATLASSERT(ppv != NULL);
+        if (ppv == NULL)
+            return E_POINTER;
+        *ppv = NULL;
+
+        hResult = E_OUTOFMEMORY;
+        newInstance = NULL;
+        ATLTRY(newInstance = new T1(pv))
+        if (newInstance != NULL)
+        {
+            newInstance->SetVoid(pv);
+            newInstance->InternalFinalConstructAddRef();
+            hResult = newInstance->_AtlInitialConstruct();
+            if (SUCCEEDED(hResult))
+                hResult = newInstance->FinalConstruct();
+            if (SUCCEEDED(hResult))
+                hResult = newInstance->_AtlFinalConstruct();
+            newInstance->InternalFinalConstructRelease();
+            if (SUCCEEDED(hResult))
+                hResult = newInstance->QueryInterface(riid, ppv);
+            if (FAILED(hResult))
+            {
+                delete newInstance;
+                newInstance = NULL;
+            }
+        }
+        return hResult;
+    }
 };
 
 template <class T1, class T2>
 class CComCreator2
 {
 public:
-       static HRESULT WINAPI CreateInstance(void *pv, REFIID riid, LPVOID *ppv)
-       {
-               ATLASSERT(ppv != NULL && riid != NULL);
-
-               if (pv == NULL)
-                       return T1::CreateInstance(NULL, riid, ppv);
-               else
-                       return T2::CreateInstance(pv, riid, ppv);
-       }
+    static HRESULT WINAPI CreateInstance(void *pv, REFIID riid, LPVOID *ppv)
+    {
+        ATLASSERT(ppv != NULL && riid != NULL);
+
+        if (pv == NULL)
+            return T1::CreateInstance(NULL, riid, ppv);
+        else
+            return T2::CreateInstance(pv, riid, ppv);
+    }
 };
 
 template <class Base>
 class CComObjectCached : public Base
 {
 public:
-       CComObjectCached(void * = NULL)
-       {
-       }
-
-       STDMETHOD_(ULONG, AddRef)()
-       {
-               ULONG                                                           newRefCount;
-
-               newRefCount = this->InternalAddRef();
-               if (newRefCount == 2)
-                       _pAtlModule->Lock();
-               return newRefCount;
-       }
-
-       STDMETHOD_(ULONG, Release)()
-       {
-               ULONG                                                           newRefCount;
-
-               newRefCount = this->InternalRelease();
-               if (newRefCount == 0)
-                       delete this;
-               else if (newRefCount == 1)
-                       _pAtlModule->Unlock();
-               return newRefCount;
-       }
-
-       STDMETHOD(QueryInterface)(REFIID iid, void **ppvObject)
-       {
-               return this->_InternalQueryInterface(iid, ppvObject);
-       }
+    CComObjectCached(void * = NULL)
+    {
+    }
+
+    virtual ~CComObjectCached()
+    {
+        this->FinalRelease();
+    }
+
+    STDMETHOD_(ULONG, AddRef)()
+    {
+        ULONG newRefCount;
+
+        newRefCount = this->InternalAddRef();
+        if (newRefCount == 2)
+            _pAtlModule->Lock();
+        return newRefCount;
+    }
+
+    STDMETHOD_(ULONG, Release)()
+    {
+        ULONG newRefCount;
+
+        newRefCount = this->InternalRelease();
+        if (newRefCount == 0)
+            delete this;
+        else if (newRefCount == 1)
+            _pAtlModule->Unlock();
+        return newRefCount;
+    }
+
+    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;
+    }
 };
 
-#define BEGIN_COM_MAP(x)                                                                                                               \
-public:                                                                                                                                                        \
-       typedef x _ComMapClass;                                                                                                         \
-       HRESULT _InternalQueryInterface(REFIID iid, void **ppvObject)                           \
-       {                                                                                                                                                       \
-               return this->InternalQueryInterface(this, _GetEntries(), iid, ppvObject);               \
-       }                                                                                                                                                       \
-       const static ATL::_ATL_INTMAP_ENTRY *WINAPI _GetEntries()                                       \
-       {                                                                                                                                                       \
-               static const ATL::_ATL_INTMAP_ENTRY _entries[] = {
-
-#define END_COM_MAP()                                                                                                                  \
-                       {NULL, 0, 0}                                                                                                            \
-               };                                                                                                                                              \
-               return _entries;                                                                                                                \
-       }                                                                                                                                                       \
-       virtual ULONG STDMETHODCALLTYPE AddRef() = 0;                                                           \
-       virtual ULONG STDMETHODCALLTYPE Release() = 0;                                                          \
-       STDMETHOD(QueryInterface)(REFIID, void **) = 0;
-
-#define COM_INTERFACE_ENTRY_IID(iid, x)                                                                                        \
-       {&iid, offsetofclass(x, _ComMapClass), _ATL_SIMPLEMAPENTRY},
+#define BEGIN_COM_MAP(x)                                                        \
+public:                                                                            \
+    typedef x _ComMapClass;                                                        \
+    HRESULT _InternalQueryInterface(REFIID iid, void **ppvObject)                \
+    {                                                                            \
+        return this->InternalQueryInterface(this, _GetEntries(), iid, ppvObject);        \
+    }                                                                            \
+    const static ATL::_ATL_INTMAP_ENTRY *WINAPI _GetEntries()                    \
+    {                                                                            \
+        static const ATL::_ATL_INTMAP_ENTRY _entries[] = {
+
+#define END_COM_MAP()                                                            \
+            {NULL, 0, 0}                                                        \
+        };                                                                        \
+        return _entries;                                                        \
+    }                                                                            \
+    virtual ULONG STDMETHODCALLTYPE AddRef() = 0;                                \
+    virtual ULONG STDMETHODCALLTYPE Release() = 0;                                \
+    STDMETHOD(QueryInterface)(REFIID, void **) = 0;
+
+#define COM_INTERFACE_ENTRY_IID(iid, x)                                            \
+    {&iid, offsetofclass(x, _ComMapClass), _ATL_SIMPLEMAPENTRY},
 
 #define COM_INTERFACE_ENTRY(x)                                                  \
-       {&_ATL_IIDOF(x),                                                            \
-       offsetofclass(x, _ComMapClass),                                             \
-       _ATL_SIMPLEMAPENTRY},
-
-#define COM_INTERFACE_ENTRY2_IID(iid, x, x2)                                                                   \
-       {&iid,                                                                                                                                          \
-                       reinterpret_cast<DWORD_PTR>(static_cast<x *>(static_cast<x2 *>(reinterpret_cast<_ComMapClass *>(_ATL_PACKING)))) - _ATL_PACKING,        \
-                       _ATL_SIMPLEMAPENTRY},
-
-#define COM_INTERFACE_ENTRY_BREAK(x)                                                                                   \
-    {&_ATL_IIDOF(x),                                                                                                                   \
-    NULL,                                                                                                                                              \
+    {&_ATL_IIDOF(x),                                                            \
+    offsetofclass(x, _ComMapClass),                                             \
+    _ATL_SIMPLEMAPENTRY},
+
+#define COM_INTERFACE_ENTRY2_IID(iid, x, x2)                                    \
+    {&iid,                                                                        \
+            reinterpret_cast<DWORD_PTR>(static_cast<x *>(static_cast<x2 *>(reinterpret_cast<_ComMapClass *>(_ATL_PACKING)))) - _ATL_PACKING,    \
+            _ATL_SIMPLEMAPENTRY},
+
+#define COM_INTERFACE_ENTRY_BREAK(x)                                            \
+    {&_ATL_IIDOF(x),                                                            \
+    NULL,                                                                        \
     _Break},    // Break is a function that issues int 3.
 
-#define COM_INTERFACE_ENTRY_NOINTERFACE(x)                                                                             \
-    {&_ATL_IIDOF(x),                                                                                                                   \
-    NULL,                                                                                                                                              \
+#define COM_INTERFACE_ENTRY_NOINTERFACE(x)                                        \
+    {&_ATL_IIDOF(x),                                                            \
+    NULL,                                                                        \
     _NoInterface}, // NoInterface returns E_NOINTERFACE.
 
-#define COM_INTERFACE_ENTRY_FUNC(iid, dw, func)                                                                        \
-    {&iid,                                                                                                                                             \
-    dw,                                                                                                                                                        \
+#define COM_INTERFACE_ENTRY_FUNC(iid, dw, func)                                    \
+    {&iid,                                                                        \
+    dw,                                                                            \
     func},
 
-#define COM_INTERFACE_ENTRY_FUNC_BLIND(dw, func)                                                               \
-    {NULL,                                                                                                                                             \
-    dw,                                                                                                                                                        \
+#define COM_INTERFACE_ENTRY_FUNC_BLIND(dw, func)                                \
+    {NULL,                                                                        \
+    dw,                                                                            \
     func},
 
-#define COM_INTERFACE_ENTRY_CHAIN(classname)                                                                   \
-    {NULL,                                                                                                                                             \
-    reinterpret_cast<DWORD>(&_CComChainData<classname, _ComMapClass>::data),   \
+#define COM_INTERFACE_ENTRY_CHAIN(classname)                                    \
+    {NULL,                                                                        \
+    reinterpret_cast<DWORD>(&_CComChainData<classname, _ComMapClass>::data),    \
     _Chain},
 
 #define DECLARE_NO_REGISTRY()\
-       static HRESULT WINAPI UpdateRegistry(BOOL /*bRegister*/)                                        \
-       {                                                                                                                                                       \
-               return S_OK;                                                                                                                    \
-       }
+    static HRESULT WINAPI UpdateRegistry(BOOL /*bRegister*/)                    \
+    {                                                                            \
+        return S_OK;                                                            \
+    }
 
-#define DECLARE_REGISTRY_RESOURCEID(x)                                                                                 \
-       static HRESULT WINAPI UpdateRegistry(BOOL bRegister)                                            \
-       {                                                                                                                                                       \
-               return ATL::_pAtlModule->UpdateRegistryFromResource(x, bRegister);              \
-       }
+#define DECLARE_REGISTRY_RESOURCEID(x)                                            \
+    static HRESULT WINAPI UpdateRegistry(BOOL bRegister)                        \
+    {                                                                            \
+        return ATL::_pAtlModule->UpdateRegistryFromResource(x, bRegister);        \
+    }
 
-#define DECLARE_NOT_AGGREGATABLE(x)                                                                                            \
-public:                                                                                                                                                        \
-       typedef ATL::CComCreator2<ATL::CComCreator<ATL::CComObject<x> >, ATL::CComFailCreator<CLASS_E_NOAGGREGATION> > _CreatorClass;
+#define DECLARE_NOT_AGGREGATABLE(x)                                                \
+public:                                                                            \
+    typedef ATL::CComCreator2<ATL::CComCreator<ATL::CComObject<x> >, ATL::CComFailCreator<CLASS_E_NOAGGREGATION> > _CreatorClass;
 
-#define DECLARE_AGGREGATABLE(x)                                                                                                        \
-public:                                                                                                                                                        \
-       typedef ATL::CComCreator2<ATL::CComCreator<ATL::CComObject<x> >, ATL::CComCreator<ATL::CComAggObject<x> > > _CreatorClass;
+#define DECLARE_AGGREGATABLE(x)                                                    \
+public:                                                                            \
+    typedef ATL::CComCreator2<ATL::CComCreator<ATL::CComObject<x> >, ATL::CComCreator<ATL::CComAggObject<x> > > _CreatorClass;
 
-#define DECLARE_ONLY_AGGREGATABLE(x)                                                                                   \
-public:                                                                                                                                                        \
-       typedef ATL::CComCreator2<ATL::CComFailCreator<E_FAIL>, ATL::CComCreator<ATL::CComAggObject<x> > > _CreatorClass;
+#define DECLARE_ONLY_AGGREGATABLE(x)                                            \
+public:                                                                            \
+    typedef ATL::CComCreator2<ATL::CComFailCreator<E_FAIL>, ATL::CComCreator<ATL::CComAggObject<x> > > _CreatorClass;
 
-#define DECLARE_POLY_AGGREGATABLE(x)                                                                                   \
-public:                                                                                                                                                        \
-       typedef ATL::CComCreator<ATL::CComPolyObject<x> > _CreatorClass;
+#define DECLARE_POLY_AGGREGATABLE(x)                                            \
+public:                                                                            \
+    typedef ATL::CComCreator<ATL::CComPolyObject<x> > _CreatorClass;
 
 #define COM_INTERFACE_ENTRY_AGGREGATE(iid, punk)                                \
-       {&iid,                                                                      \
-       (DWORD_PTR)offsetof(_ComMapClass, punk),                                    \
-       _Delegate},
-
-#define DECLARE_GET_CONTROLLING_UNKNOWN()                                                                              \
-public:                                                                                                                                                        \
-       virtual IUnknown *GetControllingUnknown()                                                                       \
-       {                                                                                                                                                       \
-               return GetUnknown();                                                                                                    \
-       }
-
-#define DECLARE_PROTECT_FINAL_CONSTRUCT()                                                                              \
-       void InternalFinalConstructAddRef()                                                                                     \
-       {                                                                                                                                                       \
-               InternalAddRef();                                                                                                               \
-       }                                                                                                                                                       \
-       void InternalFinalConstructRelease()                                                                            \
-       {                                                                                                                                                       \
-               InternalRelease();                                                                                                              \
-       }
+    {&iid,                                                                      \
+    (DWORD_PTR)offsetof(_ComMapClass, punk),                                    \
+    _Delegate},
+
+#define DECLARE_GET_CONTROLLING_UNKNOWN()                                        \
+public:                                                                            \
+    virtual IUnknown *GetControllingUnknown()                                    \
+    {                                                                            \
+        return GetUnknown();                                                    \
+    }
+
+#define DECLARE_PROTECT_FINAL_CONSTRUCT()                                        \
+    void InternalFinalConstructAddRef()                                            \
+    {                                                                            \
+        InternalAddRef();                                                        \
+    }                                                                            \
+    void InternalFinalConstructRelease()                                        \
+    {                                                                            \
+        InternalRelease();                                                        \
+    }
 
 #define BEGIN_OBJECT_MAP(x) static ATL::_ATL_OBJMAP_ENTRY x[] = {
 
 #define END_OBJECT_MAP()   {NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL}};
 
-#define OBJECT_ENTRY(clsid, class)                                                                                             \
-{                                                                                                                                                              \
-       &clsid,                                                                                                                                         \
-       class::UpdateRegistry,                                                                                                          \
-       class::_ClassFactoryCreatorClass::CreateInstance,                                                       \
-       class::_CreatorClass::CreateInstance,                                                                           \
-       NULL,                                                                                                                                           \
-       0,                                                                                                                                                      \
-       class::GetObjectDescription,                                                                                            \
-       class::GetCategoryMap,                                                                                                          \
-       class::ObjectMain },
+#define OBJECT_ENTRY(clsid, class)                                                \
+{                                                                                \
+    &clsid,                                                                        \
+    class::UpdateRegistry,                                                        \
+    class::_ClassFactoryCreatorClass::CreateInstance,                            \
+    class::_CreatorClass::CreateInstance,                                        \
+    NULL,                                                                        \
+    0,                                                                            \
+    class::GetObjectDescription,                                                \
+    class::GetCategoryMap,                                                        \
+    class::ObjectMain },
 
 class CComClassFactory :
-       public IClassFactory,
-       public CComObjectRootEx<CComGlobalsThreadModel>
+    public IClassFactory,
+    public CComObjectRootEx<CComGlobalsThreadModel>
 {
 public:
-       _ATL_CREATORFUNC                                                *m_pfnCreateInstance;
+    _ATL_CREATORFUNC *m_pfnCreateInstance;
 
-       virtual ~CComClassFactory()
-       {
-       }
+    virtual ~CComClassFactory()
+    {
+    }
 
 public:
-       STDMETHOD(CreateInstance)(LPUNKNOWN pUnkOuter, REFIID riid, void **ppvObj)
-       {
-               HRESULT                                                         hResult;
-
-               ATLASSERT(m_pfnCreateInstance != NULL);
-
-               if (ppvObj == NULL)
-                       return E_POINTER;
-               *ppvObj = NULL;
-
-               if (pUnkOuter != NULL && InlineIsEqualUnknown(riid) == FALSE)
-                       hResult = CLASS_E_NOAGGREGATION;
-               else
-                       hResult = m_pfnCreateInstance(pUnkOuter, riid, ppvObj);
-               return hResult;
-       }
-
-       STDMETHOD(LockServer)(BOOL fLock)
-       {
-               if (fLock)
-                       _pAtlModule->Lock();
-               else
-                       _pAtlModule->Unlock();
-               return S_OK;
-       }
-
-       void SetVoid(void *pv)
-       {
-               m_pfnCreateInstance = (_ATL_CREATORFUNC *)pv;
-       }
-
-       BEGIN_COM_MAP(CComClassFactory)
-               COM_INTERFACE_ENTRY_IID(IID_IClassFactory, IClassFactory)
-       END_COM_MAP()
+    STDMETHOD(CreateInstance)(LPUNKNOWN pUnkOuter, REFIID riid, void **ppvObj)
+    {
+        HRESULT hResult;
+
+        ATLASSERT(m_pfnCreateInstance != NULL);
+
+        if (ppvObj == NULL)
+            return E_POINTER;
+        *ppvObj = NULL;
+
+        if (pUnkOuter != NULL && InlineIsEqualUnknown(riid) == FALSE)
+            hResult = CLASS_E_NOAGGREGATION;
+        else
+            hResult = m_pfnCreateInstance(pUnkOuter, riid, ppvObj);
+        return hResult;
+    }
+
+    STDMETHOD(LockServer)(BOOL fLock)
+    {
+        if (fLock)
+            _pAtlModule->Lock();
+        else
+            _pAtlModule->Unlock();
+        return S_OK;
+    }
+
+    void SetVoid(void *pv)
+    {
+        m_pfnCreateInstance = (_ATL_CREATORFUNC *)pv;
+    }
+
+    BEGIN_COM_MAP(CComClassFactory)
+        COM_INTERFACE_ENTRY_IID(IID_IClassFactory, IClassFactory)
+    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
 {
 public:
-       DECLARE_CLASSFACTORY()
+    DECLARE_CLASSFACTORY()
 
-       static LPCTSTR WINAPI GetObjectDescription()
-       {
-               return NULL;
-       }
+    static LPCTSTR WINAPI GetObjectDescription()
+    {
+        return NULL;
+    }
 };
 
 template <class T>
 class _Copy
 {
 public:
-       static HRESULT copy(T *pTo, const T *pFrom)
-       {
-               memcpy(pTo, pFrom, sizeof(T));
-               return S_OK;
-       }
-
-       static void init(T *)
-       {
-       }
-
-       static void destroy(T *)
-       {
-       }
+    static HRESULT copy(T *pTo, const T *pFrom)
+    {
+        memcpy(pTo, pFrom, sizeof(T));
+        return S_OK;
+    }
+
+    static void init(T *)
+    {
+    }
+
+    static void destroy(T *)
+    {
+    }
 };
 
 template<>
 class _Copy<CONNECTDATA>
 {
 public:
-       static HRESULT copy(CONNECTDATA *pTo, const CONNECTDATA *pFrom)
-       {
-               *pTo = *pFrom;
-               if (pTo->pUnk)
-                       pTo->pUnk->AddRef();
-               return S_OK;
-       }
-
-       static void init(CONNECTDATA *)
-       {
-       }
-
-       static void destroy(CONNECTDATA *p)
-       {
-               if (p->pUnk)
-                       p->pUnk->Release();
-       }
+    static HRESULT copy(CONNECTDATA *pTo, const CONNECTDATA *pFrom)
+    {
+        *pTo = *pFrom;
+        if (pTo->pUnk)
+            pTo->pUnk->AddRef();
+        return S_OK;
+    }
+
+    static void init(CONNECTDATA *)
+    {
+    }
+
+    static void destroy(CONNECTDATA *p)
+    {
+        if (p->pUnk)
+            p->pUnk->Release();
+    }
 };
 
 template <class T>
 class _CopyInterface
 {
 public:
-       static HRESULT copy(T **pTo, T **pFrom)
-       {
-               *pTo = *pFrom;
-               if (*pTo)
-                       (*pTo)->AddRef();
-               return S_OK;
-       }
-
-       static void init(T **)
-       {
-       }
-
-       static void destroy(T **p)
-       {
-               if (*p)
-                       (*p)->Release();
-       }
+    static HRESULT copy(T **pTo, T **pFrom)
+    {
+        *pTo = *pFrom;
+        if (*pTo)
+            (*pTo)->AddRef();
+        return S_OK;
+    }
+
+    static void init(T **)
+    {
+    }
+
+    static void destroy(T **p)
+    {
+        if (*p)
+            (*p)->Release();
+    }
 };
 
 enum CComEnumFlags
 {
-       AtlFlagNoCopy = 0,
-       AtlFlagTakeOwnership = 2,               // BitOwn
-       AtlFlagCopy = 3                                 // BitOwn | BitCopy
+    AtlFlagNoCopy = 0,
+    AtlFlagTakeOwnership = 2,        // BitOwn
+    AtlFlagCopy = 3                    // BitOwn | BitCopy
 };
 
 template <class Base, const IID *piid, class T, class Copy>
 class CComEnumImpl : public Base
 {
 private:
-       typedef CComObject<CComEnum<Base, piid, T, Copy> > enumeratorClass;
+    typedef CComObject<CComEnum<Base, piid, T, Copy> > enumeratorClass;
 public:
-       CComPtr<IUnknown>                                               m_spUnk;
-       DWORD                                                                   m_dwFlags;
-       T                                                                               *m_begin;
-       T                                                                               *m_end;
-       T                                                                               *m_iter;
+    CComPtr<IUnknown> m_spUnk;
+    DWORD m_dwFlags;
+    T *m_begin;
+    T *m_end;
+    T *m_iter;
 public:
-       CComEnumImpl()
-       {
-               m_dwFlags = 0;
-               m_begin = NULL;
-               m_end = NULL;
-               m_iter = NULL;
-       }
-
-       virtual ~CComEnumImpl()
-       {
-               T                                                                       *x;
-
-               if ((m_dwFlags & BitOwn) != 0)
-               {
-                       for (x = m_begin; x != m_end; x++)
-                               Copy::destroy(x);
-                       delete [] m_begin;
-               }
-       }
-
-       HRESULT Init(T *begin, T *end, IUnknown *pUnk, CComEnumFlags flags = AtlFlagNoCopy)
-       {
-               T                                                                       *newBuffer;
-               T                                                                       *sourcePtr;
-               T                                                                       *destPtr;
-               T                                                                       *cleanupPtr;
-               HRESULT                                                         hResult;
-
-               if (flags == AtlFlagCopy)
-               {
-                       ATLTRY(newBuffer = new T[end - begin])
-                       if (newBuffer == NULL)
-                               return E_OUTOFMEMORY;
-                       destPtr = newBuffer;
-                       for (sourcePtr = begin; sourcePtr != end; sourcePtr++)
-                       {
-                               Copy::init(destPtr);
-                               hResult = Copy::copy(destPtr, sourcePtr);
-                               if (FAILED(hResult))
-                               {
-                                       cleanupPtr = m_begin;
-                                       while (cleanupPtr < destPtr)
-                                               Copy::destroy(cleanupPtr++);
-                                       delete [] newBuffer;
-                                       return hResult;
-                               }
-                               destPtr++;
-                       }
-                       m_begin = newBuffer;
-                       m_end = m_begin + (end - begin);
-               }
-               else
-               {
-                       m_begin = begin;
-                       m_end = end;
-               }
-               m_spUnk = pUnk;
-               m_dwFlags = flags;
-               m_iter = m_begin;
-               return S_OK;
-       }
-
-       STDMETHOD(Next)(ULONG celt, T *rgelt, ULONG *pceltFetched)
-       {
-               ULONG                                                           numAvailable;
-               ULONG                                                           numToFetch;
-               T                                                                       *rgeltTemp;
-               HRESULT                                                         hResult;
-
-               if (pceltFetched != NULL)
-                       *pceltFetched = 0;
-               if (celt == 0)
-                       return E_INVALIDARG;
-               if (rgelt == NULL || (celt != 1 && pceltFetched == NULL))
-                       return E_POINTER;
-               if (m_begin == NULL || m_end == NULL || m_iter == NULL)
-                       return E_FAIL;
-
-               numAvailable = static_cast<ULONG>(m_end - m_iter);
-               if (celt < numAvailable)
-                       numToFetch = celt;
-               else
-                       numToFetch = numAvailable;
-               if (pceltFetched != NULL)
-                       *pceltFetched = numToFetch;
-               rgeltTemp = rgelt;
-               while (numToFetch != 0)
-               {
-                       hResult = Copy::copy(rgeltTemp, m_iter);
-                       if (FAILED(hResult))
-                       {
-                               while (rgelt < rgeltTemp)
-                                       Copy::destroy(rgelt++);
-                               if (pceltFetched != NULL)
-                                       *pceltFetched = 0;
-                               return hResult;
-                       }
-                       rgeltTemp++;
-                       m_iter++;
-                       numToFetch--;
-               }
-               if (numAvailable < celt)
-                       return S_FALSE;
-               return S_OK;
-       }
-
-       STDMETHOD(Skip)(ULONG celt)
-       {
-               ULONG                                                           numAvailable;
-               ULONG                                                           numToSkip;
-
-               if (celt == 0)
-                       return E_INVALIDARG;
-
-               numAvailable = static_cast<ULONG>(m_end - m_iter);
-               if (celt < numAvailable)
-                       numToSkip = celt;
-               else
-                       numToSkip = numAvailable;
-               m_iter += numToSkip;
-               if (numAvailable < celt)
-                       return S_FALSE;
-               return S_OK;
-       }
-
-       STDMETHOD(Reset)()
-       {
-               m_iter = m_begin;
-               return S_OK;
-       }
-
-       STDMETHOD(Clone)(Base **ppEnum)
-       {
-               enumeratorClass                                         *newInstance;
-               HRESULT                                                         hResult;
-
-               hResult = E_POINTER;
-               if (ppEnum != NULL)
-               {
-                       *ppEnum = NULL;
-                       hResult = enumeratorClass::CreateInstance(&newInstance);
-                       if (SUCCEEDED(hResult))
-                       {
-                               hResult = newInstance->Init(m_begin, m_end, (m_dwFlags & BitOwn) ? this : m_spUnk);
-                               if (SUCCEEDED(hResult))
-                               {
-                                       newInstance->m_iter = m_iter;
-                                       hResult = newInstance->_InternalQueryInterface(*piid, (void **)ppEnum);
-                               }
-                               if (FAILED(hResult))
-                                       delete newInstance;
-                       }
-               }
-               return hResult;
-       }
+    CComEnumImpl()
+    {
+        m_dwFlags = 0;
+        m_begin = NULL;
+        m_end = NULL;
+        m_iter = NULL;
+    }
+
+    virtual ~CComEnumImpl()
+    {
+        T *x;
+
+        if ((m_dwFlags & BitOwn) != 0)
+        {
+            for (x = m_begin; x != m_end; x++)
+                Copy::destroy(x);
+            delete [] m_begin;
+        }
+    }
+
+    HRESULT Init(T *begin, T *end, IUnknown *pUnk, CComEnumFlags flags = AtlFlagNoCopy)
+    {
+        T *newBuffer;
+        T *sourcePtr;
+        T *destPtr;
+        T *cleanupPtr;
+        HRESULT hResult;
+
+        if (flags == AtlFlagCopy)
+        {
+            ATLTRY(newBuffer = new T[end - begin])
+            if (newBuffer == NULL)
+                return E_OUTOFMEMORY;
+            destPtr = newBuffer;
+            for (sourcePtr = begin; sourcePtr != end; sourcePtr++)
+            {
+                Copy::init(destPtr);
+                hResult = Copy::copy(destPtr, sourcePtr);
+                if (FAILED(hResult))
+                {
+                    cleanupPtr = m_begin;
+                    while (cleanupPtr < destPtr)
+                        Copy::destroy(cleanupPtr++);
+                    delete [] newBuffer;
+                    return hResult;
+                }
+                destPtr++;
+            }
+            m_begin = newBuffer;
+            m_end = m_begin + (end - begin);
+        }
+        else
+        {
+            m_begin = begin;
+            m_end = end;
+        }
+        m_spUnk = pUnk;
+        m_dwFlags = flags;
+        m_iter = m_begin;
+        return S_OK;
+    }
+
+    STDMETHOD(Next)(ULONG celt, T *rgelt, ULONG *pceltFetched)
+    {
+        ULONG numAvailable;
+        ULONG numToFetch;
+        T *rgeltTemp;
+        HRESULT hResult;
+
+        if (pceltFetched != NULL)
+            *pceltFetched = 0;
+        if (celt == 0)
+            return E_INVALIDARG;
+        if (rgelt == NULL || (celt != 1 && pceltFetched == NULL))
+            return E_POINTER;
+        if (m_begin == NULL || m_end == NULL || m_iter == NULL)
+            return E_FAIL;
+
+        numAvailable = static_cast<ULONG>(m_end - m_iter);
+        if (celt < numAvailable)
+            numToFetch = celt;
+        else
+            numToFetch = numAvailable;
+        if (pceltFetched != NULL)
+            *pceltFetched = numToFetch;
+        rgeltTemp = rgelt;
+        while (numToFetch != 0)
+        {
+            hResult = Copy::copy(rgeltTemp, m_iter);
+            if (FAILED(hResult))
+            {
+                while (rgelt < rgeltTemp)
+                    Copy::destroy(rgelt++);
+                if (pceltFetched != NULL)
+                    *pceltFetched = 0;
+                return hResult;
+            }
+            rgeltTemp++;
+            m_iter++;
+            numToFetch--;
+        }
+        if (numAvailable < celt)
+            return S_FALSE;
+        return S_OK;
+    }
+
+    STDMETHOD(Skip)(ULONG celt)
+    {
+        ULONG numAvailable;
+        ULONG numToSkip;
+
+        if (celt == 0)
+            return E_INVALIDARG;
+
+        numAvailable = static_cast<ULONG>(m_end - m_iter);
+        if (celt < numAvailable)
+            numToSkip = celt;
+        else
+            numToSkip = numAvailable;
+        m_iter += numToSkip;
+        if (numAvailable < celt)
+            return S_FALSE;
+        return S_OK;
+    }
+
+    STDMETHOD(Reset)()
+    {
+        m_iter = m_begin;
+        return S_OK;
+    }
+
+    STDMETHOD(Clone)(Base **ppEnum)
+    {
+        enumeratorClass *newInstance;
+        HRESULT hResult;
+
+        hResult = E_POINTER;
+        if (ppEnum != NULL)
+        {
+            *ppEnum = NULL;
+            hResult = enumeratorClass::CreateInstance(&newInstance);
+            if (SUCCEEDED(hResult))
+            {
+                hResult = newInstance->Init(m_begin, m_end, (m_dwFlags & BitOwn) ? this : m_spUnk);
+                if (SUCCEEDED(hResult))
+                {
+                    newInstance->m_iter = m_iter;
+                    hResult = newInstance->_InternalQueryInterface(*piid, (void **)ppEnum);
+                }
+                if (FAILED(hResult))
+                    delete newInstance;
+            }
+        }
+        return hResult;
+    }
 
 protected:
-       enum FlagBits
-       {
-               BitCopy = 1,
-               BitOwn = 2
-       };
+    enum FlagBits
+    {
+        BitCopy = 1,
+        BitOwn = 2
+    };
 };
 
 template <class Base, const IID *piid, class T, class Copy, class ThreadModel>
 class CComEnum :
-       public CComEnumImpl<Base, piid, T, Copy>,
-       public CComObjectRootEx<ThreadModel>
+    public CComEnumImpl<Base, piid, T, Copy>,
+    public CComObjectRootEx<ThreadModel>
 {
 public:
-       typedef CComEnum<Base, piid, T, Copy > _CComEnum;
-       typedef CComEnumImpl<Base, piid, T, Copy > _CComEnumBase;
+    typedef CComEnum<Base, piid, T, Copy > _CComEnum;
+    typedef CComEnumImpl<Base, piid, T, Copy > _CComEnumBase;
 
-       BEGIN_COM_MAP(_CComEnum)
-               COM_INTERFACE_ENTRY_IID(*piid, _CComEnumBase)
-       END_COM_MAP()
+    BEGIN_COM_MAP(_CComEnum)
+        COM_INTERFACE_ENTRY_IID(*piid, _CComEnumBase)
+    END_COM_MAP()
 };
 
 #ifndef _DEFAULT_VECTORLENGTH
@@ -951,393 +1045,480 @@ public:
 class CComDynamicUnkArray
 {
 public:
-       int                                                                             m_nSize;
-       IUnknown                                                                **m_ppUnk;
+    int m_nSize;
+    IUnknown **m_ppUnk;
 public:
-       CComDynamicUnkArray()
-       {
-               m_nSize = 0;
-               m_ppUnk = NULL;
-       }
-
-       ~CComDynamicUnkArray()
-       {
-               free(m_ppUnk);
-       }
-
-       IUnknown **begin()
-       {
-               return m_ppUnk;
-       }
-
-       IUnknown **end()
-       {
-               return &m_ppUnk[m_nSize];
-       }
-
-       IUnknown *GetAt(int nIndex)
-       {
-               ATLASSERT(nIndex >= 0 && nIndex < m_nSize);
-               if (nIndex >= 0 && nIndex < m_nSize)
-                       return m_ppUnk[nIndex];
-               else
-                       return NULL;
-       }
-
-       IUnknown *WINAPI GetUnknown(DWORD dwCookie)
-       {
-               ATLASSERT(dwCookie != 0 && dwCookie <= static_cast<DWORD>(m_nSize));
-               if (dwCookie != 0 && dwCookie <= static_cast<DWORD>(m_nSize))
-                       return GetAt(dwCookie - 1);
-               else
-                       return NULL;
-       }
-
-       DWORD WINAPI GetCookie(IUnknown **ppFind)
-       {
-               IUnknown                                                        **x;
-               DWORD                                                           curCookie;
-
-               ATLASSERT(ppFind != NULL && *ppFind != NULL);
-               if (ppFind != NULL && *ppFind != NULL)
-               {
-                       curCookie = 1;
-                       for (x = begin(); x < end(); x++)
-                       {
-                               if (*x == *ppFind)
-                                       return curCookie;
-                               curCookie++;
-                       }
-               }
-               return 0;
-       }
-
-       DWORD Add(IUnknown *pUnk)
-       {
-               IUnknown                                                        **x;
-               IUnknown                                                        **newArray;
-               int                                                                     newSize;
-               DWORD                                                           curCookie;
-
-               ATLASSERT(pUnk != NULL);
-               if (m_nSize == 0)
-               {
-                       newSize = _DEFAULT_VECTORLENGTH * sizeof(IUnknown *);
-                       ATLTRY(newArray = reinterpret_cast<IUnknown **>(malloc(newSize)));
-                       if (newArray == NULL)
-                               return 0;
-                       memset(newArray, 0, newSize);
-                       m_ppUnk = newArray;
-                       m_nSize = _DEFAULT_VECTORLENGTH;
-               }
-               curCookie = 1;
-               for (x = begin(); x < end(); x++)
-               {
-                       if (*x == NULL)
-                       {
-                               *x = pUnk;
-                               return curCookie;
-                       }
-                       curCookie++;
-               }
-               newSize = m_nSize * 2;
-               newArray = reinterpret_cast<IUnknown **>(realloc(m_ppUnk, newSize * sizeof(IUnknown *)));
-               if (newArray == NULL)
-                       return 0;
-               m_ppUnk = newArray;
-               memset(&m_ppUnk[m_nSize], 0, (newSize - m_nSize) * sizeof(IUnknown *));
-               curCookie = m_nSize + 1;
-               m_nSize = newSize;
-               m_ppUnk[curCookie - 1] = pUnk;
-               return curCookie;
-       }
-
-       BOOL Remove(DWORD dwCookie)
-       {
-               DWORD                                                           index;
-
-               index = dwCookie - 1;
-               ATLASSERT(index < dwCookie && index < static_cast<DWORD>(m_nSize));
-               if (index < dwCookie && index < static_cast<DWORD>(m_nSize) && m_ppUnk[index] != NULL)
-               {
-                       m_ppUnk[index] = NULL;
-                       return TRUE;
-               }
-               return FALSE;
-       }
+    CComDynamicUnkArray()
+    {
+        m_nSize = 0;
+        m_ppUnk = NULL;
+    }
+
+    ~CComDynamicUnkArray()
+    {
+        free(m_ppUnk);
+    }
+
+    IUnknown **begin()
+    {
+        return m_ppUnk;
+    }
+
+    IUnknown **end()
+    {
+        return &m_ppUnk[m_nSize];
+    }
+
+    IUnknown *GetAt(int nIndex)
+    {
+        ATLASSERT(nIndex >= 0 && nIndex < m_nSize);
+        if (nIndex >= 0 && nIndex < m_nSize)
+            return m_ppUnk[nIndex];
+        else
+            return NULL;
+    }
+
+    IUnknown *WINAPI GetUnknown(DWORD dwCookie)
+    {
+        ATLASSERT(dwCookie != 0 && dwCookie <= static_cast<DWORD>(m_nSize));
+        if (dwCookie != 0 && dwCookie <= static_cast<DWORD>(m_nSize))
+            return GetAt(dwCookie - 1);
+        else
+            return NULL;
+    }
+
+    DWORD WINAPI GetCookie(IUnknown **ppFind)
+    {
+        IUnknown **x;
+        DWORD curCookie;
+
+        ATLASSERT(ppFind != NULL && *ppFind != NULL);
+        if (ppFind != NULL && *ppFind != NULL)
+        {
+            curCookie = 1;
+            for (x = begin(); x < end(); x++)
+            {
+                if (*x == *ppFind)
+                    return curCookie;
+                curCookie++;
+            }
+        }
+        return 0;
+    }
+
+    DWORD Add(IUnknown *pUnk)
+    {
+        IUnknown **x;
+        IUnknown **newArray;
+        int newSize;
+        DWORD curCookie;
+
+        ATLASSERT(pUnk != NULL);
+        if (m_nSize == 0)
+        {
+            newSize = _DEFAULT_VECTORLENGTH * sizeof(IUnknown *);
+            ATLTRY(newArray = reinterpret_cast<IUnknown **>(malloc(newSize)));
+            if (newArray == NULL)
+                return 0;
+            memset(newArray, 0, newSize);
+            m_ppUnk = newArray;
+            m_nSize = _DEFAULT_VECTORLENGTH;
+        }
+        curCookie = 1;
+        for (x = begin(); x < end(); x++)
+        {
+            if (*x == NULL)
+            {
+                *x = pUnk;
+                return curCookie;
+            }
+            curCookie++;
+        }
+        newSize = m_nSize * 2;
+        newArray = reinterpret_cast<IUnknown **>(realloc(m_ppUnk, newSize * sizeof(IUnknown *)));
+        if (newArray == NULL)
+            return 0;
+        m_ppUnk = newArray;
+        memset(&m_ppUnk[m_nSize], 0, (newSize - m_nSize) * sizeof(IUnknown *));
+        curCookie = m_nSize + 1;
+        m_nSize = newSize;
+        m_ppUnk[curCookie - 1] = pUnk;
+        return curCookie;
+    }
+
+    BOOL Remove(DWORD dwCookie)
+    {
+        DWORD index;
+
+        index = dwCookie - 1;
+        ATLASSERT(index < dwCookie && index < static_cast<DWORD>(m_nSize));
+        if (index < dwCookie && index < static_cast<DWORD>(m_nSize) && m_ppUnk[index] != NULL)
+        {
+            m_ppUnk[index] = NULL;
+            return TRUE;
+        }
+        return FALSE;
+    }
 
 private:
-       CComDynamicUnkArray &operator = (const CComDynamicUnkArray &)
-       {
-               return *this;
-       }
-
-       CComDynamicUnkArray(const CComDynamicUnkArray &)
-       {
-       }
+    CComDynamicUnkArray &operator = (const CComDynamicUnkArray &)
+    {
+        return *this;
+    }
+
+    CComDynamicUnkArray(const CComDynamicUnkArray &)
+    {
+    }
 };
 
 struct _ATL_CONNMAP_ENTRY
 {
-       DWORD_PTR                                                               dwOffset;
+    DWORD_PTR dwOffset;
 };
 
 template <const IID *piid>
 class _ICPLocator
 {
 public:
-       STDMETHOD(_LocCPQueryInterface)(REFIID riid, void **ppvObject) = 0;
-       virtual ULONG STDMETHODCALLTYPE AddRef() = 0;
-       virtual ULONG STDMETHODCALLTYPE Release() = 0;
+    STDMETHOD(_LocCPQueryInterface)(REFIID riid, void **ppvObject) = 0;
+    virtual ULONG STDMETHODCALLTYPE AddRef() = 0;
+    virtual ULONG STDMETHODCALLTYPE Release() = 0;
 };
 
 template<class T, const IID *piid, class CDV = CComDynamicUnkArray>
 class IConnectionPointImpl : public _ICPLocator<piid>
 {
-       typedef CComEnum<IEnumConnections, &IID_IEnumConnections, CONNECTDATA, _Copy<CONNECTDATA> > CComEnumConnections;
+    typedef CComEnum<IEnumConnections, &IID_IEnumConnections, CONNECTDATA, _Copy<CONNECTDATA> > CComEnumConnections;
 public:
-       CDV                                                                             m_vec;
+    CDV m_vec;
 public:
-       ~IConnectionPointImpl()
-       {
-               IUnknown                                                        **x;
-
-               for (x = m_vec.begin(); x < m_vec.end(); x++)
-                       if (*x != NULL)
-                               (*x)->Release();
-       }
-
-       STDMETHOD(_LocCPQueryInterface)(REFIID riid, void **ppvObject)
-       {
-               IConnectionPointImpl<T, piid, CDV>      *pThis;
-
-               pThis = reinterpret_cast<IConnectionPointImpl<T, piid, CDV>*>(this);
-
-               ATLASSERT(ppvObject != NULL);
-               if (ppvObject == NULL)
-                       return E_POINTER;
-
-               if (InlineIsEqualGUID(riid, IID_IConnectionPoint) || InlineIsEqualUnknown(riid))
-               {
-                       *ppvObject = this;
-                       pThis->AddRef();
-                       return S_OK;
-               }
-               else
-               {
-                       *ppvObject = NULL;
-                       return E_NOINTERFACE;
-               }
-       }
-
-       STDMETHOD(GetConnectionInterface)(IID *piid2)
-       {
-               if (piid2 == NULL)
-                       return E_POINTER;
-               *piid2 = *piid;
-               return S_OK;
-       }
-
-       STDMETHOD(GetConnectionPointContainer)(IConnectionPointContainer **ppCPC)
-       {
-               T                                                                       *pThis;
-
-               pThis = static_cast<T *>(this);
-               return pThis->QueryInterface(IID_IConnectionPointContainer, reinterpret_cast<void **>(ppCPC));
-       }
-
-       STDMETHOD(Advise)(IUnknown *pUnkSink, DWORD *pdwCookie)
-       {
-               IUnknown                                                        *adviseTarget;
-               IID                                                                     interfaceID;
-               HRESULT                                                         hResult;
-
-               if (pdwCookie != NULL)
-                       *pdwCookie = 0;
-               if (pUnkSink == NULL || pdwCookie == NULL)
-                       return E_POINTER;
-               GetConnectionInterface(&interfaceID);                   // can't fail
-               hResult = pUnkSink->QueryInterface(interfaceID, reinterpret_cast<void **>(&adviseTarget));
-               if (SUCCEEDED(hResult))
-               {
-                       *pdwCookie = m_vec.Add(adviseTarget);
-                       if (*pdwCookie != 0)
-                               hResult = S_OK;
-                       else
-                       {
-                               adviseTarget->Release();
-                               hResult = CONNECT_E_ADVISELIMIT;
-                       }
-               }
-               else if (hResult == E_NOINTERFACE)
-                       hResult = CONNECT_E_CANNOTCONNECT;
-               return hResult;
-       }
-
-       STDMETHOD(Unadvise)(DWORD dwCookie)
-       {
-               IUnknown                                                        *adviseTarget;
-               HRESULT                                                         hResult;
-
-               adviseTarget = m_vec.GetUnknown(dwCookie);
-               if (m_vec.Remove(dwCookie))
-               {
-                       if (adviseTarget != NULL)
-                               adviseTarget->Release();
-                       hResult = S_OK;
-               }
-               else
-                       hResult = CONNECT_E_NOCONNECTION;
-               return hResult;
-       }
-
-       STDMETHOD(EnumConnections)(IEnumConnections **ppEnum)
-       {
-               CComObject<CComEnumConnections>         *newEnumerator;
-               CONNECTDATA                                                     *itemBuffer;
-               CONNECTDATA                                                     *itemBufferEnd;
-               IUnknown                                                        **x;
-               HRESULT                                                         hResult;
-
-               ATLASSERT(ppEnum != NULL);
-               if (ppEnum == NULL)
-                       return E_POINTER;
-               *ppEnum = NULL;
-
-               ATLTRY(itemBuffer = new CONNECTDATA[m_vec.end() - m_vec.begin()])
-               if (itemBuffer == NULL)
-                       return E_OUTOFMEMORY;
-               itemBufferEnd = itemBuffer;
-               for (x = m_vec.begin(); x < m_vec.end(); x++)
-               {
-                       if (*x != NULL)
-                       {
-                               (*x)->AddRef();
-                               itemBufferEnd->pUnk = *x;
-                               itemBufferEnd->dwCookie = m_vec.GetCookie(x);
-                               itemBufferEnd++;
-                       }
-               }
-               ATLTRY(newEnumerator = new CComObject<CComEnumConnections>)
-               if (newEnumerator == NULL)
-                       return E_OUTOFMEMORY;
-               newEnumerator->Init(itemBuffer, itemBufferEnd, NULL, AtlFlagTakeOwnership);             // can't fail
-               hResult = newEnumerator->_InternalQueryInterface(IID_IEnumConnections, (void **)ppEnum);
-               if (FAILED(hResult))
-                       delete newEnumerator;
-               return hResult;
-       }
+    ~IConnectionPointImpl()
+    {
+        IUnknown **x;
+
+        for (x = m_vec.begin(); x < m_vec.end(); x++)
+            if (*x != NULL)
+                (*x)->Release();
+    }
+
+    STDMETHOD(_LocCPQueryInterface)(REFIID riid, void **ppvObject)
+    {
+        IConnectionPointImpl<T, piid, CDV> *pThis;
+
+        pThis = reinterpret_cast<IConnectionPointImpl<T, piid, CDV>*>(this);
+
+        ATLASSERT(ppvObject != NULL);
+        if (ppvObject == NULL)
+            return E_POINTER;
+
+        if (InlineIsEqualGUID(riid, IID_IConnectionPoint) || InlineIsEqualUnknown(riid))
+        {
+            *ppvObject = this;
+            pThis->AddRef();
+            return S_OK;
+        }
+        else
+        {
+            *ppvObject = NULL;
+            return E_NOINTERFACE;
+        }
+    }
+
+    STDMETHOD(GetConnectionInterface)(IID *piid2)
+    {
+        if (piid2 == NULL)
+            return E_POINTER;
+        *piid2 = *piid;
+        return S_OK;
+    }
+
+    STDMETHOD(GetConnectionPointContainer)(IConnectionPointContainer **ppCPC)
+    {
+        T *pThis;
+
+        pThis = static_cast<T *>(this);
+        return pThis->QueryInterface(IID_IConnectionPointContainer, reinterpret_cast<void **>(ppCPC));
+    }
+
+    STDMETHOD(Advise)(IUnknown *pUnkSink, DWORD *pdwCookie)
+    {
+        IUnknown *adviseTarget;
+        IID interfaceID;
+        HRESULT hResult;
+
+        if (pdwCookie != NULL)
+            *pdwCookie = 0;
+        if (pUnkSink == NULL || pdwCookie == NULL)
+            return E_POINTER;
+        GetConnectionInterface(&interfaceID);            // can't fail
+        hResult = pUnkSink->QueryInterface(interfaceID, reinterpret_cast<void **>(&adviseTarget));
+        if (SUCCEEDED(hResult))
+        {
+            *pdwCookie = m_vec.Add(adviseTarget);
+            if (*pdwCookie != 0)
+                hResult = S_OK;
+            else
+            {
+                adviseTarget->Release();
+                hResult = CONNECT_E_ADVISELIMIT;
+            }
+        }
+        else if (hResult == E_NOINTERFACE)
+            hResult = CONNECT_E_CANNOTCONNECT;
+        return hResult;
+    }
+
+    STDMETHOD(Unadvise)(DWORD dwCookie)
+    {
+        IUnknown *adviseTarget;
+        HRESULT hResult;
+
+        adviseTarget = m_vec.GetUnknown(dwCookie);
+        if (m_vec.Remove(dwCookie))
+        {
+            if (adviseTarget != NULL)
+                adviseTarget->Release();
+            hResult = S_OK;
+        }
+        else
+            hResult = CONNECT_E_NOCONNECTION;
+        return hResult;
+    }
+
+    STDMETHOD(EnumConnections)(IEnumConnections **ppEnum)
+    {
+        CComObject<CComEnumConnections> *newEnumerator;
+        CONNECTDATA *itemBuffer;
+        CONNECTDATA *itemBufferEnd;
+        IUnknown **x;
+        HRESULT hResult;
+
+        ATLASSERT(ppEnum != NULL);
+        if (ppEnum == NULL)
+            return E_POINTER;
+        *ppEnum = NULL;
+
+        ATLTRY(itemBuffer = new CONNECTDATA[m_vec.end() - m_vec.begin()])
+        if (itemBuffer == NULL)
+            return E_OUTOFMEMORY;
+        itemBufferEnd = itemBuffer;
+        for (x = m_vec.begin(); x < m_vec.end(); x++)
+        {
+            if (*x != NULL)
+            {
+                (*x)->AddRef();
+                itemBufferEnd->pUnk = *x;
+                itemBufferEnd->dwCookie = m_vec.GetCookie(x);
+                itemBufferEnd++;
+            }
+        }
+        ATLTRY(newEnumerator = new CComObject<CComEnumConnections>)
+        if (newEnumerator == NULL)
+            return E_OUTOFMEMORY;
+        newEnumerator->Init(itemBuffer, itemBufferEnd, NULL, AtlFlagTakeOwnership);        // can't fail
+        hResult = newEnumerator->_InternalQueryInterface(IID_IEnumConnections, (void **)ppEnum);
+        if (FAILED(hResult))
+            delete newEnumerator;
+        return hResult;
+    }
 };
 
 template <class T>
 class IConnectionPointContainerImpl : public IConnectionPointContainer
 {
-               typedef const _ATL_CONNMAP_ENTRY * (*handlerFunctionType)(int *);
-               typedef CComEnum<IEnumConnectionPoints, &IID_IEnumConnectionPoints, IConnectionPoint *, _CopyInterface<IConnectionPoint> >
-                                               CComEnumConnectionPoints;
+        typedef const _ATL_CONNMAP_ENTRY * (*handlerFunctionType)(int *);
+        typedef CComEnum<IEnumConnectionPoints, &IID_IEnumConnectionPoints, IConnectionPoint *, _CopyInterface<IConnectionPoint> >
+                        CComEnumConnectionPoints;
 
 public:
-       STDMETHOD(EnumConnectionPoints)(IEnumConnectionPoints **ppEnum)
-       {
-               const _ATL_CONNMAP_ENTRY                        *entryPtr;
-               int                                                                     connectionPointCount;
-               IConnectionPoint                                        **itemBuffer;
-               int                                                                     destIndex;
-               handlerFunctionType                                     handlerFunction;
-               CComEnumConnectionPoints                        *newEnumerator;
-               HRESULT                                                         hResult;
-
-               ATLASSERT(ppEnum != NULL);
-               if (ppEnum == NULL)
-                       return E_POINTER;
-               *ppEnum = NULL;
-
-               entryPtr = T::GetConnMap(&connectionPointCount);
-               ATLTRY(itemBuffer = new IConnectionPoint * [connectionPointCount])
-               if (itemBuffer == NULL)
-                       return E_OUTOFMEMORY;
-
-               destIndex = 0;
-               while (entryPtr->dwOffset != static_cast<DWORD_PTR>(-1))
-               {
-                       if (entryPtr->dwOffset == static_cast<DWORD_PTR>(-2))
-                       {
-                               entryPtr++;
-                               handlerFunction = reinterpret_cast<handlerFunctionType>(entryPtr->dwOffset);
-                               entryPtr = handlerFunction(NULL);
-                       }
-                       else
-                       {
-                               itemBuffer[destIndex++] = reinterpret_cast<IConnectionPoint *>((char *)this + entryPtr->dwOffset);
-                               entryPtr++;
-                       }
-               }
-
-               ATLTRY(newEnumerator = new CComObject<CComEnumConnectionPoints>)
-               if (newEnumerator == NULL)
-               {
-                       delete [] itemBuffer;
-                       return E_OUTOFMEMORY;
-               }
-
-               newEnumerator->Init(&itemBuffer[0], &itemBuffer[destIndex], NULL, AtlFlagTakeOwnership);        // can't fail
-               hResult = newEnumerator->QueryInterface(IID_IEnumConnectionPoints, (void**)ppEnum);
-               if (FAILED(hResult))
-                       delete newEnumerator;
-               return hResult;
-       }
-
-       STDMETHOD(FindConnectionPoint)(REFIID riid, IConnectionPoint **ppCP)
-       {
-               IID                                                                     interfaceID;
-               const _ATL_CONNMAP_ENTRY                        *entryPtr;
-               handlerFunctionType                                     handlerFunction;
-               IConnectionPoint                                        *connectionPoint;
-               HRESULT                                                         hResult;
-
-               if (ppCP == NULL)
-                       return E_POINTER;
-               *ppCP = NULL;
-               hResult = CONNECT_E_NOCONNECTION;
-               entryPtr = T::GetConnMap(NULL);
-               while (entryPtr->dwOffset != static_cast<DWORD_PTR>(-1))
-               {
-                       if (entryPtr->dwOffset == static_cast<DWORD_PTR>(-2))
-                       {
-                               entryPtr++;
-                               handlerFunction = reinterpret_cast<handlerFunctionType>(entryPtr->dwOffset);
-                               entryPtr = handlerFunction(NULL);
-                       }
-                       else
-                       {
-                               connectionPoint = reinterpret_cast<IConnectionPoint *>(reinterpret_cast<char *>(this) + entryPtr->dwOffset);
-                               if (SUCCEEDED(connectionPoint->GetConnectionInterface(&interfaceID)) && InlineIsEqualGUID(riid, interfaceID))
-                               {
-                                       *ppCP = connectionPoint;
-                                       connectionPoint->AddRef();
-                                       hResult = S_OK;
-                                       break;
-                               }
-                               entryPtr++;
-                       }
-               }
-               return hResult;
-       }
+    STDMETHOD(EnumConnectionPoints)(IEnumConnectionPoints **ppEnum)
+    {
+        const _ATL_CONNMAP_ENTRY *entryPtr;
+        int connectionPointCount;
+        IConnectionPoint **itemBuffer;
+        int destIndex;
+        handlerFunctionType handlerFunction;
+        CComEnumConnectionPoints *newEnumerator;
+        HRESULT hResult;
+
+        ATLASSERT(ppEnum != NULL);
+        if (ppEnum == NULL)
+            return E_POINTER;
+        *ppEnum = NULL;
+
+        entryPtr = T::GetConnMap(&connectionPointCount);
+        ATLTRY(itemBuffer = new IConnectionPoint * [connectionPointCount])
+        if (itemBuffer == NULL)
+            return E_OUTOFMEMORY;
+
+        destIndex = 0;
+        while (entryPtr->dwOffset != static_cast<DWORD_PTR>(-1))
+        {
+            if (entryPtr->dwOffset == static_cast<DWORD_PTR>(-2))
+            {
+                entryPtr++;
+                handlerFunction = reinterpret_cast<handlerFunctionType>(entryPtr->dwOffset);
+                entryPtr = handlerFunction(NULL);
+            }
+            else
+            {
+                itemBuffer[destIndex++] = reinterpret_cast<IConnectionPoint *>((char *)this + entryPtr->dwOffset);
+                entryPtr++;
+            }
+        }
+
+        ATLTRY(newEnumerator = new CComObject<CComEnumConnectionPoints>)
+        if (newEnumerator == NULL)
+        {
+            delete [] itemBuffer;
+            return E_OUTOFMEMORY;
+        }
+
+        newEnumerator->Init(&itemBuffer[0], &itemBuffer[destIndex], NULL, AtlFlagTakeOwnership);    // can't fail
+        hResult = newEnumerator->QueryInterface(IID_IEnumConnectionPoints, (void**)ppEnum);
+        if (FAILED(hResult))
+            delete newEnumerator;
+        return hResult;
+    }
+
+    STDMETHOD(FindConnectionPoint)(REFIID riid, IConnectionPoint **ppCP)
+    {
+        IID interfaceID;
+        const _ATL_CONNMAP_ENTRY *entryPtr;
+        handlerFunctionType handlerFunction;
+        IConnectionPoint *connectionPoint;
+        HRESULT hResult;
+
+        if (ppCP == NULL)
+            return E_POINTER;
+        *ppCP = NULL;
+        hResult = CONNECT_E_NOCONNECTION;
+        entryPtr = T::GetConnMap(NULL);
+        while (entryPtr->dwOffset != static_cast<DWORD_PTR>(-1))
+        {
+            if (entryPtr->dwOffset == static_cast<DWORD_PTR>(-2))
+            {
+                entryPtr++;
+                handlerFunction = reinterpret_cast<handlerFunctionType>(entryPtr->dwOffset);
+                entryPtr = handlerFunction(NULL);
+            }
+            else
+            {
+                connectionPoint = reinterpret_cast<IConnectionPoint *>(reinterpret_cast<char *>(this) + entryPtr->dwOffset);
+                if (SUCCEEDED(connectionPoint->GetConnectionInterface(&interfaceID)) && InlineIsEqualGUID(riid, interfaceID))
+                {
+                    *ppCP = connectionPoint;
+                    connectionPoint->AddRef();
+                    hResult = S_OK;
+                    break;
+                }
+                entryPtr++;
+            }
+        }
+        return hResult;
+    }
 };
 
-#define BEGIN_CONNECTION_POINT_MAP(x)                                                                                  \
-       typedef x _atl_conn_classtype;                                                                                          \
-       static const ATL::_ATL_CONNMAP_ENTRY *GetConnMap(int *pnEntries) {                      \
-       static const ATL::_ATL_CONNMAP_ENTRY _entries[] = {
-
-#define END_CONNECTION_POINT_MAP()                                                                                             \
-       {(DWORD_PTR)-1} };                                                                                                                      \
-       if (pnEntries)                                                                                                                          \
-               *pnEntries = sizeof(_entries) / sizeof(ATL::_ATL_CONNMAP_ENTRY) - 1;    \
-       return _entries;}
+#define BEGIN_CONNECTION_POINT_MAP(x)                                            \
+    typedef x _atl_conn_classtype;                                                \
+    static const ATL::_ATL_CONNMAP_ENTRY *GetConnMap(int *pnEntries) {            \
+    static const ATL::_ATL_CONNMAP_ENTRY _entries[] = {
+
+#define END_CONNECTION_POINT_MAP()                                                \
+    {(DWORD_PTR)-1} };                                                            \
+    if (pnEntries)                                                                \
+        *pnEntries = sizeof(_entries) / sizeof(ATL::_ATL_CONNMAP_ENTRY) - 1;    \
+    return _entries;}
+
+#define CONNECTION_POINT_ENTRY(iid)                                                \
+    {offsetofclass(ATL::_ICPLocator<&iid>, _atl_conn_classtype) -                \
+    offsetofclass(ATL::IConnectionPointContainerImpl<_atl_conn_classtype>, _atl_conn_classtype)},
+
+
+
+/* TODO:
+ - IDispatchImpl contains a static member of type CComTypeInfoHolder that manages the type information for the dual interface.
+   If you have multiple objects that implement the same dual interface, only one instance of CComTypeInfoHolder is used.
+ - By default, the IDispatchImpl class looks up the type information for T in the registry.
+   To implement an unregistered interface, you can use the IDispatchImpl class without accessing the registry by using a predefined version number.
+   If you create an IDispatchImpl object that has 0xFFFF as the value for wMajor and 0xFFFF as the value for wMinor,
+   the IDispatchImpl class retrieves the type library from the .dll file instead of the registry.
+*/
+template<class T, const IID* piid /*= &__uuidof(T)*/, const GUID* plibid = &CAtlModule::m_libid, WORD wMajor = 1, WORD wMinor = 0>
+class IDispatchImpl :
+    public T
+{
+private:
+    CComPtr<ITypeInfo> m_pTypeInfo;
+
+    STDMETHOD(EnsureTILoaded)(LCID lcid)
+    {
+        HRESULT hr = S_OK;
+        if (m_pTypeInfo != NULL)
+            return hr;
+
+        if (IsEqualCLSID(CLSID_NULL, *plibid))
+            OutputDebugStringA("IDispatchImpl: plibid is CLSID_NULL!\r\n");
+
+        // Should we assert here?
+        if (wMajor == 0xffff && wMinor == 0xffff)
+            OutputDebugStringA("IDispatchImpl: not fully implemented, missing functionality to load TLB from file!\r\n");
+
+        CComPtr<ITypeLib> spTypeLib;
+        hr = LoadRegTypeLib(*plibid, wMajor, wMinor, lcid, &spTypeLib);
+        if (SUCCEEDED(hr))
+        {
+            hr = spTypeLib->GetTypeInfoOfGuid(*piid, &m_pTypeInfo);
+        }
+        return hr;
+    }
 
-#define CONNECTION_POINT_ENTRY(iid)                                                                                            \
-       {offsetofclass(ATL::_ICPLocator<&iid>, _atl_conn_classtype) -                           \
-       offsetofclass(ATL::IConnectionPointContainerImpl<_atl_conn_classtype>, _atl_conn_classtype)},
+public:
+    IDispatchImpl()
+    {
+    }
+
+
+    // *** IDispatch methods ***
+    STDMETHOD(GetTypeInfoCount)(UINT *pctinfo)
+    {
+        if (pctinfo == NULL)
+            return E_POINTER;
+
+        *pctinfo = 1;
+        return S_OK;
+    }
+
+    STDMETHOD(GetTypeInfo)(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
+    {
+        if (iTInfo != 0)
+            return DISP_E_BADINDEX;
+        if (ppTInfo == NULL)
+            return E_POINTER;
+
+        HRESULT hr = EnsureTILoaded(lcid);
+        *ppTInfo = m_pTypeInfo;
+        if (*ppTInfo)
+            (*ppTInfo)->AddRef();
+
+        return hr;
+    }
+
+    STDMETHOD(GetIDsOfNames)(REFIID /*riid*/, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
+    {
+        HRESULT hr = EnsureTILoaded(lcid);
+        if (SUCCEEDED(hr))
+            hr = m_pTypeInfo->GetIDsOfNames(rgszNames, cNames, rgDispId);
+        return hr;
+    }
+
+    STDMETHOD(Invoke)(DISPID dispIdMember, REFIID /*riid*/, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
+    {
+        HRESULT hr = EnsureTILoaded(lcid);
+        if (SUCCEEDED(hr))
+            hr = m_pTypeInfo->Invoke(this, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
+        return hr;
+    }
+};
 
 }; // namespace ATL