4 * Copyright 2009 Andrew Hill <ash77@reactos.org>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 template <class Base
, const IID
*piid
, class T
, class Copy
, class ThreadModel
= CComObjectThreadModel
>
29 #define DECLARE_CLASSFACTORY_EX(cf) typedef ATL::CComCreator<ATL::CComObjectCached<cf> > _ClassFactoryCreatorClass;
30 #define DECLARE_CLASSFACTORY() DECLARE_CLASSFACTORY_EX(ATL::CComClassFactory)
32 class CComObjectRootBase
50 HRESULT
_AtlFinalConstruct()
55 HRESULT
FinalConstruct()
60 void InternalFinalConstructAddRef()
64 void InternalFinalConstructRelease()
72 static void WINAPI
ObjectMain(bool)
76 static const struct _ATL_CATMAP_ENTRY
*GetCategoryMap()
81 static HRESULT WINAPI
InternalQueryInterface(void *pThis
, const _ATL_INTMAP_ENTRY
*pEntries
, REFIID iid
, void **ppvObject
)
83 return AtlInternalQueryInterface(pThis
, pEntries
, iid
, ppvObject
);
88 template <class ThreadModel
>
89 class CComObjectRootEx
: public CComObjectRootBase
92 typename
ThreadModel::AutoDeleteCriticalSection m_critsec
;
98 ULONG
InternalAddRef()
100 ATLASSERT(m_dwRef
>= 0);
101 return ThreadModel::Increment(&m_dwRef
);
104 ULONG
InternalRelease()
106 ATLASSERT(m_dwRef
> 0);
107 return ThreadModel::Decrement(&m_dwRef
);
120 HRESULT
_AtlInitialConstruct()
122 return m_critsec
.Init();
126 template <class Base
>
127 class CComObject
: public Base
130 CComObject(void * = NULL
)
135 virtual ~CComObject()
137 CComObject
<Base
> *pThis
;
139 pThis
= reinterpret_cast<CComObject
<Base
> *>(this);
140 pThis
->FinalRelease();
141 _pAtlModule
->Unlock();
144 STDMETHOD_(ULONG
, AddRef
)()
146 CComObject
<Base
> *pThis
;
148 pThis
= reinterpret_cast<CComObject
<Base
> *>(this);
149 return pThis
->InternalAddRef();
152 STDMETHOD_(ULONG
, Release
)()
154 CComObject
<Base
> *pThis
;
157 pThis
= reinterpret_cast<CComObject
<Base
> *>(this);
158 l
= pThis
->InternalRelease();
164 STDMETHOD(QueryInterface
)(REFIID iid
, void **ppvObject
)
166 CComObject
<Base
> *pThis
;
168 pThis
= reinterpret_cast<CComObject
<Base
> *>(this);
169 return pThis
->_InternalQueryInterface(iid
, ppvObject
);
172 static HRESULT WINAPI
CreateInstance(CComObject
<Base
> **pp
)
174 CComObject
<Base
> *newInstance
;
177 ATLASSERT(pp
!= NULL
);
181 hResult
= E_OUTOFMEMORY
;
183 ATLTRY(newInstance
= new CComObject
<Base
>())
184 if (newInstance
!= NULL
)
186 newInstance
->SetVoid(NULL
);
187 newInstance
->InternalFinalConstructAddRef();
188 hResult
= newInstance
->_AtlInitialConstruct();
189 if (SUCCEEDED(hResult
))
190 hResult
= newInstance
->FinalConstruct();
191 if (SUCCEEDED(hResult
))
192 hResult
= newInstance
->_AtlFinalConstruct();
193 newInstance
->InternalFinalConstructRelease();
207 template <HRESULT hResult
>
208 class CComFailCreator
211 static HRESULT WINAPI
CreateInstance(void *, REFIID
, LPVOID
*ppv
)
213 ATLASSERT(ppv
!= NULL
);
226 static HRESULT WINAPI
CreateInstance(void *pv
, REFIID riid
, LPVOID
*ppv
)
231 ATLASSERT(ppv
!= NULL
);
236 hResult
= E_OUTOFMEMORY
;
238 ATLTRY(newInstance
= new T1())
239 if (newInstance
!= NULL
)
241 newInstance
->SetVoid(pv
);
242 newInstance
->InternalFinalConstructAddRef();
243 hResult
= newInstance
->_AtlInitialConstruct();
244 if (SUCCEEDED(hResult
))
245 hResult
= newInstance
->FinalConstruct();
246 if (SUCCEEDED(hResult
))
247 hResult
= newInstance
->_AtlFinalConstruct();
248 newInstance
->InternalFinalConstructRelease();
249 if (SUCCEEDED(hResult
))
250 hResult
= newInstance
->QueryInterface(riid
, ppv
);
261 template <class T1
, class T2
>
265 static HRESULT WINAPI
CreateInstance(void *pv
, REFIID riid
, LPVOID
*ppv
)
267 ATLASSERT(ppv
!= NULL
&& ppv
!= NULL
);
270 return T1::CreateInstance(NULL
, riid
, ppv
);
272 return T2::CreateInstance(pv
, riid
, ppv
);
276 template <class Base
>
277 class CComObjectCached
: public Base
280 CComObjectCached(void * = NULL
)
284 STDMETHOD_(ULONG
, AddRef
)()
286 CComObjectCached
<Base
> *pThis
;
289 pThis
= reinterpret_cast<CComObjectCached
<Base
>*>(this);
290 newRefCount
= pThis
->InternalAddRef();
291 if (newRefCount
== 2)
296 STDMETHOD_(ULONG
, Release
)()
298 CComObjectCached
<Base
> *pThis
;
301 pThis
= reinterpret_cast<CComObjectCached
<Base
>*>(this);
302 newRefCount
= pThis
->InternalRelease();
303 if (newRefCount
== 0)
305 else if (newRefCount
== 1)
306 _pAtlModule
->Unlock();
310 STDMETHOD(QueryInterface
)(REFIID iid
, void **ppvObject
)
312 CComObjectCached
<Base
> *pThis
;
314 pThis
= reinterpret_cast<CComObjectCached
<Base
>*>(this);
315 return pThis
->_InternalQueryInterface(iid
, ppvObject
);
319 #define BEGIN_COM_MAP(x) \
321 typedef x _ComMapClass; \
322 HRESULT _InternalQueryInterface(REFIID iid, void **ppvObject) \
324 return this->InternalQueryInterface(this, _GetEntries(), iid, ppvObject); \
326 const static ATL::_ATL_INTMAP_ENTRY *WINAPI _GetEntries() \
328 static const ATL::_ATL_INTMAP_ENTRY _entries[] = {
330 #define END_COM_MAP() \
335 virtual ULONG STDMETHODCALLTYPE AddRef() = 0; \
336 virtual ULONG STDMETHODCALLTYPE Release() = 0; \
337 STDMETHOD(QueryInterface)(REFIID, void **) = 0;
339 #define COM_INTERFACE_ENTRY_IID(iid, x) \
340 {&iid, offsetofclass(x, _ComMapClass), _ATL_SIMPLEMAPENTRY},
342 #define COM_INTERFACE_ENTRY2_IID(iid, x, x2) \
344 reinterpret_cast<DWORD_PTR>(static_cast<x *>(static_cast<x2 *>(reinterpret_cast<_ComMapClass *>(_ATL_PACKING)))) - _ATL_PACKING, \
345 _ATL_SIMPLEMAPENTRY},
347 #define COM_INTERFACE_ENTRY_BREAK(x) \
350 _Break}, // Break is a function that issues int 3.
352 #define COM_INTERFACE_ENTRY_NOINTERFACE(x) \
355 _NoInterface}, // NoInterface returns E_NOINTERFACE.
357 #define COM_INTERFACE_ENTRY_FUNC(iid, dw, func) \
362 #define COM_INTERFACE_ENTRY_FUNC_BLIND(dw, func) \
367 #define COM_INTERFACE_ENTRY_CHAIN(classname) \
369 reinterpret_cast<DWORD>(&_CComChainData<classname, _ComMapClass>::data), \
372 #define DECLARE_NO_REGISTRY()\
373 static HRESULT WINAPI UpdateRegistry(BOOL /*bRegister*/) \
378 #define DECLARE_REGISTRY_RESOURCEID(x) \
379 static HRESULT WINAPI UpdateRegistry(BOOL bRegister) \
381 return ATL::_pAtlModule->UpdateRegistryFromResource(x, bRegister); \
384 #define DECLARE_NOT_AGGREGATABLE(x) \
386 typedef ATL::CComCreator2<ATL::CComCreator<ATL::CComObject<x> >, ATL::CComFailCreator<CLASS_E_NOAGGREGATION> > _CreatorClass;
388 #define DECLARE_AGGREGATABLE(x) \
390 typedef CComCreator2<CComCreator<CComObject<x> >, CComCreator<CComAggObject<x> > > _CreatorClass;
392 #define DECLARE_ONLY_AGGREGATABLE(x) \
394 typedef CComCreator2<CComFailCreator<E_FAIL>, CComCreator<CComAggObject<x> > > _CreatorClass;
396 #define DECLARE_POLY_AGGREGATABLE(x) \
398 typedef CComCreator<CComPolyObject<x> > _CreatorClass;
400 #define DECLARE_GET_CONTROLLING_UNKNOWN() \
402 virtual IUnknown *GetControllingUnknown() \
404 return GetUnknown(); \
407 #define DECLARE_PROTECT_FINAL_CONSTRUCT() \
408 void InternalFinalConstructAddRef() \
412 void InternalFinalConstructRelease() \
417 #define BEGIN_OBJECT_MAP(x) static ATL::_ATL_OBJMAP_ENTRY x[] = {
419 #define END_OBJECT_MAP() {NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL}};
421 #define OBJECT_ENTRY(clsid, class) \
424 class::UpdateRegistry, \
425 class::_ClassFactoryCreatorClass::CreateInstance, \
426 class::_CreatorClass::CreateInstance, \
429 class::GetObjectDescription, \
430 class::GetCategoryMap, \
433 class CComClassFactory
:
434 public IClassFactory
,
435 public CComObjectRootEx
<CComGlobalsThreadModel
>
438 _ATL_CREATORFUNC
*m_pfnCreateInstance
;
440 STDMETHOD(CreateInstance
)(LPUNKNOWN pUnkOuter
, REFIID riid
, void **ppvObj
)
444 ATLASSERT(m_pfnCreateInstance
!= NULL
);
450 if (pUnkOuter
!= NULL
&& InlineIsEqualUnknown(riid
) == FALSE
)
451 hResult
= CLASS_E_NOAGGREGATION
;
453 hResult
= m_pfnCreateInstance(pUnkOuter
, riid
, ppvObj
);
457 STDMETHOD(LockServer
)(BOOL fLock
)
462 _pAtlModule
->Unlock();
466 void SetVoid(void *pv
)
468 m_pfnCreateInstance
= (_ATL_CREATORFUNC
*)pv
;
471 BEGIN_COM_MAP(CComClassFactory
)
472 COM_INTERFACE_ENTRY_IID(IID_IClassFactory
, IClassFactory
)
476 template <class T
, const CLSID
*pclsid
= &CLSID_NULL
>
480 DECLARE_CLASSFACTORY()
482 static LPCTSTR WINAPI
GetObjectDescription()
492 static HRESULT
copy(T
*pTo
, const T
*pFrom
)
494 memcpy(pTo
, pFrom
, sizeof(T
));
498 static void init(T
*)
502 static void destroy(T
*)
508 class _Copy
<CONNECTDATA
>
511 static HRESULT
copy(CONNECTDATA
*pTo
, const CONNECTDATA
*pFrom
)
519 static void init(CONNECTDATA
*)
523 static void destroy(CONNECTDATA
*p
)
534 static HRESULT
copy(T
**pTo
, T
**pFrom
)
542 static void init(T
**)
546 static void destroy(T
**p
)
556 AtlFlagTakeOwnership
= 2, // BitOwn
557 AtlFlagCopy
= 3 // BitOwn | BitCopy
560 template <class Base
, const IID
*piid
, class T
, class Copy
>
561 class CComEnumImpl
: public Base
564 typedef CComObject
<CComEnum
<Base
, piid
, T
, Copy
> > enumeratorClass
;
566 CComPtr
<IUnknown
> m_spUnk
;
580 virtual ~CComEnumImpl()
584 if ((m_dwFlags
& BitOwn
) != 0)
586 for (x
= m_begin
; x
!= m_end
; x
++)
592 HRESULT
Init(T
*begin
, T
*end
, IUnknown
*pUnk
, CComEnumFlags flags
= AtlFlagNoCopy
)
600 if (flags
== AtlFlagCopy
)
602 ATLTRY(newBuffer
= new T
[end
- begin
])
603 if (newBuffer
== NULL
)
604 return E_OUTOFMEMORY
;
606 for (sourcePtr
= begin
; sourcePtr
!= end
; sourcePtr
++)
609 hResult
= Copy::copy(destPtr
, sourcePtr
);
612 cleanupPtr
= m_begin
;
613 while (cleanupPtr
< destPtr
)
614 Copy::destroy(cleanupPtr
++);
621 m_end
= m_begin
+ (end
- begin
);
634 STDMETHOD(Next
)(ULONG celt
, T
*rgelt
, ULONG
*pceltFetched
)
641 if (pceltFetched
!= NULL
)
645 if (rgelt
== NULL
|| (celt
!= 1 && pceltFetched
== NULL
))
647 if (m_begin
== NULL
|| m_end
== NULL
|| m_iter
== NULL
)
650 numAvailable
= static_cast<ULONG
>(m_end
- m_iter
);
651 if (celt
< numAvailable
)
654 numToFetch
= numAvailable
;
655 if (pceltFetched
!= NULL
)
656 *pceltFetched
= numToFetch
;
658 while (numToFetch
!= 0)
660 hResult
= Copy::copy(rgeltTemp
, m_iter
);
663 while (rgelt
< rgeltTemp
)
664 Copy::destroy(rgelt
++);
665 if (pceltFetched
!= NULL
)
673 if (numAvailable
< celt
)
678 STDMETHOD(Skip
)(ULONG celt
)
686 numAvailable
= static_cast<ULONG
>(m_end
- m_iter
);
687 if (celt
< numAvailable
)
690 numToSkip
= numAvailable
;
692 if (numAvailable
< celt
)
703 STDMETHOD(Clone
)(Base
**ppEnum
)
705 enumeratorClass
*newInstance
;
712 hResult
= enumeratorClass::CreateInstance(&newInstance
);
713 if (SUCCEEDED(hResult
))
715 hResult
= newInstance
->Init(m_begin
, m_end
, (m_dwFlags
& BitOwn
) ? this : m_spUnk
);
716 if (SUCCEEDED(hResult
))
718 newInstance
->m_iter
= m_iter
;
719 hResult
= newInstance
->_InternalQueryInterface(*piid
, (void **)ppEnum
);
736 template <class Base
, const IID
*piid
, class T
, class Copy
, class ThreadModel
>
738 public CComEnumImpl
<Base
, piid
, T
, Copy
>,
739 public CComObjectRootEx
<ThreadModel
>
742 typedef CComEnum
<Base
, piid
, T
, Copy
> _CComEnum
;
743 typedef CComEnumImpl
<Base
, piid
, T
, Copy
> _CComEnumBase
;
745 BEGIN_COM_MAP(_CComEnum
)
746 COM_INTERFACE_ENTRY_IID(*piid
, _CComEnumBase
)
750 #ifndef _DEFAULT_VECTORLENGTH
751 #define _DEFAULT_VECTORLENGTH 4
754 class CComDynamicUnkArray
760 CComDynamicUnkArray()
766 ~CComDynamicUnkArray()
778 return &m_ppUnk
[m_nSize
];
781 IUnknown
*GetAt(int nIndex
)
783 ATLASSERT(nIndex
>= 0 && nIndex
< m_nSize
);
784 if (nIndex
>= 0 && nIndex
< m_nSize
)
785 return m_ppUnk
[nIndex
];
790 IUnknown
*WINAPI
GetUnknown(DWORD dwCookie
)
792 ATLASSERT(dwCookie
!= 0 && dwCookie
<= static_cast<DWORD
>(m_nSize
));
793 if (dwCookie
!= 0 && dwCookie
<= static_cast<DWORD
>(m_nSize
))
794 return GetAt(dwCookie
- 1);
799 DWORD WINAPI
GetCookie(IUnknown
**ppFind
)
804 ATLASSERT(ppFind
!= NULL
&& *ppFind
!= NULL
);
805 if (ppFind
!= NULL
&& *ppFind
!= NULL
)
808 for (x
= begin(); x
< end(); x
++)
818 DWORD
Add(IUnknown
*pUnk
)
825 ATLASSERT(pUnk
!= NULL
);
828 newSize
= _DEFAULT_VECTORLENGTH
* sizeof(IUnknown
*);
829 ATLTRY(newArray
= reinterpret_cast<IUnknown
**>(malloc(newSize
)));
830 if (newArray
== NULL
)
832 memset(newArray
, 0, newSize
);
834 m_nSize
= _DEFAULT_VECTORLENGTH
;
837 for (x
= begin(); x
< end(); x
++)
846 newSize
= m_nSize
* 2;
847 newArray
= reinterpret_cast<IUnknown
**>(realloc(m_ppUnk
, newSize
* sizeof(IUnknown
*)));
848 if (newArray
== NULL
)
851 memset(&m_ppUnk
[m_nSize
], 0, (newSize
- m_nSize
) * sizeof(IUnknown
*));
852 curCookie
= m_nSize
+ 1;
854 m_ppUnk
[curCookie
- 1] = pUnk
;
858 BOOL
Remove(DWORD dwCookie
)
862 index
= dwCookie
- 1;
863 ATLASSERT(index
< dwCookie
&& index
< static_cast<DWORD
>(m_nSize
));
864 if (index
< dwCookie
&& index
< static_cast<DWORD
>(m_nSize
) && m_ppUnk
[index
] != NULL
)
866 m_ppUnk
[index
] = NULL
;
873 CComDynamicUnkArray
&operator = (const CComDynamicUnkArray
&)
878 CComDynamicUnkArray(const CComDynamicUnkArray
&)
883 struct _ATL_CONNMAP_ENTRY
888 template <const IID
*piid
>
892 STDMETHOD(_LocCPQueryInterface
)(REFIID riid
, void **ppvObject
) = 0;
893 virtual ULONG STDMETHODCALLTYPE
AddRef() = 0;
894 virtual ULONG STDMETHODCALLTYPE
Release() = 0;
897 template<class T
, const IID
*piid
, class CDV
= CComDynamicUnkArray
>
898 class IConnectionPointImpl
: public _ICPLocator
<piid
>
900 typedef CComEnum
<IEnumConnections
, &IID_IEnumConnections
, CONNECTDATA
, _Copy
<CONNECTDATA
> > CComEnumConnections
;
904 ~IConnectionPointImpl()
908 for (x
= m_vec
.begin(); x
< m_vec
.end(); x
++)
913 STDMETHOD(_LocCPQueryInterface
)(REFIID riid
, void **ppvObject
)
915 IConnectionPointImpl
<T
, piid
, CDV
> *pThis
;
917 pThis
= reinterpret_cast<IConnectionPointImpl
<T
, piid
, CDV
>*>(this);
919 ATLASSERT(ppvObject
!= NULL
);
920 if (ppvObject
== NULL
)
923 if (InlineIsEqualGUID(riid
, IID_IConnectionPoint
) || InlineIsEqualUnknown(riid
))
932 return E_NOINTERFACE
;
936 STDMETHOD(GetConnectionInterface
)(IID
*piid2
)
944 STDMETHOD(GetConnectionPointContainer
)(IConnectionPointContainer
**ppCPC
)
948 pThis
= static_cast<T
*>(this);
949 return pThis
->QueryInterface(IID_IConnectionPointContainer
, reinterpret_cast<void **>(ppCPC
));
952 STDMETHOD(Advise
)(IUnknown
*pUnkSink
, DWORD
*pdwCookie
)
954 IUnknown
*adviseTarget
;
958 if (pdwCookie
!= NULL
)
960 if (pUnkSink
== NULL
|| pdwCookie
== NULL
)
962 GetConnectionInterface(&interfaceID
); // can't fail
963 hResult
= pUnkSink
->QueryInterface(interfaceID
, reinterpret_cast<void **>(&adviseTarget
));
964 if (SUCCEEDED(hResult
))
966 *pdwCookie
= m_vec
.Add(adviseTarget
);
971 adviseTarget
->Release();
972 hResult
= CONNECT_E_ADVISELIMIT
;
975 else if (hResult
== E_NOINTERFACE
)
976 hResult
= CONNECT_E_CANNOTCONNECT
;
980 STDMETHOD(Unadvise
)(DWORD dwCookie
)
982 IUnknown
*adviseTarget
;
985 adviseTarget
= m_vec
.GetUnknown(dwCookie
);
986 if (m_vec
.Remove(dwCookie
))
988 if (adviseTarget
!= NULL
)
989 adviseTarget
->Release();
993 hResult
= CONNECT_E_NOCONNECTION
;
997 STDMETHOD(EnumConnections
)(IEnumConnections
**ppEnum
)
999 CComObject
<CComEnumConnections
> *newEnumerator
;
1000 CONNECTDATA
*itemBuffer
;
1001 CONNECTDATA
*itemBufferEnd
;
1005 ATLASSERT(ppEnum
!= NULL
);
1010 ATLTRY(itemBuffer
= new CONNECTDATA
[m_vec
.end() - m_vec
.begin()])
1011 if (itemBuffer
== NULL
)
1012 return E_OUTOFMEMORY
;
1013 itemBufferEnd
= itemBuffer
;
1014 for (x
= m_vec
.begin(); x
< m_vec
.end(); x
++)
1019 itemBufferEnd
->pUnk
= *x
;
1020 itemBufferEnd
->dwCookie
= m_vec
.GetCookie(x
);
1024 ATLTRY(newEnumerator
= new CComObject
<CComEnumConnections
>)
1025 if (newEnumerator
== NULL
)
1026 return E_OUTOFMEMORY
;
1027 newEnumerator
->Init(itemBuffer
, itemBufferEnd
, NULL
, AtlFlagTakeOwnership
); // can't fail
1028 hResult
= newEnumerator
->_InternalQueryInterface(IID_IEnumConnections
, (void **)ppEnum
);
1029 if (FAILED(hResult
))
1030 delete newEnumerator
;
1036 class IConnectionPointContainerImpl
: public IConnectionPointContainer
1038 typedef const _ATL_CONNMAP_ENTRY
* (*handlerFunctionType
)(int *);
1039 typedef CComEnum
<IEnumConnectionPoints
, &IID_IEnumConnectionPoints
, IConnectionPoint
*, _CopyInterface
<IConnectionPoint
> >
1040 CComEnumConnectionPoints
;
1043 STDMETHOD(EnumConnectionPoints
)(IEnumConnectionPoints
**ppEnum
)
1045 const _ATL_CONNMAP_ENTRY
*entryPtr
;
1046 int connectionPointCount
;
1047 IConnectionPoint
**itemBuffer
;
1049 handlerFunctionType handlerFunction
;
1050 CComEnumConnectionPoints
*newEnumerator
;
1053 ATLASSERT(ppEnum
!= NULL
);
1058 entryPtr
= T::GetConnMap(&connectionPointCount
);
1059 ATLTRY(itemBuffer
= new IConnectionPoint
* [connectionPointCount
])
1060 if (itemBuffer
== NULL
)
1061 return E_OUTOFMEMORY
;
1064 while (entryPtr
->dwOffset
!= static_cast<DWORD_PTR
>(-1))
1066 if (entryPtr
->dwOffset
== static_cast<DWORD_PTR
>(-2))
1069 handlerFunction
= reinterpret_cast<handlerFunctionType
>(entryPtr
->dwOffset
);
1070 entryPtr
= handlerFunction(NULL
);
1074 itemBuffer
[destIndex
++] = reinterpret_cast<IConnectionPoint
*>((char *)this + entryPtr
->dwOffset
);
1079 ATLTRY(newEnumerator
= new CComObject
<CComEnumConnectionPoints
>)
1080 if (newEnumerator
== NULL
)
1082 delete [] itemBuffer
;
1083 return E_OUTOFMEMORY
;
1086 newEnumerator
->Init(&itemBuffer
[0], &itemBuffer
[destIndex
], NULL
, AtlFlagTakeOwnership
); // can't fail
1087 hResult
= newEnumerator
->QueryInterface(IID_IEnumConnectionPoints
, (void**)ppEnum
);
1088 if (FAILED(hResult
))
1089 delete newEnumerator
;
1093 STDMETHOD(FindConnectionPoint
)(REFIID riid
, IConnectionPoint
**ppCP
)
1096 const _ATL_CONNMAP_ENTRY
*entryPtr
;
1097 handlerFunctionType handlerFunction
;
1098 IConnectionPoint
*connectionPoint
;
1104 hResult
= CONNECT_E_NOCONNECTION
;
1105 entryPtr
= T::GetConnMap(NULL
);
1106 while (entryPtr
->dwOffset
!= static_cast<DWORD_PTR
>(-1))
1108 if (entryPtr
->dwOffset
== static_cast<DWORD_PTR
>(-2))
1111 handlerFunction
= reinterpret_cast<handlerFunctionType
>(entryPtr
->dwOffset
);
1112 entryPtr
= handlerFunction(NULL
);
1116 connectionPoint
= reinterpret_cast<IConnectionPoint
*>(reinterpret_cast<char *>(this) + entryPtr
->dwOffset
);
1117 if (SUCCEEDED(connectionPoint
->GetConnectionInterface(&interfaceID
)) && InlineIsEqualGUID(riid
, interfaceID
))
1119 *ppCP
= connectionPoint
;
1120 connectionPoint
->AddRef();
1131 #define BEGIN_CONNECTION_POINT_MAP(x) \
1132 typedef x _atl_conn_classtype; \
1133 static const ATL::_ATL_CONNMAP_ENTRY *GetConnMap(int *pnEntries) { \
1134 static const ATL::_ATL_CONNMAP_ENTRY _entries[] = {
1136 #define END_CONNECTION_POINT_MAP() \
1137 {(DWORD_PTR)-1} }; \
1139 *pnEntries = sizeof(_entries) / sizeof(ATL::_ATL_CONNMAP_ENTRY) - 1; \
1142 #define CONNECTION_POINT_ENTRY(iid) \
1143 {offsetofclass(ATL::_ICPLocator<&iid>, _atl_conn_classtype) - \
1144 offsetofclass(ATL::IConnectionPointContainerImpl<_atl_conn_classtype>, _atl_conn_classtype)},