4 * Copyright 2009 Andrew Hill <ash77@reactos.org>
5 * Copyright 2013 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27 template <class Base
, const IID
*piid
, class T
, class Copy
, class ThreadModel
= CComObjectThreadModel
>
30 #define DECLARE_CLASSFACTORY_EX(cf) typedef ATL::CComCreator<ATL::CComObjectCached<cf> > _ClassFactoryCreatorClass;
31 #define DECLARE_CLASSFACTORY() DECLARE_CLASSFACTORY_EX(ATL::CComClassFactory)
33 class CComObjectRootBase
51 HRESULT
_AtlFinalConstruct()
56 HRESULT
FinalConstruct()
61 void InternalFinalConstructAddRef()
65 void InternalFinalConstructRelease()
73 static void WINAPI
ObjectMain(bool)
77 static const struct _ATL_CATMAP_ENTRY
*GetCategoryMap()
82 static HRESULT WINAPI
InternalQueryInterface(void *pThis
, const _ATL_INTMAP_ENTRY
*pEntries
, REFIID iid
, void **ppvObject
)
84 return AtlInternalQueryInterface(pThis
, pEntries
, iid
, ppvObject
);
89 template <class ThreadModel
>
90 class CComObjectRootEx
: public CComObjectRootBase
93 typename
ThreadModel::AutoDeleteCriticalSection m_critsec
;
99 ULONG
InternalAddRef()
101 ATLASSERT(m_dwRef
>= 0);
102 return ThreadModel::Increment(&m_dwRef
);
105 ULONG
InternalRelease()
107 ATLASSERT(m_dwRef
> 0);
108 return ThreadModel::Decrement(&m_dwRef
);
121 HRESULT
_AtlInitialConstruct()
123 return m_critsec
.Init();
127 template <class Base
>
128 class CComObject
: public Base
131 CComObject(void * = NULL
)
136 virtual ~CComObject()
138 this->FinalRelease();
139 _pAtlModule
->Unlock();
142 STDMETHOD_(ULONG
, AddRef
)()
144 return this->InternalAddRef();
147 STDMETHOD_(ULONG
, Release
)()
151 newRefCount
= this->InternalRelease();
152 if (newRefCount
== 0)
157 STDMETHOD(QueryInterface
)(REFIID iid
, void **ppvObject
)
159 return this->_InternalQueryInterface(iid
, ppvObject
);
162 static HRESULT WINAPI
CreateInstance(CComObject
<Base
> **pp
)
164 CComObject
<Base
> *newInstance
;
167 ATLASSERT(pp
!= NULL
);
171 hResult
= E_OUTOFMEMORY
;
173 ATLTRY(newInstance
= new CComObject
<Base
>())
174 if (newInstance
!= NULL
)
176 newInstance
->SetVoid(NULL
);
177 newInstance
->InternalFinalConstructAddRef();
178 hResult
= newInstance
->_AtlInitialConstruct();
179 if (SUCCEEDED(hResult
))
180 hResult
= newInstance
->FinalConstruct();
181 if (SUCCEEDED(hResult
))
182 hResult
= newInstance
->_AtlFinalConstruct();
183 newInstance
->InternalFinalConstructRelease();
197 template <class Base
>
198 class CComContainedObject
: public Base
201 IUnknown
* m_pUnkOuter
;
202 CComContainedObject(void * pv
= NULL
) : m_pUnkOuter(static_cast<IUnknown
*>(pv
))
206 STDMETHOD_(ULONG
, AddRef
)()
208 return m_pUnkOuter
->AddRef();
211 STDMETHOD_(ULONG
, Release
)()
213 return m_pUnkOuter
->Release();
216 STDMETHOD(QueryInterface
)(REFIID iid
, void **ppvObject
)
218 return m_pUnkOuter
->QueryInterface(iid
, ppvObject
);
221 IUnknown
* GetControllingUnknown()
227 template <class contained
>
228 class CComAggObject
: public contained
231 CComContainedObject
<contained
> m_contained
;
233 CComAggObject(void * pv
= NULL
) : m_contained(static_cast<contained
*>(pv
))
238 virtual ~CComAggObject()
240 this->FinalRelease();
241 _pAtlModule
->Unlock();
244 HRESULT
FinalConstruct()
246 return m_contained
.FinalConstruct();
250 m_contained
.FinalRelease();
253 STDMETHOD_(ULONG
, AddRef
)()
255 return this->InternalAddRef();
258 STDMETHOD_(ULONG
, Release
)()
261 newRefCount
= this->InternalRelease();
262 if (newRefCount
== 0)
267 STDMETHOD(QueryInterface
)(REFIID iid
, void **ppvObject
)
269 if (ppvObject
== NULL
)
271 if (iid
== IID_IUnknown
)
272 *ppvObject
= reinterpret_cast<void*>(this);
274 return m_contained
._InternalQueryInterface(iid
, ppvObject
);
278 static HRESULT WINAPI
CreateInstance(IUnknown
* punkOuter
, CComAggObject
<contained
> **pp
)
280 CComAggObject
<contained
> *newInstance
;
283 ATLASSERT(pp
!= NULL
);
287 hResult
= E_OUTOFMEMORY
;
289 ATLTRY(newInstance
= new CComAggObject
<contained
>(punkOuter
))
290 if (newInstance
!= NULL
)
292 newInstance
->SetVoid(NULL
);
293 newInstance
->InternalFinalConstructAddRef();
294 hResult
= newInstance
->_AtlInitialConstruct();
295 if (SUCCEEDED(hResult
))
296 hResult
= newInstance
->FinalConstruct();
297 if (SUCCEEDED(hResult
))
298 hResult
= newInstance
->_AtlFinalConstruct();
299 newInstance
->InternalFinalConstructRelease();
311 template <class contained
>
312 class CComPolyObject
: public contained
315 CComContainedObject
<contained
> m_contained
;
317 CComPolyObject(void * pv
= NULL
)
318 : m_contained(pv
? static_cast<contained
*>(pv
) : this)
323 virtual ~CComPolyObject()
325 this->FinalRelease();
326 _pAtlModule
->Unlock();
329 HRESULT
FinalConstruct()
331 return m_contained
.FinalConstruct();
335 m_contained
.FinalRelease();
338 STDMETHOD_(ULONG
, AddRef
)()
340 return this->InternalAddRef();
343 STDMETHOD_(ULONG
, Release
)()
346 newRefCount
= this->InternalRelease();
347 if (newRefCount
== 0)
352 STDMETHOD(QueryInterface
)(REFIID iid
, void **ppvObject
)
354 if (ppvObject
== NULL
)
356 if (iid
== IID_IUnknown
)
357 *ppvObject
= reinterpret_cast<void*>(this);
359 return m_contained
._InternalQueryInterface(iid
, ppvObject
);
363 static HRESULT WINAPI
CreateInstance(IUnknown
* punkOuter
, CComPolyObject
<contained
> **pp
)
365 CComPolyObject
<contained
> *newInstance
;
368 ATLASSERT(pp
!= NULL
);
372 hResult
= E_OUTOFMEMORY
;
374 ATLTRY(newInstance
= new CComPolyObject
<contained
>(punkOuter
))
375 if (newInstance
!= NULL
)
377 newInstance
->SetVoid(NULL
);
378 newInstance
->InternalFinalConstructAddRef();
379 hResult
= newInstance
->_AtlInitialConstruct();
380 if (SUCCEEDED(hResult
))
381 hResult
= newInstance
->FinalConstruct();
382 if (SUCCEEDED(hResult
))
383 hResult
= newInstance
->_AtlFinalConstruct();
384 newInstance
->InternalFinalConstructRelease();
396 template <HRESULT hResult
>
397 class CComFailCreator
400 static HRESULT WINAPI
CreateInstance(void *, REFIID
, LPVOID
*ppv
)
402 ATLASSERT(ppv
!= NULL
);
415 static HRESULT WINAPI
CreateInstance(void *pv
, REFIID riid
, LPVOID
*ppv
)
420 ATLASSERT(ppv
!= NULL
);
425 hResult
= E_OUTOFMEMORY
;
427 ATLTRY(newInstance
= new T1(pv
))
428 if (newInstance
!= NULL
)
430 newInstance
->SetVoid(pv
);
431 newInstance
->InternalFinalConstructAddRef();
432 hResult
= newInstance
->_AtlInitialConstruct();
433 if (SUCCEEDED(hResult
))
434 hResult
= newInstance
->FinalConstruct();
435 if (SUCCEEDED(hResult
))
436 hResult
= newInstance
->_AtlFinalConstruct();
437 newInstance
->InternalFinalConstructRelease();
438 if (SUCCEEDED(hResult
))
439 hResult
= newInstance
->QueryInterface(riid
, ppv
);
450 template <class T1
, class T2
>
454 static HRESULT WINAPI
CreateInstance(void *pv
, REFIID riid
, LPVOID
*ppv
)
456 ATLASSERT(ppv
!= NULL
&& riid
!= NULL
);
459 return T1::CreateInstance(NULL
, riid
, ppv
);
461 return T2::CreateInstance(pv
, riid
, ppv
);
465 template <class Base
>
466 class CComObjectCached
: public Base
469 CComObjectCached(void * = NULL
)
473 STDMETHOD_(ULONG
, AddRef
)()
477 newRefCount
= this->InternalAddRef();
478 if (newRefCount
== 2)
483 STDMETHOD_(ULONG
, Release
)()
487 newRefCount
= this->InternalRelease();
488 if (newRefCount
== 0)
490 else if (newRefCount
== 1)
491 _pAtlModule
->Unlock();
495 STDMETHOD(QueryInterface
)(REFIID iid
, void **ppvObject
)
497 return this->_InternalQueryInterface(iid
, ppvObject
);
501 #define BEGIN_COM_MAP(x) \
503 typedef x _ComMapClass; \
504 HRESULT _InternalQueryInterface(REFIID iid, void **ppvObject) \
506 return this->InternalQueryInterface(this, _GetEntries(), iid, ppvObject); \
508 const static ATL::_ATL_INTMAP_ENTRY *WINAPI _GetEntries() \
510 static const ATL::_ATL_INTMAP_ENTRY _entries[] = {
512 #define END_COM_MAP() \
517 virtual ULONG STDMETHODCALLTYPE AddRef() = 0; \
518 virtual ULONG STDMETHODCALLTYPE Release() = 0; \
519 STDMETHOD(QueryInterface)(REFIID, void **) = 0;
521 #define COM_INTERFACE_ENTRY_IID(iid, x) \
522 {&iid, offsetofclass(x, _ComMapClass), _ATL_SIMPLEMAPENTRY},
524 #define COM_INTERFACE_ENTRY(x) \
526 offsetofclass(x, _ComMapClass), \
527 _ATL_SIMPLEMAPENTRY},
529 #define COM_INTERFACE_ENTRY2_IID(iid, x, x2) \
531 reinterpret_cast<DWORD_PTR>(static_cast<x *>(static_cast<x2 *>(reinterpret_cast<_ComMapClass *>(_ATL_PACKING)))) - _ATL_PACKING, \
532 _ATL_SIMPLEMAPENTRY},
534 #define COM_INTERFACE_ENTRY_BREAK(x) \
537 _Break}, // Break is a function that issues int 3.
539 #define COM_INTERFACE_ENTRY_NOINTERFACE(x) \
542 _NoInterface}, // NoInterface returns E_NOINTERFACE.
544 #define COM_INTERFACE_ENTRY_FUNC(iid, dw, func) \
549 #define COM_INTERFACE_ENTRY_FUNC_BLIND(dw, func) \
554 #define COM_INTERFACE_ENTRY_CHAIN(classname) \
556 reinterpret_cast<DWORD>(&_CComChainData<classname, _ComMapClass>::data), \
559 #define DECLARE_NO_REGISTRY()\
560 static HRESULT WINAPI UpdateRegistry(BOOL /*bRegister*/) \
565 #define DECLARE_REGISTRY_RESOURCEID(x) \
566 static HRESULT WINAPI UpdateRegistry(BOOL bRegister) \
568 return ATL::_pAtlModule->UpdateRegistryFromResource(x, bRegister); \
571 #define DECLARE_NOT_AGGREGATABLE(x) \
573 typedef ATL::CComCreator2<ATL::CComCreator<ATL::CComObject<x> >, ATL::CComFailCreator<CLASS_E_NOAGGREGATION> > _CreatorClass;
575 #define DECLARE_AGGREGATABLE(x) \
577 typedef ATL::CComCreator2<ATL::CComCreator<ATL::CComObject<x> >, ATL::CComCreator<ATL::CComAggObject<x> > > _CreatorClass;
579 #define DECLARE_ONLY_AGGREGATABLE(x) \
581 typedef ATL::CComCreator2<ATL::CComFailCreator<E_FAIL>, ATL::CComCreator<ATL::CComAggObject<x> > > _CreatorClass;
583 #define DECLARE_POLY_AGGREGATABLE(x) \
585 typedef ATL::CComCreator<ATL::CComPolyObject<x> > _CreatorClass;
587 #define COM_INTERFACE_ENTRY_AGGREGATE(iid, punk) \
589 (DWORD_PTR)offsetof(_ComMapClass, punk), \
592 #define DECLARE_GET_CONTROLLING_UNKNOWN() \
594 virtual IUnknown *GetControllingUnknown() \
596 return GetUnknown(); \
599 #define DECLARE_PROTECT_FINAL_CONSTRUCT() \
600 void InternalFinalConstructAddRef() \
604 void InternalFinalConstructRelease() \
609 #define BEGIN_OBJECT_MAP(x) static ATL::_ATL_OBJMAP_ENTRY x[] = {
611 #define END_OBJECT_MAP() {NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL}};
613 #define OBJECT_ENTRY(clsid, class) \
616 class::UpdateRegistry, \
617 class::_ClassFactoryCreatorClass::CreateInstance, \
618 class::_CreatorClass::CreateInstance, \
621 class::GetObjectDescription, \
622 class::GetCategoryMap, \
625 class CComClassFactory
:
626 public IClassFactory
,
627 public CComObjectRootEx
<CComGlobalsThreadModel
>
630 _ATL_CREATORFUNC
*m_pfnCreateInstance
;
632 virtual ~CComClassFactory()
637 STDMETHOD(CreateInstance
)(LPUNKNOWN pUnkOuter
, REFIID riid
, void **ppvObj
)
641 ATLASSERT(m_pfnCreateInstance
!= NULL
);
647 if (pUnkOuter
!= NULL
&& InlineIsEqualUnknown(riid
) == FALSE
)
648 hResult
= CLASS_E_NOAGGREGATION
;
650 hResult
= m_pfnCreateInstance(pUnkOuter
, riid
, ppvObj
);
654 STDMETHOD(LockServer
)(BOOL fLock
)
659 _pAtlModule
->Unlock();
663 void SetVoid(void *pv
)
665 m_pfnCreateInstance
= (_ATL_CREATORFUNC
*)pv
;
668 BEGIN_COM_MAP(CComClassFactory
)
669 COM_INTERFACE_ENTRY_IID(IID_IClassFactory
, IClassFactory
)
673 template <class T
, const CLSID
*pclsid
= &CLSID_NULL
>
677 DECLARE_CLASSFACTORY()
679 static LPCTSTR WINAPI
GetObjectDescription()
689 static HRESULT
copy(T
*pTo
, const T
*pFrom
)
691 memcpy(pTo
, pFrom
, sizeof(T
));
695 static void init(T
*)
699 static void destroy(T
*)
705 class _Copy
<CONNECTDATA
>
708 static HRESULT
copy(CONNECTDATA
*pTo
, const CONNECTDATA
*pFrom
)
716 static void init(CONNECTDATA
*)
720 static void destroy(CONNECTDATA
*p
)
731 static HRESULT
copy(T
**pTo
, T
**pFrom
)
739 static void init(T
**)
743 static void destroy(T
**p
)
753 AtlFlagTakeOwnership
= 2, // BitOwn
754 AtlFlagCopy
= 3 // BitOwn | BitCopy
757 template <class Base
, const IID
*piid
, class T
, class Copy
>
758 class CComEnumImpl
: public Base
761 typedef CComObject
<CComEnum
<Base
, piid
, T
, Copy
> > enumeratorClass
;
763 CComPtr
<IUnknown
> m_spUnk
;
777 virtual ~CComEnumImpl()
781 if ((m_dwFlags
& BitOwn
) != 0)
783 for (x
= m_begin
; x
!= m_end
; x
++)
789 HRESULT
Init(T
*begin
, T
*end
, IUnknown
*pUnk
, CComEnumFlags flags
= AtlFlagNoCopy
)
797 if (flags
== AtlFlagCopy
)
799 ATLTRY(newBuffer
= new T
[end
- begin
])
800 if (newBuffer
== NULL
)
801 return E_OUTOFMEMORY
;
803 for (sourcePtr
= begin
; sourcePtr
!= end
; sourcePtr
++)
806 hResult
= Copy::copy(destPtr
, sourcePtr
);
809 cleanupPtr
= m_begin
;
810 while (cleanupPtr
< destPtr
)
811 Copy::destroy(cleanupPtr
++);
818 m_end
= m_begin
+ (end
- begin
);
831 STDMETHOD(Next
)(ULONG celt
, T
*rgelt
, ULONG
*pceltFetched
)
838 if (pceltFetched
!= NULL
)
842 if (rgelt
== NULL
|| (celt
!= 1 && pceltFetched
== NULL
))
844 if (m_begin
== NULL
|| m_end
== NULL
|| m_iter
== NULL
)
847 numAvailable
= static_cast<ULONG
>(m_end
- m_iter
);
848 if (celt
< numAvailable
)
851 numToFetch
= numAvailable
;
852 if (pceltFetched
!= NULL
)
853 *pceltFetched
= numToFetch
;
855 while (numToFetch
!= 0)
857 hResult
= Copy::copy(rgeltTemp
, m_iter
);
860 while (rgelt
< rgeltTemp
)
861 Copy::destroy(rgelt
++);
862 if (pceltFetched
!= NULL
)
870 if (numAvailable
< celt
)
875 STDMETHOD(Skip
)(ULONG celt
)
883 numAvailable
= static_cast<ULONG
>(m_end
- m_iter
);
884 if (celt
< numAvailable
)
887 numToSkip
= numAvailable
;
889 if (numAvailable
< celt
)
900 STDMETHOD(Clone
)(Base
**ppEnum
)
902 enumeratorClass
*newInstance
;
909 hResult
= enumeratorClass::CreateInstance(&newInstance
);
910 if (SUCCEEDED(hResult
))
912 hResult
= newInstance
->Init(m_begin
, m_end
, (m_dwFlags
& BitOwn
) ? this : m_spUnk
);
913 if (SUCCEEDED(hResult
))
915 newInstance
->m_iter
= m_iter
;
916 hResult
= newInstance
->_InternalQueryInterface(*piid
, (void **)ppEnum
);
933 template <class Base
, const IID
*piid
, class T
, class Copy
, class ThreadModel
>
935 public CComEnumImpl
<Base
, piid
, T
, Copy
>,
936 public CComObjectRootEx
<ThreadModel
>
939 typedef CComEnum
<Base
, piid
, T
, Copy
> _CComEnum
;
940 typedef CComEnumImpl
<Base
, piid
, T
, Copy
> _CComEnumBase
;
942 BEGIN_COM_MAP(_CComEnum
)
943 COM_INTERFACE_ENTRY_IID(*piid
, _CComEnumBase
)
947 #ifndef _DEFAULT_VECTORLENGTH
948 #define _DEFAULT_VECTORLENGTH 4
951 class CComDynamicUnkArray
957 CComDynamicUnkArray()
963 ~CComDynamicUnkArray()
975 return &m_ppUnk
[m_nSize
];
978 IUnknown
*GetAt(int nIndex
)
980 ATLASSERT(nIndex
>= 0 && nIndex
< m_nSize
);
981 if (nIndex
>= 0 && nIndex
< m_nSize
)
982 return m_ppUnk
[nIndex
];
987 IUnknown
*WINAPI
GetUnknown(DWORD dwCookie
)
989 ATLASSERT(dwCookie
!= 0 && dwCookie
<= static_cast<DWORD
>(m_nSize
));
990 if (dwCookie
!= 0 && dwCookie
<= static_cast<DWORD
>(m_nSize
))
991 return GetAt(dwCookie
- 1);
996 DWORD WINAPI
GetCookie(IUnknown
**ppFind
)
1001 ATLASSERT(ppFind
!= NULL
&& *ppFind
!= NULL
);
1002 if (ppFind
!= NULL
&& *ppFind
!= NULL
)
1005 for (x
= begin(); x
< end(); x
++)
1015 DWORD
Add(IUnknown
*pUnk
)
1018 IUnknown
**newArray
;
1022 ATLASSERT(pUnk
!= NULL
);
1025 newSize
= _DEFAULT_VECTORLENGTH
* sizeof(IUnknown
*);
1026 ATLTRY(newArray
= reinterpret_cast<IUnknown
**>(malloc(newSize
)));
1027 if (newArray
== NULL
)
1029 memset(newArray
, 0, newSize
);
1031 m_nSize
= _DEFAULT_VECTORLENGTH
;
1034 for (x
= begin(); x
< end(); x
++)
1043 newSize
= m_nSize
* 2;
1044 newArray
= reinterpret_cast<IUnknown
**>(realloc(m_ppUnk
, newSize
* sizeof(IUnknown
*)));
1045 if (newArray
== NULL
)
1048 memset(&m_ppUnk
[m_nSize
], 0, (newSize
- m_nSize
) * sizeof(IUnknown
*));
1049 curCookie
= m_nSize
+ 1;
1051 m_ppUnk
[curCookie
- 1] = pUnk
;
1055 BOOL
Remove(DWORD dwCookie
)
1059 index
= dwCookie
- 1;
1060 ATLASSERT(index
< dwCookie
&& index
< static_cast<DWORD
>(m_nSize
));
1061 if (index
< dwCookie
&& index
< static_cast<DWORD
>(m_nSize
) && m_ppUnk
[index
] != NULL
)
1063 m_ppUnk
[index
] = NULL
;
1070 CComDynamicUnkArray
&operator = (const CComDynamicUnkArray
&)
1075 CComDynamicUnkArray(const CComDynamicUnkArray
&)
1080 struct _ATL_CONNMAP_ENTRY
1085 template <const IID
*piid
>
1089 STDMETHOD(_LocCPQueryInterface
)(REFIID riid
, void **ppvObject
) = 0;
1090 virtual ULONG STDMETHODCALLTYPE
AddRef() = 0;
1091 virtual ULONG STDMETHODCALLTYPE
Release() = 0;
1094 template<class T
, const IID
*piid
, class CDV
= CComDynamicUnkArray
>
1095 class IConnectionPointImpl
: public _ICPLocator
<piid
>
1097 typedef CComEnum
<IEnumConnections
, &IID_IEnumConnections
, CONNECTDATA
, _Copy
<CONNECTDATA
> > CComEnumConnections
;
1101 ~IConnectionPointImpl()
1105 for (x
= m_vec
.begin(); x
< m_vec
.end(); x
++)
1110 STDMETHOD(_LocCPQueryInterface
)(REFIID riid
, void **ppvObject
)
1112 IConnectionPointImpl
<T
, piid
, CDV
> *pThis
;
1114 pThis
= reinterpret_cast<IConnectionPointImpl
<T
, piid
, CDV
>*>(this);
1116 ATLASSERT(ppvObject
!= NULL
);
1117 if (ppvObject
== NULL
)
1120 if (InlineIsEqualGUID(riid
, IID_IConnectionPoint
) || InlineIsEqualUnknown(riid
))
1129 return E_NOINTERFACE
;
1133 STDMETHOD(GetConnectionInterface
)(IID
*piid2
)
1141 STDMETHOD(GetConnectionPointContainer
)(IConnectionPointContainer
**ppCPC
)
1145 pThis
= static_cast<T
*>(this);
1146 return pThis
->QueryInterface(IID_IConnectionPointContainer
, reinterpret_cast<void **>(ppCPC
));
1149 STDMETHOD(Advise
)(IUnknown
*pUnkSink
, DWORD
*pdwCookie
)
1151 IUnknown
*adviseTarget
;
1155 if (pdwCookie
!= NULL
)
1157 if (pUnkSink
== NULL
|| pdwCookie
== NULL
)
1159 GetConnectionInterface(&interfaceID
); // can't fail
1160 hResult
= pUnkSink
->QueryInterface(interfaceID
, reinterpret_cast<void **>(&adviseTarget
));
1161 if (SUCCEEDED(hResult
))
1163 *pdwCookie
= m_vec
.Add(adviseTarget
);
1164 if (*pdwCookie
!= 0)
1168 adviseTarget
->Release();
1169 hResult
= CONNECT_E_ADVISELIMIT
;
1172 else if (hResult
== E_NOINTERFACE
)
1173 hResult
= CONNECT_E_CANNOTCONNECT
;
1177 STDMETHOD(Unadvise
)(DWORD dwCookie
)
1179 IUnknown
*adviseTarget
;
1182 adviseTarget
= m_vec
.GetUnknown(dwCookie
);
1183 if (m_vec
.Remove(dwCookie
))
1185 if (adviseTarget
!= NULL
)
1186 adviseTarget
->Release();
1190 hResult
= CONNECT_E_NOCONNECTION
;
1194 STDMETHOD(EnumConnections
)(IEnumConnections
**ppEnum
)
1196 CComObject
<CComEnumConnections
> *newEnumerator
;
1197 CONNECTDATA
*itemBuffer
;
1198 CONNECTDATA
*itemBufferEnd
;
1202 ATLASSERT(ppEnum
!= NULL
);
1207 ATLTRY(itemBuffer
= new CONNECTDATA
[m_vec
.end() - m_vec
.begin()])
1208 if (itemBuffer
== NULL
)
1209 return E_OUTOFMEMORY
;
1210 itemBufferEnd
= itemBuffer
;
1211 for (x
= m_vec
.begin(); x
< m_vec
.end(); x
++)
1216 itemBufferEnd
->pUnk
= *x
;
1217 itemBufferEnd
->dwCookie
= m_vec
.GetCookie(x
);
1221 ATLTRY(newEnumerator
= new CComObject
<CComEnumConnections
>)
1222 if (newEnumerator
== NULL
)
1223 return E_OUTOFMEMORY
;
1224 newEnumerator
->Init(itemBuffer
, itemBufferEnd
, NULL
, AtlFlagTakeOwnership
); // can't fail
1225 hResult
= newEnumerator
->_InternalQueryInterface(IID_IEnumConnections
, (void **)ppEnum
);
1226 if (FAILED(hResult
))
1227 delete newEnumerator
;
1233 class IConnectionPointContainerImpl
: public IConnectionPointContainer
1235 typedef const _ATL_CONNMAP_ENTRY
* (*handlerFunctionType
)(int *);
1236 typedef CComEnum
<IEnumConnectionPoints
, &IID_IEnumConnectionPoints
, IConnectionPoint
*, _CopyInterface
<IConnectionPoint
> >
1237 CComEnumConnectionPoints
;
1240 STDMETHOD(EnumConnectionPoints
)(IEnumConnectionPoints
**ppEnum
)
1242 const _ATL_CONNMAP_ENTRY
*entryPtr
;
1243 int connectionPointCount
;
1244 IConnectionPoint
**itemBuffer
;
1246 handlerFunctionType handlerFunction
;
1247 CComEnumConnectionPoints
*newEnumerator
;
1250 ATLASSERT(ppEnum
!= NULL
);
1255 entryPtr
= T::GetConnMap(&connectionPointCount
);
1256 ATLTRY(itemBuffer
= new IConnectionPoint
* [connectionPointCount
])
1257 if (itemBuffer
== NULL
)
1258 return E_OUTOFMEMORY
;
1261 while (entryPtr
->dwOffset
!= static_cast<DWORD_PTR
>(-1))
1263 if (entryPtr
->dwOffset
== static_cast<DWORD_PTR
>(-2))
1266 handlerFunction
= reinterpret_cast<handlerFunctionType
>(entryPtr
->dwOffset
);
1267 entryPtr
= handlerFunction(NULL
);
1271 itemBuffer
[destIndex
++] = reinterpret_cast<IConnectionPoint
*>((char *)this + entryPtr
->dwOffset
);
1276 ATLTRY(newEnumerator
= new CComObject
<CComEnumConnectionPoints
>)
1277 if (newEnumerator
== NULL
)
1279 delete [] itemBuffer
;
1280 return E_OUTOFMEMORY
;
1283 newEnumerator
->Init(&itemBuffer
[0], &itemBuffer
[destIndex
], NULL
, AtlFlagTakeOwnership
); // can't fail
1284 hResult
= newEnumerator
->QueryInterface(IID_IEnumConnectionPoints
, (void**)ppEnum
);
1285 if (FAILED(hResult
))
1286 delete newEnumerator
;
1290 STDMETHOD(FindConnectionPoint
)(REFIID riid
, IConnectionPoint
**ppCP
)
1293 const _ATL_CONNMAP_ENTRY
*entryPtr
;
1294 handlerFunctionType handlerFunction
;
1295 IConnectionPoint
*connectionPoint
;
1301 hResult
= CONNECT_E_NOCONNECTION
;
1302 entryPtr
= T::GetConnMap(NULL
);
1303 while (entryPtr
->dwOffset
!= static_cast<DWORD_PTR
>(-1))
1305 if (entryPtr
->dwOffset
== static_cast<DWORD_PTR
>(-2))
1308 handlerFunction
= reinterpret_cast<handlerFunctionType
>(entryPtr
->dwOffset
);
1309 entryPtr
= handlerFunction(NULL
);
1313 connectionPoint
= reinterpret_cast<IConnectionPoint
*>(reinterpret_cast<char *>(this) + entryPtr
->dwOffset
);
1314 if (SUCCEEDED(connectionPoint
->GetConnectionInterface(&interfaceID
)) && InlineIsEqualGUID(riid
, interfaceID
))
1316 *ppCP
= connectionPoint
;
1317 connectionPoint
->AddRef();
1328 #define BEGIN_CONNECTION_POINT_MAP(x) \
1329 typedef x _atl_conn_classtype; \
1330 static const ATL::_ATL_CONNMAP_ENTRY *GetConnMap(int *pnEntries) { \
1331 static const ATL::_ATL_CONNMAP_ENTRY _entries[] = {
1333 #define END_CONNECTION_POINT_MAP() \
1334 {(DWORD_PTR)-1} }; \
1336 *pnEntries = sizeof(_entries) / sizeof(ATL::_ATL_CONNMAP_ENTRY) - 1; \
1339 #define CONNECTION_POINT_ENTRY(iid) \
1340 {offsetofclass(ATL::_ICPLocator<&iid>, _atl_conn_classtype) - \
1341 offsetofclass(ATL::IConnectionPointContainerImpl<_atl_conn_classtype>, _atl_conn_classtype)},