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)
32 #define DECLARE_CLASSFACTORY_SINGLETON(obj) DECLARE_CLASSFACTORY_EX(ATL::CComClassFactorySingleton<obj>)
34 class CComObjectRootBase
52 HRESULT
_AtlFinalConstruct()
57 HRESULT
FinalConstruct()
62 void InternalFinalConstructAddRef()
66 void InternalFinalConstructRelease()
74 static void WINAPI
ObjectMain(bool)
78 static const struct _ATL_CATMAP_ENTRY
*GetCategoryMap()
83 static HRESULT WINAPI
InternalQueryInterface(void *pThis
, const _ATL_INTMAP_ENTRY
*pEntries
, REFIID iid
, void **ppvObject
)
85 return AtlInternalQueryInterface(pThis
, pEntries
, iid
, ppvObject
);
90 template <class ThreadModel
>
91 class CComObjectRootEx
: public CComObjectRootBase
94 typename
ThreadModel::AutoDeleteCriticalSection m_critsec
;
100 ULONG
InternalAddRef()
102 ATLASSERT(m_dwRef
>= 0);
103 return ThreadModel::Increment(&m_dwRef
);
106 ULONG
InternalRelease()
108 ATLASSERT(m_dwRef
> 0);
109 return ThreadModel::Decrement(&m_dwRef
);
122 HRESULT
_AtlInitialConstruct()
124 return m_critsec
.Init();
128 template <class Base
>
129 class CComObject
: public Base
132 CComObject(void * = NULL
)
137 virtual ~CComObject()
139 this->FinalRelease();
140 _pAtlModule
->Unlock();
143 STDMETHOD_(ULONG
, AddRef
)()
145 return this->InternalAddRef();
148 STDMETHOD_(ULONG
, Release
)()
152 newRefCount
= this->InternalRelease();
153 if (newRefCount
== 0)
158 STDMETHOD(QueryInterface
)(REFIID iid
, void **ppvObject
)
160 return this->_InternalQueryInterface(iid
, ppvObject
);
163 static HRESULT WINAPI
CreateInstance(CComObject
<Base
> **pp
)
165 CComObject
<Base
> *newInstance
;
168 ATLASSERT(pp
!= NULL
);
172 hResult
= E_OUTOFMEMORY
;
174 ATLTRY(newInstance
= new CComObject
<Base
>())
175 if (newInstance
!= NULL
)
177 newInstance
->SetVoid(NULL
);
178 newInstance
->InternalFinalConstructAddRef();
179 hResult
= newInstance
->_AtlInitialConstruct();
180 if (SUCCEEDED(hResult
))
181 hResult
= newInstance
->FinalConstruct();
182 if (SUCCEEDED(hResult
))
183 hResult
= newInstance
->_AtlFinalConstruct();
184 newInstance
->InternalFinalConstructRelease();
198 template <class Base
>
199 class CComContainedObject
: public Base
202 IUnknown
* m_pUnkOuter
;
203 CComContainedObject(void * pv
= NULL
) : m_pUnkOuter(static_cast<IUnknown
*>(pv
))
207 STDMETHOD_(ULONG
, AddRef
)()
209 return m_pUnkOuter
->AddRef();
212 STDMETHOD_(ULONG
, Release
)()
214 return m_pUnkOuter
->Release();
217 STDMETHOD(QueryInterface
)(REFIID iid
, void **ppvObject
)
219 return m_pUnkOuter
->QueryInterface(iid
, ppvObject
);
222 IUnknown
* GetControllingUnknown()
228 template <class contained
>
229 class CComAggObject
: public contained
232 CComContainedObject
<contained
> m_contained
;
234 CComAggObject(void * pv
= NULL
) : m_contained(static_cast<contained
*>(pv
))
239 virtual ~CComAggObject()
241 this->FinalRelease();
242 _pAtlModule
->Unlock();
245 HRESULT
FinalConstruct()
247 return m_contained
.FinalConstruct();
251 m_contained
.FinalRelease();
254 STDMETHOD_(ULONG
, AddRef
)()
256 return this->InternalAddRef();
259 STDMETHOD_(ULONG
, Release
)()
262 newRefCount
= this->InternalRelease();
263 if (newRefCount
== 0)
268 STDMETHOD(QueryInterface
)(REFIID iid
, void **ppvObject
)
270 if (ppvObject
== NULL
)
272 if (iid
== IID_IUnknown
)
273 *ppvObject
= reinterpret_cast<void*>(this);
275 return m_contained
._InternalQueryInterface(iid
, ppvObject
);
279 static HRESULT WINAPI
CreateInstance(IUnknown
* punkOuter
, CComAggObject
<contained
> **pp
)
281 CComAggObject
<contained
> *newInstance
;
284 ATLASSERT(pp
!= NULL
);
288 hResult
= E_OUTOFMEMORY
;
290 ATLTRY(newInstance
= new CComAggObject
<contained
>(punkOuter
))
291 if (newInstance
!= NULL
)
293 newInstance
->SetVoid(NULL
);
294 newInstance
->InternalFinalConstructAddRef();
295 hResult
= newInstance
->_AtlInitialConstruct();
296 if (SUCCEEDED(hResult
))
297 hResult
= newInstance
->FinalConstruct();
298 if (SUCCEEDED(hResult
))
299 hResult
= newInstance
->_AtlFinalConstruct();
300 newInstance
->InternalFinalConstructRelease();
312 template <class contained
>
313 class CComPolyObject
: public contained
316 CComContainedObject
<contained
> m_contained
;
318 CComPolyObject(void * pv
= NULL
)
319 : m_contained(pv
? static_cast<contained
*>(pv
) : this)
324 virtual ~CComPolyObject()
326 this->FinalRelease();
327 _pAtlModule
->Unlock();
330 HRESULT
FinalConstruct()
332 return m_contained
.FinalConstruct();
336 m_contained
.FinalRelease();
339 STDMETHOD_(ULONG
, AddRef
)()
341 return this->InternalAddRef();
344 STDMETHOD_(ULONG
, Release
)()
347 newRefCount
= this->InternalRelease();
348 if (newRefCount
== 0)
353 STDMETHOD(QueryInterface
)(REFIID iid
, void **ppvObject
)
355 if (ppvObject
== NULL
)
357 if (iid
== IID_IUnknown
)
358 *ppvObject
= reinterpret_cast<void*>(this);
360 return m_contained
._InternalQueryInterface(iid
, ppvObject
);
364 static HRESULT WINAPI
CreateInstance(IUnknown
* punkOuter
, CComPolyObject
<contained
> **pp
)
366 CComPolyObject
<contained
> *newInstance
;
369 ATLASSERT(pp
!= NULL
);
373 hResult
= E_OUTOFMEMORY
;
375 ATLTRY(newInstance
= new CComPolyObject
<contained
>(punkOuter
))
376 if (newInstance
!= NULL
)
378 newInstance
->SetVoid(NULL
);
379 newInstance
->InternalFinalConstructAddRef();
380 hResult
= newInstance
->_AtlInitialConstruct();
381 if (SUCCEEDED(hResult
))
382 hResult
= newInstance
->FinalConstruct();
383 if (SUCCEEDED(hResult
))
384 hResult
= newInstance
->_AtlFinalConstruct();
385 newInstance
->InternalFinalConstructRelease();
397 template <HRESULT hResult
>
398 class CComFailCreator
401 static HRESULT WINAPI
CreateInstance(void *, REFIID
, LPVOID
*ppv
)
403 ATLASSERT(ppv
!= NULL
);
416 static HRESULT WINAPI
CreateInstance(void *pv
, REFIID riid
, LPVOID
*ppv
)
421 ATLASSERT(ppv
!= NULL
);
426 hResult
= E_OUTOFMEMORY
;
428 ATLTRY(newInstance
= new T1(pv
))
429 if (newInstance
!= NULL
)
431 newInstance
->SetVoid(pv
);
432 newInstance
->InternalFinalConstructAddRef();
433 hResult
= newInstance
->_AtlInitialConstruct();
434 if (SUCCEEDED(hResult
))
435 hResult
= newInstance
->FinalConstruct();
436 if (SUCCEEDED(hResult
))
437 hResult
= newInstance
->_AtlFinalConstruct();
438 newInstance
->InternalFinalConstructRelease();
439 if (SUCCEEDED(hResult
))
440 hResult
= newInstance
->QueryInterface(riid
, ppv
);
451 template <class T1
, class T2
>
455 static HRESULT WINAPI
CreateInstance(void *pv
, REFIID riid
, LPVOID
*ppv
)
457 ATLASSERT(ppv
!= NULL
&& riid
!= NULL
);
460 return T1::CreateInstance(NULL
, riid
, ppv
);
462 return T2::CreateInstance(pv
, riid
, ppv
);
466 template <class Base
>
467 class CComObjectCached
: public Base
470 CComObjectCached(void * = NULL
)
474 virtual ~CComObjectCached()
476 this->FinalRelease();
479 STDMETHOD_(ULONG
, AddRef
)()
483 newRefCount
= this->InternalAddRef();
484 if (newRefCount
== 2)
489 STDMETHOD_(ULONG
, Release
)()
493 newRefCount
= this->InternalRelease();
494 if (newRefCount
== 0)
496 else if (newRefCount
== 1)
497 _pAtlModule
->Unlock();
501 STDMETHOD(QueryInterface
)(REFIID iid
, void **ppvObject
)
503 return this->_InternalQueryInterface(iid
, ppvObject
);
506 static HRESULT WINAPI
CreateInstance(CComObjectCached
<Base
> **pp
)
508 CComObjectCached
<Base
> *newInstance
;
511 ATLASSERT(pp
!= NULL
);
515 hResult
= E_OUTOFMEMORY
;
517 ATLTRY(newInstance
= new CComObjectCached
<Base
>())
518 if (newInstance
!= NULL
)
520 newInstance
->SetVoid(NULL
);
521 newInstance
->InternalFinalConstructAddRef();
522 hResult
= newInstance
->_AtlInitialConstruct();
523 if (SUCCEEDED(hResult
))
524 hResult
= newInstance
->FinalConstruct();
525 if (SUCCEEDED(hResult
))
526 hResult
= newInstance
->_AtlFinalConstruct();
527 newInstance
->InternalFinalConstructRelease();
539 #define BEGIN_COM_MAP(x) \
541 typedef x _ComMapClass; \
542 HRESULT _InternalQueryInterface(REFIID iid, void **ppvObject) \
544 return this->InternalQueryInterface(this, _GetEntries(), iid, ppvObject); \
546 const static ATL::_ATL_INTMAP_ENTRY *WINAPI _GetEntries() \
548 static const ATL::_ATL_INTMAP_ENTRY _entries[] = {
550 #define END_COM_MAP() \
555 virtual ULONG STDMETHODCALLTYPE AddRef() = 0; \
556 virtual ULONG STDMETHODCALLTYPE Release() = 0; \
557 STDMETHOD(QueryInterface)(REFIID, void **) = 0;
559 #define COM_INTERFACE_ENTRY_IID(iid, x) \
560 {&iid, offsetofclass(x, _ComMapClass), _ATL_SIMPLEMAPENTRY},
562 #define COM_INTERFACE_ENTRY(x) \
564 offsetofclass(x, _ComMapClass), \
565 _ATL_SIMPLEMAPENTRY},
567 #define COM_INTERFACE_ENTRY2_IID(iid, x, x2) \
569 reinterpret_cast<DWORD_PTR>(static_cast<x *>(static_cast<x2 *>(reinterpret_cast<_ComMapClass *>(_ATL_PACKING)))) - _ATL_PACKING, \
570 _ATL_SIMPLEMAPENTRY},
572 #define COM_INTERFACE_ENTRY_BREAK(x) \
575 _Break}, // Break is a function that issues int 3.
577 #define COM_INTERFACE_ENTRY_NOINTERFACE(x) \
580 _NoInterface}, // NoInterface returns E_NOINTERFACE.
582 #define COM_INTERFACE_ENTRY_FUNC(iid, dw, func) \
587 #define COM_INTERFACE_ENTRY_FUNC_BLIND(dw, func) \
592 #define COM_INTERFACE_ENTRY_CHAIN(classname) \
594 reinterpret_cast<DWORD>(&_CComChainData<classname, _ComMapClass>::data), \
597 #define DECLARE_NO_REGISTRY()\
598 static HRESULT WINAPI UpdateRegistry(BOOL /*bRegister*/) \
603 #define DECLARE_REGISTRY_RESOURCEID(x) \
604 static HRESULT WINAPI UpdateRegistry(BOOL bRegister) \
606 return ATL::_pAtlModule->UpdateRegistryFromResource(x, bRegister); \
609 #define DECLARE_NOT_AGGREGATABLE(x) \
611 typedef ATL::CComCreator2<ATL::CComCreator<ATL::CComObject<x> >, ATL::CComFailCreator<CLASS_E_NOAGGREGATION> > _CreatorClass;
613 #define DECLARE_AGGREGATABLE(x) \
615 typedef ATL::CComCreator2<ATL::CComCreator<ATL::CComObject<x> >, ATL::CComCreator<ATL::CComAggObject<x> > > _CreatorClass;
617 #define DECLARE_ONLY_AGGREGATABLE(x) \
619 typedef ATL::CComCreator2<ATL::CComFailCreator<E_FAIL>, ATL::CComCreator<ATL::CComAggObject<x> > > _CreatorClass;
621 #define DECLARE_POLY_AGGREGATABLE(x) \
623 typedef ATL::CComCreator<ATL::CComPolyObject<x> > _CreatorClass;
625 #define COM_INTERFACE_ENTRY_AGGREGATE(iid, punk) \
627 (DWORD_PTR)offsetof(_ComMapClass, punk), \
630 #define DECLARE_GET_CONTROLLING_UNKNOWN() \
632 virtual IUnknown *GetControllingUnknown() \
634 return GetUnknown(); \
637 #define DECLARE_PROTECT_FINAL_CONSTRUCT() \
638 void InternalFinalConstructAddRef() \
642 void InternalFinalConstructRelease() \
647 #define BEGIN_OBJECT_MAP(x) static ATL::_ATL_OBJMAP_ENTRY x[] = {
649 #define END_OBJECT_MAP() {NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL}};
651 #define OBJECT_ENTRY(clsid, class) \
654 class::UpdateRegistry, \
655 class::_ClassFactoryCreatorClass::CreateInstance, \
656 class::_CreatorClass::CreateInstance, \
659 class::GetObjectDescription, \
660 class::GetCategoryMap, \
663 class CComClassFactory
:
664 public IClassFactory
,
665 public CComObjectRootEx
<CComGlobalsThreadModel
>
668 _ATL_CREATORFUNC
*m_pfnCreateInstance
;
670 virtual ~CComClassFactory()
675 STDMETHOD(CreateInstance
)(LPUNKNOWN pUnkOuter
, REFIID riid
, void **ppvObj
)
679 ATLASSERT(m_pfnCreateInstance
!= NULL
);
685 if (pUnkOuter
!= NULL
&& InlineIsEqualUnknown(riid
) == FALSE
)
686 hResult
= CLASS_E_NOAGGREGATION
;
688 hResult
= m_pfnCreateInstance(pUnkOuter
, riid
, ppvObj
);
692 STDMETHOD(LockServer
)(BOOL fLock
)
697 _pAtlModule
->Unlock();
701 void SetVoid(void *pv
)
703 m_pfnCreateInstance
= (_ATL_CREATORFUNC
*)pv
;
706 BEGIN_COM_MAP(CComClassFactory
)
707 COM_INTERFACE_ENTRY_IID(IID_IClassFactory
, IClassFactory
)
712 class CComClassFactorySingleton
:
713 public CComClassFactory
720 CComClassFactorySingleton() :
726 STDMETHOD(CreateInstance
)(LPUNKNOWN pUnkOuter
, REFIID riid
, void **ppvObj
)
734 if (pUnkOuter
!= NULL
)
735 hResult
= CLASS_E_NOAGGREGATION
;
736 else if (m_hrCreate
== S_OK
&& m_spObj
== NULL
)
741 if (m_hrCreate
== S_OK
&& m_spObj
== NULL
)
743 CComObjectCached
<T
> *pObj
;
744 m_hrCreate
= CComObjectCached
<T
>::CreateInstance(&pObj
);
745 if (SUCCEEDED(m_hrCreate
))
747 m_hrCreate
= pObj
->QueryInterface(IID_IUnknown
, reinterpret_cast<PVOID
*>(&m_spObj
));
748 if (FAILED(m_hrCreate
))
759 if (m_hrCreate
== S_OK
)
760 hResult
= m_spObj
->QueryInterface(riid
, ppvObj
);
762 hResult
= m_hrCreate
;
767 template <class T
, const CLSID
*pclsid
= &CLSID_NULL
>
771 DECLARE_CLASSFACTORY()
773 static LPCTSTR WINAPI
GetObjectDescription()
783 static HRESULT
copy(T
*pTo
, const T
*pFrom
)
785 memcpy(pTo
, pFrom
, sizeof(T
));
789 static void init(T
*)
793 static void destroy(T
*)
799 class _Copy
<CONNECTDATA
>
802 static HRESULT
copy(CONNECTDATA
*pTo
, const CONNECTDATA
*pFrom
)
810 static void init(CONNECTDATA
*)
814 static void destroy(CONNECTDATA
*p
)
825 static HRESULT
copy(T
**pTo
, T
**pFrom
)
833 static void init(T
**)
837 static void destroy(T
**p
)
847 AtlFlagTakeOwnership
= 2, // BitOwn
848 AtlFlagCopy
= 3 // BitOwn | BitCopy
851 template <class Base
, const IID
*piid
, class T
, class Copy
>
852 class CComEnumImpl
: public Base
855 typedef CComObject
<CComEnum
<Base
, piid
, T
, Copy
> > enumeratorClass
;
857 CComPtr
<IUnknown
> m_spUnk
;
871 virtual ~CComEnumImpl()
875 if ((m_dwFlags
& BitOwn
) != 0)
877 for (x
= m_begin
; x
!= m_end
; x
++)
883 HRESULT
Init(T
*begin
, T
*end
, IUnknown
*pUnk
, CComEnumFlags flags
= AtlFlagNoCopy
)
891 if (flags
== AtlFlagCopy
)
893 ATLTRY(newBuffer
= new T
[end
- begin
])
894 if (newBuffer
== NULL
)
895 return E_OUTOFMEMORY
;
897 for (sourcePtr
= begin
; sourcePtr
!= end
; sourcePtr
++)
900 hResult
= Copy::copy(destPtr
, sourcePtr
);
903 cleanupPtr
= m_begin
;
904 while (cleanupPtr
< destPtr
)
905 Copy::destroy(cleanupPtr
++);
912 m_end
= m_begin
+ (end
- begin
);
925 STDMETHOD(Next
)(ULONG celt
, T
*rgelt
, ULONG
*pceltFetched
)
932 if (pceltFetched
!= NULL
)
936 if (rgelt
== NULL
|| (celt
!= 1 && pceltFetched
== NULL
))
938 if (m_begin
== NULL
|| m_end
== NULL
|| m_iter
== NULL
)
941 numAvailable
= static_cast<ULONG
>(m_end
- m_iter
);
942 if (celt
< numAvailable
)
945 numToFetch
= numAvailable
;
946 if (pceltFetched
!= NULL
)
947 *pceltFetched
= numToFetch
;
949 while (numToFetch
!= 0)
951 hResult
= Copy::copy(rgeltTemp
, m_iter
);
954 while (rgelt
< rgeltTemp
)
955 Copy::destroy(rgelt
++);
956 if (pceltFetched
!= NULL
)
964 if (numAvailable
< celt
)
969 STDMETHOD(Skip
)(ULONG celt
)
977 numAvailable
= static_cast<ULONG
>(m_end
- m_iter
);
978 if (celt
< numAvailable
)
981 numToSkip
= numAvailable
;
983 if (numAvailable
< celt
)
994 STDMETHOD(Clone
)(Base
**ppEnum
)
996 enumeratorClass
*newInstance
;
1003 hResult
= enumeratorClass::CreateInstance(&newInstance
);
1004 if (SUCCEEDED(hResult
))
1006 hResult
= newInstance
->Init(m_begin
, m_end
, (m_dwFlags
& BitOwn
) ? this : m_spUnk
);
1007 if (SUCCEEDED(hResult
))
1009 newInstance
->m_iter
= m_iter
;
1010 hResult
= newInstance
->_InternalQueryInterface(*piid
, (void **)ppEnum
);
1012 if (FAILED(hResult
))
1027 template <class Base
, const IID
*piid
, class T
, class Copy
, class ThreadModel
>
1029 public CComEnumImpl
<Base
, piid
, T
, Copy
>,
1030 public CComObjectRootEx
<ThreadModel
>
1033 typedef CComEnum
<Base
, piid
, T
, Copy
> _CComEnum
;
1034 typedef CComEnumImpl
<Base
, piid
, T
, Copy
> _CComEnumBase
;
1036 BEGIN_COM_MAP(_CComEnum
)
1037 COM_INTERFACE_ENTRY_IID(*piid
, _CComEnumBase
)
1041 #ifndef _DEFAULT_VECTORLENGTH
1042 #define _DEFAULT_VECTORLENGTH 4
1045 class CComDynamicUnkArray
1051 CComDynamicUnkArray()
1057 ~CComDynamicUnkArray()
1069 return &m_ppUnk
[m_nSize
];
1072 IUnknown
*GetAt(int nIndex
)
1074 ATLASSERT(nIndex
>= 0 && nIndex
< m_nSize
);
1075 if (nIndex
>= 0 && nIndex
< m_nSize
)
1076 return m_ppUnk
[nIndex
];
1081 IUnknown
*WINAPI
GetUnknown(DWORD dwCookie
)
1083 ATLASSERT(dwCookie
!= 0 && dwCookie
<= static_cast<DWORD
>(m_nSize
));
1084 if (dwCookie
!= 0 && dwCookie
<= static_cast<DWORD
>(m_nSize
))
1085 return GetAt(dwCookie
- 1);
1090 DWORD WINAPI
GetCookie(IUnknown
**ppFind
)
1095 ATLASSERT(ppFind
!= NULL
&& *ppFind
!= NULL
);
1096 if (ppFind
!= NULL
&& *ppFind
!= NULL
)
1099 for (x
= begin(); x
< end(); x
++)
1109 DWORD
Add(IUnknown
*pUnk
)
1112 IUnknown
**newArray
;
1116 ATLASSERT(pUnk
!= NULL
);
1119 newSize
= _DEFAULT_VECTORLENGTH
* sizeof(IUnknown
*);
1120 ATLTRY(newArray
= reinterpret_cast<IUnknown
**>(malloc(newSize
)));
1121 if (newArray
== NULL
)
1123 memset(newArray
, 0, newSize
);
1125 m_nSize
= _DEFAULT_VECTORLENGTH
;
1128 for (x
= begin(); x
< end(); x
++)
1137 newSize
= m_nSize
* 2;
1138 newArray
= reinterpret_cast<IUnknown
**>(realloc(m_ppUnk
, newSize
* sizeof(IUnknown
*)));
1139 if (newArray
== NULL
)
1142 memset(&m_ppUnk
[m_nSize
], 0, (newSize
- m_nSize
) * sizeof(IUnknown
*));
1143 curCookie
= m_nSize
+ 1;
1145 m_ppUnk
[curCookie
- 1] = pUnk
;
1149 BOOL
Remove(DWORD dwCookie
)
1153 index
= dwCookie
- 1;
1154 ATLASSERT(index
< dwCookie
&& index
< static_cast<DWORD
>(m_nSize
));
1155 if (index
< dwCookie
&& index
< static_cast<DWORD
>(m_nSize
) && m_ppUnk
[index
] != NULL
)
1157 m_ppUnk
[index
] = NULL
;
1164 CComDynamicUnkArray
&operator = (const CComDynamicUnkArray
&)
1169 CComDynamicUnkArray(const CComDynamicUnkArray
&)
1174 struct _ATL_CONNMAP_ENTRY
1179 template <const IID
*piid
>
1183 STDMETHOD(_LocCPQueryInterface
)(REFIID riid
, void **ppvObject
) = 0;
1184 virtual ULONG STDMETHODCALLTYPE
AddRef() = 0;
1185 virtual ULONG STDMETHODCALLTYPE
Release() = 0;
1188 template<class T
, const IID
*piid
, class CDV
= CComDynamicUnkArray
>
1189 class IConnectionPointImpl
: public _ICPLocator
<piid
>
1191 typedef CComEnum
<IEnumConnections
, &IID_IEnumConnections
, CONNECTDATA
, _Copy
<CONNECTDATA
> > CComEnumConnections
;
1195 ~IConnectionPointImpl()
1199 for (x
= m_vec
.begin(); x
< m_vec
.end(); x
++)
1204 STDMETHOD(_LocCPQueryInterface
)(REFIID riid
, void **ppvObject
)
1206 IConnectionPointImpl
<T
, piid
, CDV
> *pThis
;
1208 pThis
= reinterpret_cast<IConnectionPointImpl
<T
, piid
, CDV
>*>(this);
1210 ATLASSERT(ppvObject
!= NULL
);
1211 if (ppvObject
== NULL
)
1214 if (InlineIsEqualGUID(riid
, IID_IConnectionPoint
) || InlineIsEqualUnknown(riid
))
1223 return E_NOINTERFACE
;
1227 STDMETHOD(GetConnectionInterface
)(IID
*piid2
)
1235 STDMETHOD(GetConnectionPointContainer
)(IConnectionPointContainer
**ppCPC
)
1239 pThis
= static_cast<T
*>(this);
1240 return pThis
->QueryInterface(IID_IConnectionPointContainer
, reinterpret_cast<void **>(ppCPC
));
1243 STDMETHOD(Advise
)(IUnknown
*pUnkSink
, DWORD
*pdwCookie
)
1245 IUnknown
*adviseTarget
;
1249 if (pdwCookie
!= NULL
)
1251 if (pUnkSink
== NULL
|| pdwCookie
== NULL
)
1253 GetConnectionInterface(&interfaceID
); // can't fail
1254 hResult
= pUnkSink
->QueryInterface(interfaceID
, reinterpret_cast<void **>(&adviseTarget
));
1255 if (SUCCEEDED(hResult
))
1257 *pdwCookie
= m_vec
.Add(adviseTarget
);
1258 if (*pdwCookie
!= 0)
1262 adviseTarget
->Release();
1263 hResult
= CONNECT_E_ADVISELIMIT
;
1266 else if (hResult
== E_NOINTERFACE
)
1267 hResult
= CONNECT_E_CANNOTCONNECT
;
1271 STDMETHOD(Unadvise
)(DWORD dwCookie
)
1273 IUnknown
*adviseTarget
;
1276 adviseTarget
= m_vec
.GetUnknown(dwCookie
);
1277 if (m_vec
.Remove(dwCookie
))
1279 if (adviseTarget
!= NULL
)
1280 adviseTarget
->Release();
1284 hResult
= CONNECT_E_NOCONNECTION
;
1288 STDMETHOD(EnumConnections
)(IEnumConnections
**ppEnum
)
1290 CComObject
<CComEnumConnections
> *newEnumerator
;
1291 CONNECTDATA
*itemBuffer
;
1292 CONNECTDATA
*itemBufferEnd
;
1296 ATLASSERT(ppEnum
!= NULL
);
1301 ATLTRY(itemBuffer
= new CONNECTDATA
[m_vec
.end() - m_vec
.begin()])
1302 if (itemBuffer
== NULL
)
1303 return E_OUTOFMEMORY
;
1304 itemBufferEnd
= itemBuffer
;
1305 for (x
= m_vec
.begin(); x
< m_vec
.end(); x
++)
1310 itemBufferEnd
->pUnk
= *x
;
1311 itemBufferEnd
->dwCookie
= m_vec
.GetCookie(x
);
1315 ATLTRY(newEnumerator
= new CComObject
<CComEnumConnections
>)
1316 if (newEnumerator
== NULL
)
1317 return E_OUTOFMEMORY
;
1318 newEnumerator
->Init(itemBuffer
, itemBufferEnd
, NULL
, AtlFlagTakeOwnership
); // can't fail
1319 hResult
= newEnumerator
->_InternalQueryInterface(IID_IEnumConnections
, (void **)ppEnum
);
1320 if (FAILED(hResult
))
1321 delete newEnumerator
;
1327 class IConnectionPointContainerImpl
: public IConnectionPointContainer
1329 typedef const _ATL_CONNMAP_ENTRY
* (*handlerFunctionType
)(int *);
1330 typedef CComEnum
<IEnumConnectionPoints
, &IID_IEnumConnectionPoints
, IConnectionPoint
*, _CopyInterface
<IConnectionPoint
> >
1331 CComEnumConnectionPoints
;
1334 STDMETHOD(EnumConnectionPoints
)(IEnumConnectionPoints
**ppEnum
)
1336 const _ATL_CONNMAP_ENTRY
*entryPtr
;
1337 int connectionPointCount
;
1338 IConnectionPoint
**itemBuffer
;
1340 handlerFunctionType handlerFunction
;
1341 CComEnumConnectionPoints
*newEnumerator
;
1344 ATLASSERT(ppEnum
!= NULL
);
1349 entryPtr
= T::GetConnMap(&connectionPointCount
);
1350 ATLTRY(itemBuffer
= new IConnectionPoint
* [connectionPointCount
])
1351 if (itemBuffer
== NULL
)
1352 return E_OUTOFMEMORY
;
1355 while (entryPtr
->dwOffset
!= static_cast<DWORD_PTR
>(-1))
1357 if (entryPtr
->dwOffset
== static_cast<DWORD_PTR
>(-2))
1360 handlerFunction
= reinterpret_cast<handlerFunctionType
>(entryPtr
->dwOffset
);
1361 entryPtr
= handlerFunction(NULL
);
1365 itemBuffer
[destIndex
++] = reinterpret_cast<IConnectionPoint
*>((char *)this + entryPtr
->dwOffset
);
1370 ATLTRY(newEnumerator
= new CComObject
<CComEnumConnectionPoints
>)
1371 if (newEnumerator
== NULL
)
1373 delete [] itemBuffer
;
1374 return E_OUTOFMEMORY
;
1377 newEnumerator
->Init(&itemBuffer
[0], &itemBuffer
[destIndex
], NULL
, AtlFlagTakeOwnership
); // can't fail
1378 hResult
= newEnumerator
->QueryInterface(IID_IEnumConnectionPoints
, (void**)ppEnum
);
1379 if (FAILED(hResult
))
1380 delete newEnumerator
;
1384 STDMETHOD(FindConnectionPoint
)(REFIID riid
, IConnectionPoint
**ppCP
)
1387 const _ATL_CONNMAP_ENTRY
*entryPtr
;
1388 handlerFunctionType handlerFunction
;
1389 IConnectionPoint
*connectionPoint
;
1395 hResult
= CONNECT_E_NOCONNECTION
;
1396 entryPtr
= T::GetConnMap(NULL
);
1397 while (entryPtr
->dwOffset
!= static_cast<DWORD_PTR
>(-1))
1399 if (entryPtr
->dwOffset
== static_cast<DWORD_PTR
>(-2))
1402 handlerFunction
= reinterpret_cast<handlerFunctionType
>(entryPtr
->dwOffset
);
1403 entryPtr
= handlerFunction(NULL
);
1407 connectionPoint
= reinterpret_cast<IConnectionPoint
*>(reinterpret_cast<char *>(this) + entryPtr
->dwOffset
);
1408 if (SUCCEEDED(connectionPoint
->GetConnectionInterface(&interfaceID
)) && InlineIsEqualGUID(riid
, interfaceID
))
1410 *ppCP
= connectionPoint
;
1411 connectionPoint
->AddRef();
1422 #define BEGIN_CONNECTION_POINT_MAP(x) \
1423 typedef x _atl_conn_classtype; \
1424 static const ATL::_ATL_CONNMAP_ENTRY *GetConnMap(int *pnEntries) { \
1425 static const ATL::_ATL_CONNMAP_ENTRY _entries[] = {
1427 #define END_CONNECTION_POINT_MAP() \
1428 {(DWORD_PTR)-1} }; \
1430 *pnEntries = sizeof(_entries) / sizeof(ATL::_ATL_CONNMAP_ENTRY) - 1; \
1433 #define CONNECTION_POINT_ENTRY(iid) \
1434 {offsetofclass(ATL::_ICPLocator<&iid>, _atl_conn_classtype) - \
1435 offsetofclass(ATL::IConnectionPointContainerImpl<_atl_conn_classtype>, _atl_conn_classtype)},