ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

atlcom.h
Go to the documentation of this file.
00001 /*
00002  * ReactOS ATL
00003  *
00004  * Copyright 2009 Andrew Hill <ash77@reactos.org>
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00019  */
00020 
00021 #pragma once
00022 
00023 namespace ATL
00024 {
00025 
00026 template <class Base, const IID *piid, class T, class Copy, class ThreadModel = CComObjectThreadModel>
00027 class CComEnum;
00028 
00029 #define DECLARE_CLASSFACTORY_EX(cf) typedef ATL::CComCreator<ATL::CComObjectCached<cf> > _ClassFactoryCreatorClass;
00030 #define DECLARE_CLASSFACTORY() DECLARE_CLASSFACTORY_EX(ATL::CComClassFactory)
00031 
00032 class CComObjectRootBase
00033 {
00034 public:
00035     LONG                                    m_dwRef;
00036 public:
00037     CComObjectRootBase()
00038     {
00039         m_dwRef = 0;
00040     }
00041 
00042     ~CComObjectRootBase()
00043     {
00044     }
00045 
00046     void SetVoid(void *)
00047     {
00048     }
00049 
00050     HRESULT _AtlFinalConstruct()
00051     {
00052         return S_OK;
00053     }
00054 
00055     HRESULT FinalConstruct()
00056     {
00057         return S_OK;
00058     }
00059 
00060     void InternalFinalConstructAddRef()
00061     {
00062     }
00063 
00064     void InternalFinalConstructRelease()
00065     {
00066     }
00067 
00068     void FinalRelease()
00069     {
00070     }
00071 
00072     static void WINAPI ObjectMain(bool)
00073     {
00074     }
00075 
00076     static const struct _ATL_CATMAP_ENTRY *GetCategoryMap()
00077     {
00078         return NULL;
00079     }
00080 
00081     static HRESULT WINAPI InternalQueryInterface(void *pThis, const _ATL_INTMAP_ENTRY *pEntries, REFIID iid, void **ppvObject)
00082     {
00083         return AtlInternalQueryInterface(pThis, pEntries, iid, ppvObject);
00084     }
00085 
00086 };
00087 
00088 template <class ThreadModel>
00089 class CComObjectRootEx : public CComObjectRootBase
00090 {
00091 private:
00092     typename ThreadModel::AutoDeleteCriticalSection     m_critsec;
00093 public:
00094     ~CComObjectRootEx()
00095     {
00096     }
00097 
00098     ULONG InternalAddRef()
00099     {
00100         ATLASSERT(m_dwRef >= 0);
00101         return ThreadModel::Increment(&m_dwRef);
00102     }
00103 
00104     ULONG InternalRelease()
00105     {
00106         ATLASSERT(m_dwRef > 0);
00107         return ThreadModel::Decrement(&m_dwRef);
00108     }
00109 
00110     void Lock()
00111     {
00112         m_critsec.Lock();
00113     }
00114 
00115     void Unlock()
00116     {
00117         m_critsec.Unlock();
00118     }
00119 
00120     HRESULT _AtlInitialConstruct()
00121     {
00122         return m_critsec.Init();
00123     }
00124 };
00125 
00126 template <class Base>
00127 class CComObject : public Base
00128 {
00129 public:
00130     CComObject(void * = NULL)
00131     {
00132         _pAtlModule->Lock();
00133     }
00134 
00135     virtual ~CComObject()
00136     {
00137         CComObject<Base>                    *pThis;
00138 
00139         pThis = reinterpret_cast<CComObject<Base> *>(this);
00140         pThis->FinalRelease();
00141         _pAtlModule->Unlock();
00142     }
00143 
00144     STDMETHOD_(ULONG, AddRef)()
00145     {
00146         CComObject<Base>                    *pThis;
00147 
00148         pThis = reinterpret_cast<CComObject<Base> *>(this);
00149         return pThis->InternalAddRef();
00150     }
00151 
00152     STDMETHOD_(ULONG, Release)()
00153     {
00154         CComObject<Base>                    *pThis;
00155         ULONG                               l;
00156 
00157         pThis = reinterpret_cast<CComObject<Base> *>(this);
00158         l = pThis->InternalRelease();
00159         if (l == 0)
00160             delete this;
00161         return l;
00162     }
00163 
00164     STDMETHOD(QueryInterface)(REFIID iid, void **ppvObject)
00165     {
00166         CComObject<Base>                    *pThis;
00167 
00168         pThis = reinterpret_cast<CComObject<Base> *>(this);
00169         return pThis->_InternalQueryInterface(iid, ppvObject);
00170     }
00171 
00172     static HRESULT WINAPI CreateInstance(CComObject<Base> **pp)
00173     {
00174         CComObject<Base>                    *newInstance;
00175         HRESULT                             hResult;
00176 
00177         ATLASSERT(pp != NULL);
00178         if (pp == NULL)
00179             return E_POINTER;
00180 
00181         hResult = E_OUTOFMEMORY;
00182         newInstance = NULL;
00183         ATLTRY(newInstance = new CComObject<Base>())
00184         if (newInstance != NULL)
00185         {
00186             newInstance->SetVoid(NULL);
00187             newInstance->InternalFinalConstructAddRef();
00188             hResult = newInstance->_AtlInitialConstruct();
00189             if (SUCCEEDED(hResult))
00190                 hResult = newInstance->FinalConstruct();
00191             if (SUCCEEDED(hResult))
00192                 hResult = newInstance->_AtlFinalConstruct();
00193             newInstance->InternalFinalConstructRelease();
00194             if (hResult != S_OK)
00195             {
00196                 delete newInstance;
00197                 newInstance = NULL;
00198             }
00199         }
00200         *pp = newInstance;
00201         return hResult;
00202     }
00203 
00204 
00205 };
00206 
00207 template <HRESULT hResult>
00208 class CComFailCreator
00209 {
00210 public:
00211     static HRESULT WINAPI CreateInstance(void *, REFIID, LPVOID *ppv)
00212     {
00213         ATLASSERT(ppv != NULL);
00214         if (ppv == NULL)
00215             return E_POINTER;
00216         *ppv = NULL;
00217 
00218         return hResult;
00219     }
00220 };
00221 
00222 template <class T1>
00223 class CComCreator
00224 {
00225 public:
00226     static HRESULT WINAPI CreateInstance(void *pv, REFIID riid, LPVOID *ppv)
00227     {
00228         T1                                  *newInstance;
00229         HRESULT                             hResult;
00230 
00231         ATLASSERT(ppv != NULL);
00232         if (ppv == NULL)
00233             return E_POINTER;
00234         *ppv = NULL;
00235 
00236         hResult = E_OUTOFMEMORY;
00237         newInstance = NULL;
00238         ATLTRY(newInstance = new T1())
00239         if (newInstance != NULL)
00240         {
00241             newInstance->SetVoid(pv);
00242             newInstance->InternalFinalConstructAddRef();
00243             hResult = newInstance->_AtlInitialConstruct();
00244             if (SUCCEEDED(hResult))
00245                 hResult = newInstance->FinalConstruct();
00246             if (SUCCEEDED(hResult))
00247                 hResult = newInstance->_AtlFinalConstruct();
00248             newInstance->InternalFinalConstructRelease();
00249             if (SUCCEEDED(hResult))
00250                 hResult = newInstance->QueryInterface(riid, ppv);
00251             if (FAILED(hResult))
00252             {
00253                 delete newInstance;
00254                 newInstance = NULL;
00255             }
00256         }
00257         return hResult;
00258     }
00259 };
00260 
00261 template <class T1, class T2>
00262 class CComCreator2
00263 {
00264 public:
00265     static HRESULT WINAPI CreateInstance(void *pv, REFIID riid, LPVOID *ppv)
00266     {
00267         ATLASSERT(ppv != NULL && ppv != NULL);
00268 
00269         if (pv == NULL)
00270             return T1::CreateInstance(NULL, riid, ppv);
00271         else
00272             return T2::CreateInstance(pv, riid, ppv);
00273     }
00274 };
00275 
00276 template <class Base>
00277 class CComObjectCached : public Base
00278 {
00279 public:
00280     CComObjectCached(void * = NULL)
00281     {
00282     }
00283 
00284     STDMETHOD_(ULONG, AddRef)()
00285     {
00286         CComObjectCached<Base>              *pThis;
00287         ULONG                               newRefCount;
00288 
00289         pThis = reinterpret_cast<CComObjectCached<Base>*>(this);
00290         newRefCount = pThis->InternalAddRef();
00291         if (newRefCount == 2)
00292             _pAtlModule->Lock();
00293         return newRefCount;
00294     }
00295 
00296     STDMETHOD_(ULONG, Release)()
00297     {
00298         CComObjectCached<Base>              *pThis;
00299         ULONG                               newRefCount;
00300 
00301         pThis = reinterpret_cast<CComObjectCached<Base>*>(this);
00302         newRefCount = pThis->InternalRelease();
00303         if (newRefCount == 0)
00304             delete this;
00305         else if (newRefCount == 1)
00306             _pAtlModule->Unlock();
00307         return newRefCount;
00308     }
00309 
00310     STDMETHOD(QueryInterface)(REFIID iid, void **ppvObject)
00311     {
00312         CComObjectCached<Base>              *pThis;
00313 
00314         pThis = reinterpret_cast<CComObjectCached<Base>*>(this);
00315         return pThis->_InternalQueryInterface(iid, ppvObject);
00316     }
00317 };
00318 
00319 #define BEGIN_COM_MAP(x)                                                        \
00320 public:                                                                         \
00321     typedef x _ComMapClass;                                                     \
00322     HRESULT _InternalQueryInterface(REFIID iid, void **ppvObject)               \
00323     {                                                                           \
00324         return this->InternalQueryInterface(this, _GetEntries(), iid, ppvObject);       \
00325     }                                                                           \
00326     const static ATL::_ATL_INTMAP_ENTRY *WINAPI _GetEntries()                   \
00327     {                                                                           \
00328         static const ATL::_ATL_INTMAP_ENTRY _entries[] = {
00329 
00330 #define END_COM_MAP()                                                           \
00331             {NULL, 0, 0}                                                        \
00332         };                                                                      \
00333         return _entries;                                                        \
00334     }                                                                           \
00335     virtual ULONG STDMETHODCALLTYPE AddRef() = 0;                               \
00336     virtual ULONG STDMETHODCALLTYPE Release() = 0;                              \
00337     STDMETHOD(QueryInterface)(REFIID, void **) = 0;
00338 
00339 #define COM_INTERFACE_ENTRY_IID(iid, x)                                         \
00340     {&iid, offsetofclass(x, _ComMapClass), _ATL_SIMPLEMAPENTRY},
00341 
00342 #define COM_INTERFACE_ENTRY2_IID(iid, x, x2)                                    \
00343     {&iid,                                                                      \
00344             reinterpret_cast<DWORD_PTR>(static_cast<x *>(static_cast<x2 *>(reinterpret_cast<_ComMapClass *>(_ATL_PACKING)))) - _ATL_PACKING,    \
00345             _ATL_SIMPLEMAPENTRY},
00346 
00347 #define COM_INTERFACE_ENTRY_BREAK(x)                                            \
00348     {&_ATL_IIDOF(x),                                                            \
00349     NULL,                                                                       \
00350     _Break},    // Break is a function that issues int 3.
00351 
00352 #define COM_INTERFACE_ENTRY_NOINTERFACE(x)                                      \
00353     {&_ATL_IIDOF(x),                                                            \
00354     NULL,                                                                       \
00355     _NoInterface}, // NoInterface returns E_NOINTERFACE.
00356 
00357 #define COM_INTERFACE_ENTRY_FUNC(iid, dw, func)                                 \
00358     {&iid,                                                                      \
00359     dw,                                                                         \
00360     func},
00361 
00362 #define COM_INTERFACE_ENTRY_FUNC_BLIND(dw, func)                                \
00363     {NULL,                                                                      \
00364     dw,                                                                         \
00365     func},
00366 
00367 #define COM_INTERFACE_ENTRY_CHAIN(classname)                                    \
00368     {NULL,                                                                      \
00369     reinterpret_cast<DWORD>(&_CComChainData<classname, _ComMapClass>::data),    \
00370     _Chain},
00371 
00372 #define DECLARE_NO_REGISTRY()\
00373     static HRESULT WINAPI UpdateRegistry(BOOL /*bRegister*/)                    \
00374     {                                                                           \
00375         return S_OK;                                                            \
00376     }
00377 
00378 #define DECLARE_REGISTRY_RESOURCEID(x)                                          \
00379     static HRESULT WINAPI UpdateRegistry(BOOL bRegister)                        \
00380     {                                                                           \
00381         return ATL::_pAtlModule->UpdateRegistryFromResource(x, bRegister);      \
00382     }
00383 
00384 #define DECLARE_NOT_AGGREGATABLE(x)                                             \
00385 public:                                                                         \
00386     typedef ATL::CComCreator2<ATL::CComCreator<ATL::CComObject<x> >, ATL::CComFailCreator<CLASS_E_NOAGGREGATION> > _CreatorClass;
00387 
00388 #define DECLARE_AGGREGATABLE(x)                                                 \
00389 public:                                                                         \
00390     typedef CComCreator2<CComCreator<CComObject<x> >, CComCreator<CComAggObject<x> > > _CreatorClass;
00391 
00392 #define DECLARE_ONLY_AGGREGATABLE(x)                                            \
00393 public:                                                                         \
00394     typedef CComCreator2<CComFailCreator<E_FAIL>, CComCreator<CComAggObject<x> > > _CreatorClass;
00395 
00396 #define DECLARE_POLY_AGGREGATABLE(x)                                            \
00397 public:                                                                         \
00398     typedef CComCreator<CComPolyObject<x> > _CreatorClass;
00399 
00400 #define DECLARE_GET_CONTROLLING_UNKNOWN()                                       \
00401 public:                                                                         \
00402     virtual IUnknown *GetControllingUnknown()                                   \
00403     {                                                                           \
00404         return GetUnknown();                                                    \
00405     }
00406 
00407 #define DECLARE_PROTECT_FINAL_CONSTRUCT()                                       \
00408     void InternalFinalConstructAddRef()                                         \
00409     {                                                                           \
00410         InternalAddRef();                                                       \
00411     }                                                                           \
00412     void InternalFinalConstructRelease()                                        \
00413     {                                                                           \
00414         InternalRelease();                                                      \
00415     }
00416 
00417 #define BEGIN_OBJECT_MAP(x) static ATL::_ATL_OBJMAP_ENTRY x[] = {
00418 
00419 #define END_OBJECT_MAP()   {NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL}};
00420 
00421 #define OBJECT_ENTRY(clsid, class)                                              \
00422 {                                                                               \
00423     &clsid,                                                                     \
00424     class::UpdateRegistry,                                                      \
00425     class::_ClassFactoryCreatorClass::CreateInstance,                           \
00426     class::_CreatorClass::CreateInstance,                                       \
00427     NULL,                                                                       \
00428     0,                                                                          \
00429     class::GetObjectDescription,                                                \
00430     class::GetCategoryMap,                                                      \
00431     class::ObjectMain },
00432 
00433 class CComClassFactory :
00434     public IClassFactory,
00435     public CComObjectRootEx<CComGlobalsThreadModel>
00436 {
00437 public:
00438     _ATL_CREATORFUNC                        *m_pfnCreateInstance;
00439 public:
00440     STDMETHOD(CreateInstance)(LPUNKNOWN pUnkOuter, REFIID riid, void **ppvObj)
00441     {
00442         HRESULT                             hResult;
00443 
00444         ATLASSERT(m_pfnCreateInstance != NULL);
00445 
00446         if (ppvObj == NULL)
00447             return E_POINTER;
00448         *ppvObj = NULL;
00449 
00450         if (pUnkOuter != NULL && InlineIsEqualUnknown(riid) == FALSE)
00451             hResult = CLASS_E_NOAGGREGATION;
00452         else
00453             hResult = m_pfnCreateInstance(pUnkOuter, riid, ppvObj);
00454         return hResult;
00455     }
00456 
00457     STDMETHOD(LockServer)(BOOL fLock)
00458     {
00459         if (fLock)
00460             _pAtlModule->Lock();
00461         else
00462             _pAtlModule->Unlock();
00463         return S_OK;
00464     }
00465 
00466     void SetVoid(void *pv)
00467     {
00468         m_pfnCreateInstance = (_ATL_CREATORFUNC *)pv;
00469     }
00470 
00471     BEGIN_COM_MAP(CComClassFactory)
00472         COM_INTERFACE_ENTRY_IID(IID_IClassFactory, IClassFactory)
00473     END_COM_MAP()
00474 };
00475 
00476 template <class T, const CLSID *pclsid = &CLSID_NULL>
00477 class CComCoClass
00478 {
00479 public:
00480     DECLARE_CLASSFACTORY()
00481 
00482     static LPCTSTR WINAPI GetObjectDescription()
00483     {
00484         return NULL;
00485     }
00486 };
00487 
00488 template <class T>
00489 class _Copy
00490 {
00491 public:
00492     static HRESULT copy(T *pTo, const T *pFrom)
00493     {
00494         memcpy(pTo, pFrom, sizeof(T));
00495         return S_OK;
00496     }
00497 
00498     static void init(T *)
00499     {
00500     }
00501 
00502     static void destroy(T *)
00503     {
00504     }
00505 };
00506 
00507 template<>
00508 class _Copy<CONNECTDATA>
00509 {
00510 public:
00511     static HRESULT copy(CONNECTDATA *pTo, const CONNECTDATA *pFrom)
00512     {
00513         *pTo = *pFrom;
00514         if (pTo->pUnk)
00515             pTo->pUnk->AddRef();
00516         return S_OK;
00517     }
00518 
00519     static void init(CONNECTDATA *)
00520     {
00521     }
00522 
00523     static void destroy(CONNECTDATA *p)
00524     {
00525         if (p->pUnk)
00526             p->pUnk->Release();
00527     }
00528 };
00529 
00530 template <class T>
00531 class _CopyInterface
00532 {
00533 public:
00534     static HRESULT copy(T **pTo, T **pFrom)
00535     {
00536         *pTo = *pFrom;
00537         if (*pTo)
00538             (*pTo)->AddRef();
00539         return S_OK;
00540     }
00541 
00542     static void init(T **)
00543     {
00544     }
00545 
00546     static void destroy(T **p)
00547     {
00548         if (*p)
00549             (*p)->Release();
00550     }
00551 };
00552 
00553 enum CComEnumFlags
00554 {
00555     AtlFlagNoCopy = 0,
00556     AtlFlagTakeOwnership = 2,       // BitOwn
00557     AtlFlagCopy = 3                 // BitOwn | BitCopy
00558 };
00559 
00560 template <class Base, const IID *piid, class T, class Copy>
00561 class CComEnumImpl : public Base
00562 {
00563 private:
00564     typedef CComObject<CComEnum<Base, piid, T, Copy> > enumeratorClass;
00565 public:
00566     CComPtr<IUnknown>                       m_spUnk;
00567     DWORD                                   m_dwFlags;
00568     T                                       *m_begin;
00569     T                                       *m_end;
00570     T                                       *m_iter;
00571 public:
00572     CComEnumImpl()
00573     {
00574         m_dwFlags = 0;
00575         m_begin = NULL;
00576         m_end = NULL;
00577         m_iter = NULL;
00578     }
00579 
00580     virtual ~CComEnumImpl()
00581     {
00582         T                                   *x;
00583 
00584         if ((m_dwFlags & BitOwn) != 0)
00585         {
00586             for (x = m_begin; x != m_end; x++)
00587                 Copy::destroy(x);
00588             delete [] m_begin;
00589         }
00590     }
00591 
00592     HRESULT Init(T *begin, T *end, IUnknown *pUnk, CComEnumFlags flags = AtlFlagNoCopy)
00593     {
00594         T                                   *newBuffer;
00595         T                                   *sourcePtr;
00596         T                                   *destPtr;
00597         T                                   *cleanupPtr;
00598         HRESULT                             hResult;
00599 
00600         if (flags == AtlFlagCopy)
00601         {
00602             ATLTRY(newBuffer = new T[end - begin])
00603             if (newBuffer == NULL)
00604                 return E_OUTOFMEMORY;
00605             destPtr = newBuffer;
00606             for (sourcePtr = begin; sourcePtr != end; sourcePtr++)
00607             {
00608                 Copy::init(destPtr);
00609                 hResult = Copy::copy(destPtr, sourcePtr);
00610                 if (FAILED(hResult))
00611                 {
00612                     cleanupPtr = m_begin;
00613                     while (cleanupPtr < destPtr)
00614                         Copy::destroy(cleanupPtr++);
00615                     delete [] newBuffer;
00616                     return hResult;
00617                 }
00618                 destPtr++;
00619             }
00620             m_begin = newBuffer;
00621             m_end = m_begin + (end - begin);
00622         }
00623         else
00624         {
00625             m_begin = begin;
00626             m_end = end;
00627         }
00628         m_spUnk = pUnk;
00629         m_dwFlags = flags;
00630         m_iter = m_begin;
00631         return S_OK;
00632     }
00633 
00634     STDMETHOD(Next)(ULONG celt, T *rgelt, ULONG *pceltFetched)
00635     {
00636         ULONG                               numAvailable;
00637         ULONG                               numToFetch;
00638         T                                   *rgeltTemp;
00639         HRESULT                             hResult;
00640 
00641         if (pceltFetched != NULL)
00642             *pceltFetched = 0;
00643         if (celt == 0)
00644             return E_INVALIDARG;
00645         if (rgelt == NULL || (celt != 1 && pceltFetched == NULL))
00646             return E_POINTER;
00647         if (m_begin == NULL || m_end == NULL || m_iter == NULL)
00648             return E_FAIL;
00649 
00650         numAvailable = static_cast<ULONG>(m_end - m_iter);
00651         if (celt < numAvailable)
00652             numToFetch = celt;
00653         else
00654             numToFetch = numAvailable;
00655         if (pceltFetched != NULL)
00656             *pceltFetched = numToFetch;
00657         rgeltTemp = rgelt;
00658         while (numToFetch != 0)
00659         {
00660             hResult = Copy::copy(rgeltTemp, m_iter);
00661             if (FAILED(hResult))
00662             {
00663                 while (rgelt < rgeltTemp)
00664                     Copy::destroy(rgelt++);
00665                 if (pceltFetched != NULL)
00666                     *pceltFetched = 0;
00667                 return hResult;
00668             }
00669             rgeltTemp++;
00670             m_iter++;
00671             numToFetch--;
00672         }
00673         if (numAvailable < celt)
00674             return S_FALSE;
00675         return S_OK;
00676     }
00677 
00678     STDMETHOD(Skip)(ULONG celt)
00679     {
00680         ULONG                               numAvailable;
00681         ULONG                               numToSkip;
00682 
00683         if (celt == 0)
00684             return E_INVALIDARG;
00685 
00686         numAvailable = static_cast<ULONG>(m_end - m_iter);
00687         if (celt < numAvailable)
00688             numToSkip = celt;
00689         else
00690             numToSkip = numAvailable;
00691         m_iter += numToSkip;
00692         if (numAvailable < celt)
00693             return S_FALSE;
00694         return S_OK;
00695     }
00696 
00697     STDMETHOD(Reset)()
00698     {
00699         m_iter = m_begin;
00700         return S_OK;
00701     }
00702 
00703     STDMETHOD(Clone)(Base **ppEnum)
00704     {
00705         enumeratorClass                     *newInstance;
00706         HRESULT                             hResult;
00707 
00708         hResult = E_POINTER;
00709         if (ppEnum != NULL)
00710         {
00711             *ppEnum = NULL;
00712             hResult = enumeratorClass::CreateInstance(&newInstance);
00713             if (SUCCEEDED(hResult))
00714             {
00715                 hResult = newInstance->Init(m_begin, m_end, (m_dwFlags & BitOwn) ? this : m_spUnk);
00716                 if (SUCCEEDED(hResult))
00717                 {
00718                     newInstance->m_iter = m_iter;
00719                     hResult = newInstance->_InternalQueryInterface(*piid, (void **)ppEnum);
00720                 }
00721                 if (FAILED(hResult))
00722                     delete newInstance;
00723             }
00724         }
00725         return hResult;
00726     }
00727 
00728 protected:
00729     enum FlagBits
00730     {
00731         BitCopy = 1,
00732         BitOwn = 2
00733     };
00734 };
00735 
00736 template <class Base, const IID *piid, class T, class Copy, class ThreadModel>
00737 class CComEnum :
00738     public CComEnumImpl<Base, piid, T, Copy>,
00739     public CComObjectRootEx<ThreadModel>
00740 {
00741 public:
00742     typedef CComEnum<Base, piid, T, Copy > _CComEnum;
00743     typedef CComEnumImpl<Base, piid, T, Copy > _CComEnumBase;
00744 
00745     BEGIN_COM_MAP(_CComEnum)
00746         COM_INTERFACE_ENTRY_IID(*piid, _CComEnumBase)
00747     END_COM_MAP()
00748 };
00749 
00750 #ifndef _DEFAULT_VECTORLENGTH
00751 #define _DEFAULT_VECTORLENGTH 4
00752 #endif
00753 
00754 class CComDynamicUnkArray
00755 {
00756 public:
00757     int                                     m_nSize;
00758     IUnknown                                **m_ppUnk;
00759 public:
00760     CComDynamicUnkArray()
00761     {
00762         m_nSize = 0;
00763         m_ppUnk = NULL;
00764     }
00765 
00766     ~CComDynamicUnkArray()
00767     {
00768         free(m_ppUnk);
00769     }
00770 
00771     IUnknown **begin()
00772     {
00773         return m_ppUnk;
00774     }
00775 
00776     IUnknown **end()
00777     {
00778         return &m_ppUnk[m_nSize];
00779     }
00780 
00781     IUnknown *GetAt(int nIndex)
00782     {
00783         ATLASSERT(nIndex >= 0 && nIndex < m_nSize);
00784         if (nIndex >= 0 && nIndex < m_nSize)
00785             return m_ppUnk[nIndex];
00786         else
00787             return NULL;
00788     }
00789 
00790     IUnknown *WINAPI GetUnknown(DWORD dwCookie)
00791     {
00792         ATLASSERT(dwCookie != 0 && dwCookie <= static_cast<DWORD>(m_nSize));
00793         if (dwCookie != 0 && dwCookie <= static_cast<DWORD>(m_nSize))
00794             return GetAt(dwCookie - 1);
00795         else
00796             return NULL;
00797     }
00798 
00799     DWORD WINAPI GetCookie(IUnknown **ppFind)
00800     {
00801         IUnknown                            **x;
00802         DWORD                               curCookie;
00803 
00804         ATLASSERT(ppFind != NULL && *ppFind != NULL);
00805         if (ppFind != NULL && *ppFind != NULL)
00806         {
00807             curCookie = 1;
00808             for (x = begin(); x < end(); x++)
00809             {
00810                 if (*x == *ppFind)
00811                     return curCookie;
00812                 curCookie++;
00813             }
00814         }
00815         return 0;
00816     }
00817 
00818     DWORD Add(IUnknown *pUnk)
00819     {
00820         IUnknown                            **x;
00821         IUnknown                            **newArray;
00822         int                                 newSize;
00823         DWORD                               curCookie;
00824 
00825         ATLASSERT(pUnk != NULL);
00826         if (m_nSize == 0)
00827         {
00828             newSize = _DEFAULT_VECTORLENGTH * sizeof(IUnknown *);
00829             ATLTRY(newArray = reinterpret_cast<IUnknown **>(malloc(newSize)));
00830             if (newArray == NULL)
00831                 return 0;
00832             memset(newArray, 0, newSize);
00833             m_ppUnk = newArray;
00834             m_nSize = _DEFAULT_VECTORLENGTH;
00835         }
00836         curCookie = 1;
00837         for (x = begin(); x < end(); x++)
00838         {
00839             if (*x == NULL)
00840             {
00841                 *x = pUnk;
00842                 return curCookie;
00843             }
00844             curCookie++;
00845         }
00846         newSize = m_nSize * 2;
00847         newArray = reinterpret_cast<IUnknown **>(realloc(m_ppUnk, newSize * sizeof(IUnknown *)));
00848         if (newArray == NULL)
00849             return 0;
00850         m_ppUnk = newArray;
00851         memset(&m_ppUnk[m_nSize], 0, (newSize - m_nSize) * sizeof(IUnknown *));
00852         curCookie = m_nSize + 1;
00853         m_nSize = newSize;
00854         m_ppUnk[curCookie - 1] = pUnk;
00855         return curCookie;
00856     }
00857 
00858     BOOL Remove(DWORD dwCookie)
00859     {
00860         DWORD                               index;
00861 
00862         index = dwCookie - 1;
00863         ATLASSERT(index < dwCookie && index < static_cast<DWORD>(m_nSize));
00864         if (index < dwCookie && index < static_cast<DWORD>(m_nSize) && m_ppUnk[index] != NULL)
00865         {
00866             m_ppUnk[index] = NULL;
00867             return TRUE;
00868         }
00869         return FALSE;
00870     }
00871 
00872 private:
00873     CComDynamicUnkArray &operator = (const CComDynamicUnkArray &)
00874     {
00875         return *this;
00876     }
00877 
00878     CComDynamicUnkArray(const CComDynamicUnkArray &)
00879     {
00880     }
00881 };
00882 
00883 struct _ATL_CONNMAP_ENTRY
00884 {
00885     DWORD_PTR                               dwOffset;
00886 };
00887 
00888 template <const IID *piid>
00889 class _ICPLocator
00890 {
00891 public:
00892     STDMETHOD(_LocCPQueryInterface)(REFIID riid, void **ppvObject) = 0;
00893     virtual ULONG STDMETHODCALLTYPE AddRef() = 0;
00894     virtual ULONG STDMETHODCALLTYPE Release() = 0;
00895 };
00896 
00897 template<class T, const IID *piid, class CDV = CComDynamicUnkArray>
00898 class IConnectionPointImpl : public _ICPLocator<piid>
00899 {
00900     typedef CComEnum<IEnumConnections, &IID_IEnumConnections, CONNECTDATA, _Copy<CONNECTDATA> > CComEnumConnections;
00901 public:
00902     CDV                                     m_vec;
00903 public:
00904     ~IConnectionPointImpl()
00905     {
00906         IUnknown                            **x;
00907 
00908         for (x = m_vec.begin(); x < m_vec.end(); x++)
00909             if (*x != NULL)
00910                 (*x)->Release();
00911     }
00912 
00913     STDMETHOD(_LocCPQueryInterface)(REFIID riid, void **ppvObject)
00914     {
00915         IConnectionPointImpl<T, piid, CDV>  *pThis;
00916 
00917         pThis = reinterpret_cast<IConnectionPointImpl<T, piid, CDV>*>(this);
00918 
00919         ATLASSERT(ppvObject != NULL);
00920         if (ppvObject == NULL)
00921             return E_POINTER;
00922 
00923         if (InlineIsEqualGUID(riid, IID_IConnectionPoint) || InlineIsEqualUnknown(riid))
00924         {
00925             *ppvObject = this;
00926             pThis->AddRef();
00927             return S_OK;
00928         }
00929         else
00930         {
00931             *ppvObject = NULL;
00932             return E_NOINTERFACE;
00933         }
00934     }
00935 
00936     STDMETHOD(GetConnectionInterface)(IID *piid2)
00937     {
00938         if (piid2 == NULL)
00939             return E_POINTER;
00940         *piid2 = *piid;
00941         return S_OK;
00942     }
00943 
00944     STDMETHOD(GetConnectionPointContainer)(IConnectionPointContainer **ppCPC)
00945     {
00946         T                                   *pThis;
00947 
00948         pThis = static_cast<T *>(this);
00949         return pThis->QueryInterface(IID_IConnectionPointContainer, reinterpret_cast<void **>(ppCPC));
00950     }
00951 
00952     STDMETHOD(Advise)(IUnknown *pUnkSink, DWORD *pdwCookie)
00953     {
00954         IUnknown                            *adviseTarget;
00955         IID                                 interfaceID;
00956         HRESULT                             hResult;
00957 
00958         if (pdwCookie != NULL)
00959             *pdwCookie = 0;
00960         if (pUnkSink == NULL || pdwCookie == NULL)
00961             return E_POINTER;
00962         GetConnectionInterface(&interfaceID);           // can't fail
00963         hResult = pUnkSink->QueryInterface(interfaceID, reinterpret_cast<void **>(&adviseTarget));
00964         if (SUCCEEDED(hResult))
00965         {
00966             *pdwCookie = m_vec.Add(adviseTarget);
00967             if (*pdwCookie != 0)
00968                 hResult = S_OK;
00969             else
00970             {
00971                 adviseTarget->Release();
00972                 hResult = CONNECT_E_ADVISELIMIT;
00973             }
00974         }
00975         else if (hResult == E_NOINTERFACE)
00976             hResult = CONNECT_E_CANNOTCONNECT;
00977         return hResult;
00978     }
00979 
00980     STDMETHOD(Unadvise)(DWORD dwCookie)
00981     {
00982         IUnknown                            *adviseTarget;
00983         HRESULT                             hResult;
00984 
00985         adviseTarget = m_vec.GetUnknown(dwCookie);
00986         if (m_vec.Remove(dwCookie))
00987         {
00988             if (adviseTarget != NULL)
00989                 adviseTarget->Release();
00990             hResult = S_OK;
00991         }
00992         else
00993             hResult = CONNECT_E_NOCONNECTION;
00994         return hResult;
00995     }
00996 
00997     STDMETHOD(EnumConnections)(IEnumConnections **ppEnum)
00998     {
00999         CComObject<CComEnumConnections>     *newEnumerator;
01000         CONNECTDATA                         *itemBuffer;
01001         CONNECTDATA                         *itemBufferEnd;
01002         IUnknown                            **x;
01003         HRESULT                             hResult;
01004 
01005         ATLASSERT(ppEnum != NULL);
01006         if (ppEnum == NULL)
01007             return E_POINTER;
01008         *ppEnum = NULL;
01009 
01010         ATLTRY(itemBuffer = new CONNECTDATA[m_vec.end() - m_vec.begin()])
01011         if (itemBuffer == NULL)
01012             return E_OUTOFMEMORY;
01013         itemBufferEnd = itemBuffer;
01014         for (x = m_vec.begin(); x < m_vec.end(); x++)
01015         {
01016             if (*x != NULL)
01017             {
01018                 (*x)->AddRef();
01019                 itemBufferEnd->pUnk = *x;
01020                 itemBufferEnd->dwCookie = m_vec.GetCookie(x);
01021                 itemBufferEnd++;
01022             }
01023         }
01024         ATLTRY(newEnumerator = new CComObject<CComEnumConnections>)
01025         if (newEnumerator == NULL)
01026             return E_OUTOFMEMORY;
01027         newEnumerator->Init(itemBuffer, itemBufferEnd, NULL, AtlFlagTakeOwnership);     // can't fail
01028         hResult = newEnumerator->_InternalQueryInterface(IID_IEnumConnections, (void **)ppEnum);
01029         if (FAILED(hResult))
01030             delete newEnumerator;
01031         return hResult;
01032     }
01033 };
01034 
01035 template <class T>
01036 class IConnectionPointContainerImpl : public IConnectionPointContainer
01037 {
01038         typedef const _ATL_CONNMAP_ENTRY * (*handlerFunctionType)(int *);
01039         typedef CComEnum<IEnumConnectionPoints, &IID_IEnumConnectionPoints, IConnectionPoint *, _CopyInterface<IConnectionPoint> >
01040                         CComEnumConnectionPoints;
01041 
01042 public:
01043     STDMETHOD(EnumConnectionPoints)(IEnumConnectionPoints **ppEnum)
01044     {
01045         const _ATL_CONNMAP_ENTRY            *entryPtr;
01046         int                                 connectionPointCount;
01047         IConnectionPoint                    **itemBuffer;
01048         int                                 destIndex;
01049         handlerFunctionType                 handlerFunction;
01050         CComEnumConnectionPoints            *newEnumerator;
01051         HRESULT                             hResult;
01052 
01053         ATLASSERT(ppEnum != NULL);
01054         if (ppEnum == NULL)
01055             return E_POINTER;
01056         *ppEnum = NULL;
01057 
01058         entryPtr = T::GetConnMap(&connectionPointCount);
01059         ATLTRY(itemBuffer = new IConnectionPoint * [connectionPointCount])
01060         if (itemBuffer == NULL)
01061             return E_OUTOFMEMORY;
01062 
01063         destIndex = 0;
01064         while (entryPtr->dwOffset != static_cast<DWORD_PTR>(-1))
01065         {
01066             if (entryPtr->dwOffset == static_cast<DWORD_PTR>(-2))
01067             {
01068                 entryPtr++;
01069                 handlerFunction = reinterpret_cast<handlerFunctionType>(entryPtr->dwOffset);
01070                 entryPtr = handlerFunction(NULL);
01071             }
01072             else
01073             {
01074                 itemBuffer[destIndex++] = reinterpret_cast<IConnectionPoint *>((char *)this + entryPtr->dwOffset);
01075                 entryPtr++;
01076             }
01077         }
01078 
01079         ATLTRY(newEnumerator = new CComObject<CComEnumConnectionPoints>)
01080         if (newEnumerator == NULL)
01081         {
01082             delete [] itemBuffer;
01083             return E_OUTOFMEMORY;
01084         }
01085 
01086         newEnumerator->Init(&itemBuffer[0], &itemBuffer[destIndex], NULL, AtlFlagTakeOwnership);    // can't fail
01087         hResult = newEnumerator->QueryInterface(IID_IEnumConnectionPoints, (void**)ppEnum);
01088         if (FAILED(hResult))
01089             delete newEnumerator;
01090         return hResult;
01091     }
01092 
01093     STDMETHOD(FindConnectionPoint)(REFIID riid, IConnectionPoint **ppCP)
01094     {
01095         IID                                 interfaceID;
01096         const _ATL_CONNMAP_ENTRY            *entryPtr;
01097         handlerFunctionType                 handlerFunction;
01098         IConnectionPoint                    *connectionPoint;
01099         HRESULT                             hResult;
01100 
01101         if (ppCP == NULL)
01102             return E_POINTER;
01103         *ppCP = NULL;
01104         hResult = CONNECT_E_NOCONNECTION;
01105         entryPtr = T::GetConnMap(NULL);
01106         while (entryPtr->dwOffset != static_cast<DWORD_PTR>(-1))
01107         {
01108             if (entryPtr->dwOffset == static_cast<DWORD_PTR>(-2))
01109             {
01110                 entryPtr++;
01111                 handlerFunction = reinterpret_cast<handlerFunctionType>(entryPtr->dwOffset);
01112                 entryPtr = handlerFunction(NULL);
01113             }
01114             else
01115             {
01116                 connectionPoint = reinterpret_cast<IConnectionPoint *>(reinterpret_cast<char *>(this) + entryPtr->dwOffset);
01117                 if (SUCCEEDED(connectionPoint->GetConnectionInterface(&interfaceID)) && InlineIsEqualGUID(riid, interfaceID))
01118                 {
01119                     *ppCP = connectionPoint;
01120                     connectionPoint->AddRef();
01121                     hResult = S_OK;
01122                     break;
01123                 }
01124                 entryPtr++;
01125             }
01126         }
01127         return hResult;
01128     }
01129 };
01130 
01131 #define BEGIN_CONNECTION_POINT_MAP(x)                                           \
01132     typedef x _atl_conn_classtype;                                              \
01133     static const ATL::_ATL_CONNMAP_ENTRY *GetConnMap(int *pnEntries) {          \
01134     static const ATL::_ATL_CONNMAP_ENTRY _entries[] = {
01135 
01136 #define END_CONNECTION_POINT_MAP()                                              \
01137     {(DWORD_PTR)-1} };                                                          \
01138     if (pnEntries)                                                              \
01139         *pnEntries = sizeof(_entries) / sizeof(ATL::_ATL_CONNMAP_ENTRY) - 1;    \
01140     return _entries;}
01141 
01142 #define CONNECTION_POINT_ENTRY(iid)                                             \
01143     {offsetofclass(ATL::_ICPLocator<&iid>, _atl_conn_classtype) -               \
01144     offsetofclass(ATL::IConnectionPointContainerImpl<_atl_conn_classtype>, _atl_conn_classtype)},
01145 
01146 }; // namespace ATL

Generated on Sat May 26 2012 04:34:51 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.