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
24 #include <cguid.h> // for GUID_NULL
29 template <class Base
, const IID
*piid
, class T
, class Copy
, class ThreadModel
= CComObjectThreadModel
>
32 #define DECLARE_CLASSFACTORY_EX(cf) typedef ATL::CComCreator<ATL::CComObjectCached<cf> > _ClassFactoryCreatorClass;
33 #define DECLARE_CLASSFACTORY() DECLARE_CLASSFACTORY_EX(ATL::CComClassFactory)
34 #define DECLARE_CLASSFACTORY_SINGLETON(obj) DECLARE_CLASSFACTORY_EX(ATL::CComClassFactorySingleton<obj>)
36 class CComObjectRootBase
54 HRESULT
_AtlFinalConstruct()
59 HRESULT
FinalConstruct()
64 void InternalFinalConstructAddRef()
68 void InternalFinalConstructRelease()
76 static void WINAPI
ObjectMain(bool)
80 static const struct _ATL_CATMAP_ENTRY
*GetCategoryMap()
85 static HRESULT WINAPI
InternalQueryInterface(void *pThis
, const _ATL_INTMAP_ENTRY
*pEntries
, REFIID iid
, void **ppvObject
)
87 return AtlInternalQueryInterface(pThis
, pEntries
, iid
, ppvObject
);
92 template <class ThreadModel
>
93 class CComObjectRootEx
: public CComObjectRootBase
96 typename
ThreadModel::AutoDeleteCriticalSection m_critsec
;
102 ULONG
InternalAddRef()
104 ATLASSERT(m_dwRef
>= 0);
105 return ThreadModel::Increment(&m_dwRef
);
108 ULONG
InternalRelease()
110 ATLASSERT(m_dwRef
> 0);
111 return ThreadModel::Decrement(&m_dwRef
);
124 HRESULT
_AtlInitialConstruct()
126 return m_critsec
.Init();
130 template <class Base
>
131 class CComObject
: public Base
134 CComObject(void * = NULL
)
139 virtual ~CComObject()
141 this->FinalRelease();
142 _pAtlModule
->Unlock();
145 STDMETHOD_(ULONG
, AddRef
)()
147 return this->InternalAddRef();
150 STDMETHOD_(ULONG
, Release
)()
154 newRefCount
= this->InternalRelease();
155 if (newRefCount
== 0)
160 STDMETHOD(QueryInterface
)(REFIID iid
, void **ppvObject
)
162 return this->_InternalQueryInterface(iid
, ppvObject
);
165 static HRESULT WINAPI
CreateInstance(CComObject
<Base
> **pp
)
167 CComObject
<Base
> *newInstance
;
170 ATLASSERT(pp
!= NULL
);
174 hResult
= E_OUTOFMEMORY
;
176 ATLTRY(newInstance
= new CComObject
<Base
>())
177 if (newInstance
!= NULL
)
179 newInstance
->SetVoid(NULL
);
180 newInstance
->InternalFinalConstructAddRef();
181 hResult
= newInstance
->_AtlInitialConstruct();
182 if (SUCCEEDED(hResult
))
183 hResult
= newInstance
->FinalConstruct();
184 if (SUCCEEDED(hResult
))
185 hResult
= newInstance
->_AtlFinalConstruct();
186 newInstance
->InternalFinalConstructRelease();
200 template <class Base
>
201 class CComContainedObject
: public Base
204 IUnknown
* m_pUnkOuter
;
205 CComContainedObject(void * pv
= NULL
) : m_pUnkOuter(static_cast<IUnknown
*>(pv
))
209 STDMETHOD_(ULONG
, AddRef
)()
211 return m_pUnkOuter
->AddRef();
214 STDMETHOD_(ULONG
, Release
)()
216 return m_pUnkOuter
->Release();
219 STDMETHOD(QueryInterface
)(REFIID iid
, void **ppvObject
)
221 return m_pUnkOuter
->QueryInterface(iid
, ppvObject
);
224 IUnknown
* GetControllingUnknown()
230 template <class contained
>
231 class CComAggObject
: public contained
234 CComContainedObject
<contained
> m_contained
;
236 CComAggObject(void * pv
= NULL
) : m_contained(static_cast<contained
*>(pv
))
241 virtual ~CComAggObject()
243 this->FinalRelease();
244 _pAtlModule
->Unlock();
247 HRESULT
FinalConstruct()
249 return m_contained
.FinalConstruct();
253 m_contained
.FinalRelease();
256 STDMETHOD_(ULONG
, AddRef
)()
258 return this->InternalAddRef();
261 STDMETHOD_(ULONG
, Release
)()
264 newRefCount
= this->InternalRelease();
265 if (newRefCount
== 0)
270 STDMETHOD(QueryInterface
)(REFIID iid
, void **ppvObject
)
272 if (ppvObject
== NULL
)
274 if (iid
== IID_IUnknown
)
275 *ppvObject
= reinterpret_cast<void*>(this);
277 return m_contained
._InternalQueryInterface(iid
, ppvObject
);
281 static HRESULT WINAPI
CreateInstance(IUnknown
* punkOuter
, CComAggObject
<contained
> **pp
)
283 CComAggObject
<contained
> *newInstance
;
286 ATLASSERT(pp
!= NULL
);
290 hResult
= E_OUTOFMEMORY
;
292 ATLTRY(newInstance
= new CComAggObject
<contained
>(punkOuter
))
293 if (newInstance
!= NULL
)
295 newInstance
->SetVoid(NULL
);
296 newInstance
->InternalFinalConstructAddRef();
297 hResult
= newInstance
->_AtlInitialConstruct();
298 if (SUCCEEDED(hResult
))
299 hResult
= newInstance
->FinalConstruct();
300 if (SUCCEEDED(hResult
))
301 hResult
= newInstance
->_AtlFinalConstruct();
302 newInstance
->InternalFinalConstructRelease();
314 template <class contained
>
315 class CComPolyObject
: public contained
318 CComContainedObject
<contained
> m_contained
;
320 CComPolyObject(void * pv
= NULL
)
321 : m_contained(pv
? static_cast<contained
*>(pv
) : this)
326 virtual ~CComPolyObject()
328 this->FinalRelease();
329 _pAtlModule
->Unlock();
332 HRESULT
FinalConstruct()
334 return m_contained
.FinalConstruct();
338 m_contained
.FinalRelease();
341 STDMETHOD_(ULONG
, AddRef
)()
343 return this->InternalAddRef();
346 STDMETHOD_(ULONG
, Release
)()
349 newRefCount
= this->InternalRelease();
350 if (newRefCount
== 0)
355 STDMETHOD(QueryInterface
)(REFIID iid
, void **ppvObject
)
357 if (ppvObject
== NULL
)
359 if (iid
== IID_IUnknown
)
360 *ppvObject
= reinterpret_cast<void*>(this);
362 return m_contained
._InternalQueryInterface(iid
, ppvObject
);
366 static HRESULT WINAPI
CreateInstance(IUnknown
* punkOuter
, CComPolyObject
<contained
> **pp
)
368 CComPolyObject
<contained
> *newInstance
;
371 ATLASSERT(pp
!= NULL
);
375 hResult
= E_OUTOFMEMORY
;
377 ATLTRY(newInstance
= new CComPolyObject
<contained
>(punkOuter
))
378 if (newInstance
!= NULL
)
380 newInstance
->SetVoid(NULL
);
381 newInstance
->InternalFinalConstructAddRef();
382 hResult
= newInstance
->_AtlInitialConstruct();
383 if (SUCCEEDED(hResult
))
384 hResult
= newInstance
->FinalConstruct();
385 if (SUCCEEDED(hResult
))
386 hResult
= newInstance
->_AtlFinalConstruct();
387 newInstance
->InternalFinalConstructRelease();
399 template <HRESULT hResult
>
400 class CComFailCreator
403 static HRESULT WINAPI
CreateInstance(void *, REFIID
, LPVOID
*ppv
)
405 ATLASSERT(ppv
!= NULL
);
418 static HRESULT WINAPI
CreateInstance(void *pv
, REFIID riid
, LPVOID
*ppv
)
423 ATLASSERT(ppv
!= NULL
);
428 hResult
= E_OUTOFMEMORY
;
430 ATLTRY(newInstance
= new T1(pv
))
431 if (newInstance
!= NULL
)
433 newInstance
->SetVoid(pv
);
434 newInstance
->InternalFinalConstructAddRef();
435 hResult
= newInstance
->_AtlInitialConstruct();
436 if (SUCCEEDED(hResult
))
437 hResult
= newInstance
->FinalConstruct();
438 if (SUCCEEDED(hResult
))
439 hResult
= newInstance
->_AtlFinalConstruct();
440 newInstance
->InternalFinalConstructRelease();
441 if (SUCCEEDED(hResult
))
442 hResult
= newInstance
->QueryInterface(riid
, ppv
);
453 template <class T1
, class T2
>
457 static HRESULT WINAPI
CreateInstance(void *pv
, REFIID riid
, LPVOID
*ppv
)
459 ATLASSERT(ppv
!= NULL
&& riid
!= NULL
);
462 return T1::CreateInstance(NULL
, riid
, ppv
);
464 return T2::CreateInstance(pv
, riid
, ppv
);
468 template <class Base
>
469 class CComObjectCached
: public Base
472 CComObjectCached(void * = NULL
)
476 virtual ~CComObjectCached()
478 this->FinalRelease();
481 STDMETHOD_(ULONG
, AddRef
)()
485 newRefCount
= this->InternalAddRef();
486 if (newRefCount
== 2)
491 STDMETHOD_(ULONG
, Release
)()
495 newRefCount
= this->InternalRelease();
496 if (newRefCount
== 0)
498 else if (newRefCount
== 1)
499 _pAtlModule
->Unlock();
503 STDMETHOD(QueryInterface
)(REFIID iid
, void **ppvObject
)
505 return this->_InternalQueryInterface(iid
, ppvObject
);
508 static HRESULT WINAPI
CreateInstance(CComObjectCached
<Base
> **pp
)
510 CComObjectCached
<Base
> *newInstance
;
513 ATLASSERT(pp
!= NULL
);
517 hResult
= E_OUTOFMEMORY
;
519 ATLTRY(newInstance
= new CComObjectCached
<Base
>())
520 if (newInstance
!= NULL
)
522 newInstance
->SetVoid(NULL
);
523 newInstance
->InternalFinalConstructAddRef();
524 hResult
= newInstance
->_AtlInitialConstruct();
525 if (SUCCEEDED(hResult
))
526 hResult
= newInstance
->FinalConstruct();
527 if (SUCCEEDED(hResult
))
528 hResult
= newInstance
->_AtlFinalConstruct();
529 newInstance
->InternalFinalConstructRelease();
541 #define BEGIN_COM_MAP(x) \
543 typedef x _ComMapClass; \
544 HRESULT _InternalQueryInterface(REFIID iid, void **ppvObject) \
546 return this->InternalQueryInterface(this, _GetEntries(), iid, ppvObject); \
548 const static ATL::_ATL_INTMAP_ENTRY *WINAPI _GetEntries() \
550 static const ATL::_ATL_INTMAP_ENTRY _entries[] = {
552 #define END_COM_MAP() \
557 virtual ULONG STDMETHODCALLTYPE AddRef() = 0; \
558 virtual ULONG STDMETHODCALLTYPE Release() = 0; \
559 STDMETHOD(QueryInterface)(REFIID, void **) = 0;
561 #define COM_INTERFACE_ENTRY_IID(iid, x) \
562 {&iid, offsetofclass(x, _ComMapClass), _ATL_SIMPLEMAPENTRY},
564 #define COM_INTERFACE_ENTRY(x) \
566 offsetofclass(x, _ComMapClass), \
567 _ATL_SIMPLEMAPENTRY},
569 #define COM_INTERFACE_ENTRY2_IID(iid, x, x2) \
571 reinterpret_cast<DWORD_PTR>(static_cast<x *>(static_cast<x2 *>(reinterpret_cast<_ComMapClass *>(_ATL_PACKING)))) - _ATL_PACKING, \
572 _ATL_SIMPLEMAPENTRY},
574 #define COM_INTERFACE_ENTRY_BREAK(x) \
577 _Break}, // Break is a function that issues int 3.
579 #define COM_INTERFACE_ENTRY_NOINTERFACE(x) \
582 _NoInterface}, // NoInterface returns E_NOINTERFACE.
584 #define COM_INTERFACE_ENTRY_FUNC(iid, dw, func) \
589 #define COM_INTERFACE_ENTRY_FUNC_BLIND(dw, func) \
594 #define COM_INTERFACE_ENTRY_CHAIN(classname) \
596 reinterpret_cast<DWORD>(&_CComChainData<classname, _ComMapClass>::data), \
599 #define DECLARE_NO_REGISTRY()\
600 static HRESULT WINAPI UpdateRegistry(BOOL /*bRegister*/) \
605 #define DECLARE_REGISTRY_RESOURCEID(x) \
606 static HRESULT WINAPI UpdateRegistry(BOOL bRegister) \
608 return ATL::_pAtlModule->UpdateRegistryFromResource(x, bRegister); \
611 #define DECLARE_NOT_AGGREGATABLE(x) \
613 typedef ATL::CComCreator2<ATL::CComCreator<ATL::CComObject<x> >, ATL::CComFailCreator<CLASS_E_NOAGGREGATION> > _CreatorClass;
615 #define DECLARE_AGGREGATABLE(x) \
617 typedef ATL::CComCreator2<ATL::CComCreator<ATL::CComObject<x> >, ATL::CComCreator<ATL::CComAggObject<x> > > _CreatorClass;
619 #define DECLARE_ONLY_AGGREGATABLE(x) \
621 typedef ATL::CComCreator2<ATL::CComFailCreator<E_FAIL>, ATL::CComCreator<ATL::CComAggObject<x> > > _CreatorClass;
623 #define DECLARE_POLY_AGGREGATABLE(x) \
625 typedef ATL::CComCreator<ATL::CComPolyObject<x> > _CreatorClass;
627 #define COM_INTERFACE_ENTRY_AGGREGATE(iid, punk) \
629 (DWORD_PTR)offsetof(_ComMapClass, punk), \
632 #define DECLARE_GET_CONTROLLING_UNKNOWN() \
634 virtual IUnknown *GetControllingUnknown() \
636 return GetUnknown(); \
639 #define DECLARE_PROTECT_FINAL_CONSTRUCT() \
640 void InternalFinalConstructAddRef() \
644 void InternalFinalConstructRelease() \
649 #define BEGIN_OBJECT_MAP(x) static ATL::_ATL_OBJMAP_ENTRY x[] = {
651 #define END_OBJECT_MAP() {NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL}};
653 #define OBJECT_ENTRY(clsid, class) \
656 class::UpdateRegistry, \
657 class::_ClassFactoryCreatorClass::CreateInstance, \
658 class::_CreatorClass::CreateInstance, \
661 class::GetObjectDescription, \
662 class::GetCategoryMap, \
665 class CComClassFactory
:
666 public IClassFactory
,
667 public CComObjectRootEx
<CComGlobalsThreadModel
>
670 _ATL_CREATORFUNC
*m_pfnCreateInstance
;
672 virtual ~CComClassFactory()
677 STDMETHOD(CreateInstance
)(LPUNKNOWN pUnkOuter
, REFIID riid
, void **ppvObj
)
681 ATLASSERT(m_pfnCreateInstance
!= NULL
);
687 if (pUnkOuter
!= NULL
&& InlineIsEqualUnknown(riid
) == FALSE
)
688 hResult
= CLASS_E_NOAGGREGATION
;
690 hResult
= m_pfnCreateInstance(pUnkOuter
, riid
, ppvObj
);
694 STDMETHOD(LockServer
)(BOOL fLock
)
699 _pAtlModule
->Unlock();
703 void SetVoid(void *pv
)
705 m_pfnCreateInstance
= (_ATL_CREATORFUNC
*)pv
;
708 BEGIN_COM_MAP(CComClassFactory
)
709 COM_INTERFACE_ENTRY_IID(IID_IClassFactory
, IClassFactory
)
714 class CComClassFactorySingleton
:
715 public CComClassFactory
722 CComClassFactorySingleton() :
728 STDMETHOD(CreateInstance
)(LPUNKNOWN pUnkOuter
, REFIID riid
, void **ppvObj
)
736 if (pUnkOuter
!= NULL
)
737 hResult
= CLASS_E_NOAGGREGATION
;
738 else if (m_hrCreate
== S_OK
&& m_spObj
== NULL
)
743 if (m_hrCreate
== S_OK
&& m_spObj
== NULL
)
745 CComObjectCached
<T
> *pObj
;
746 m_hrCreate
= CComObjectCached
<T
>::CreateInstance(&pObj
);
747 if (SUCCEEDED(m_hrCreate
))
749 m_hrCreate
= pObj
->QueryInterface(IID_IUnknown
, reinterpret_cast<PVOID
*>(&m_spObj
));
750 if (FAILED(m_hrCreate
))
761 if (m_hrCreate
== S_OK
)
762 hResult
= m_spObj
->QueryInterface(riid
, ppvObj
);
764 hResult
= m_hrCreate
;
769 template <class T
, const CLSID
*pclsid
= &CLSID_NULL
>
773 DECLARE_CLASSFACTORY()
775 static LPCTSTR WINAPI
GetObjectDescription()
785 static HRESULT
copy(T
*pTo
, const T
*pFrom
)
787 memcpy(pTo
, pFrom
, sizeof(T
));
791 static void init(T
*)
795 static void destroy(T
*)
801 class _Copy
<CONNECTDATA
>
804 static HRESULT
copy(CONNECTDATA
*pTo
, const CONNECTDATA
*pFrom
)
812 static void init(CONNECTDATA
*)
816 static void destroy(CONNECTDATA
*p
)
827 static HRESULT
copy(T
**pTo
, T
**pFrom
)
835 static void init(T
**)
839 static void destroy(T
**p
)
849 AtlFlagTakeOwnership
= 2, // BitOwn
850 AtlFlagCopy
= 3 // BitOwn | BitCopy
853 template <class Base
, const IID
*piid
, class T
, class Copy
>
854 class CComEnumImpl
: public Base
857 typedef CComObject
<CComEnum
<Base
, piid
, T
, Copy
> > enumeratorClass
;
859 CComPtr
<IUnknown
> m_spUnk
;
873 virtual ~CComEnumImpl()
877 if ((m_dwFlags
& BitOwn
) != 0)
879 for (x
= m_begin
; x
!= m_end
; x
++)
885 HRESULT
Init(T
*begin
, T
*end
, IUnknown
*pUnk
, CComEnumFlags flags
= AtlFlagNoCopy
)
893 if (flags
== AtlFlagCopy
)
895 ATLTRY(newBuffer
= new T
[end
- begin
])
896 if (newBuffer
== NULL
)
897 return E_OUTOFMEMORY
;
899 for (sourcePtr
= begin
; sourcePtr
!= end
; sourcePtr
++)
902 hResult
= Copy::copy(destPtr
, sourcePtr
);
905 cleanupPtr
= m_begin
;
906 while (cleanupPtr
< destPtr
)
907 Copy::destroy(cleanupPtr
++);
914 m_end
= m_begin
+ (end
- begin
);
927 STDMETHOD(Next
)(ULONG celt
, T
*rgelt
, ULONG
*pceltFetched
)
934 if (pceltFetched
!= NULL
)
938 if (rgelt
== NULL
|| (celt
!= 1 && pceltFetched
== NULL
))
940 if (m_begin
== NULL
|| m_end
== NULL
|| m_iter
== NULL
)
943 numAvailable
= static_cast<ULONG
>(m_end
- m_iter
);
944 if (celt
< numAvailable
)
947 numToFetch
= numAvailable
;
948 if (pceltFetched
!= NULL
)
949 *pceltFetched
= numToFetch
;
951 while (numToFetch
!= 0)
953 hResult
= Copy::copy(rgeltTemp
, m_iter
);
956 while (rgelt
< rgeltTemp
)
957 Copy::destroy(rgelt
++);
958 if (pceltFetched
!= NULL
)
966 if (numAvailable
< celt
)
971 STDMETHOD(Skip
)(ULONG celt
)
979 numAvailable
= static_cast<ULONG
>(m_end
- m_iter
);
980 if (celt
< numAvailable
)
983 numToSkip
= numAvailable
;
985 if (numAvailable
< celt
)
996 STDMETHOD(Clone
)(Base
**ppEnum
)
998 enumeratorClass
*newInstance
;
1001 hResult
= E_POINTER
;
1005 hResult
= enumeratorClass::CreateInstance(&newInstance
);
1006 if (SUCCEEDED(hResult
))
1008 hResult
= newInstance
->Init(m_begin
, m_end
, (m_dwFlags
& BitOwn
) ? this : m_spUnk
);
1009 if (SUCCEEDED(hResult
))
1011 newInstance
->m_iter
= m_iter
;
1012 hResult
= newInstance
->_InternalQueryInterface(*piid
, (void **)ppEnum
);
1014 if (FAILED(hResult
))
1029 template <class Base
, const IID
*piid
, class T
, class Copy
, class ThreadModel
>
1031 public CComEnumImpl
<Base
, piid
, T
, Copy
>,
1032 public CComObjectRootEx
<ThreadModel
>
1035 typedef CComEnum
<Base
, piid
, T
, Copy
> _CComEnum
;
1036 typedef CComEnumImpl
<Base
, piid
, T
, Copy
> _CComEnumBase
;
1038 BEGIN_COM_MAP(_CComEnum
)
1039 COM_INTERFACE_ENTRY_IID(*piid
, _CComEnumBase
)
1043 #ifndef _DEFAULT_VECTORLENGTH
1044 #define _DEFAULT_VECTORLENGTH 4
1047 class CComDynamicUnkArray
1053 CComDynamicUnkArray()
1059 ~CComDynamicUnkArray()
1071 return &m_ppUnk
[m_nSize
];
1074 IUnknown
*GetAt(int nIndex
)
1076 ATLASSERT(nIndex
>= 0 && nIndex
< m_nSize
);
1077 if (nIndex
>= 0 && nIndex
< m_nSize
)
1078 return m_ppUnk
[nIndex
];
1083 IUnknown
*WINAPI
GetUnknown(DWORD dwCookie
)
1085 ATLASSERT(dwCookie
!= 0 && dwCookie
<= static_cast<DWORD
>(m_nSize
));
1086 if (dwCookie
!= 0 && dwCookie
<= static_cast<DWORD
>(m_nSize
))
1087 return GetAt(dwCookie
- 1);
1092 DWORD WINAPI
GetCookie(IUnknown
**ppFind
)
1097 ATLASSERT(ppFind
!= NULL
&& *ppFind
!= NULL
);
1098 if (ppFind
!= NULL
&& *ppFind
!= NULL
)
1101 for (x
= begin(); x
< end(); x
++)
1111 DWORD
Add(IUnknown
*pUnk
)
1114 IUnknown
**newArray
;
1118 ATLASSERT(pUnk
!= NULL
);
1121 newSize
= _DEFAULT_VECTORLENGTH
* sizeof(IUnknown
*);
1122 ATLTRY(newArray
= reinterpret_cast<IUnknown
**>(malloc(newSize
)));
1123 if (newArray
== NULL
)
1125 memset(newArray
, 0, newSize
);
1127 m_nSize
= _DEFAULT_VECTORLENGTH
;
1130 for (x
= begin(); x
< end(); x
++)
1139 newSize
= m_nSize
* 2;
1140 newArray
= reinterpret_cast<IUnknown
**>(realloc(m_ppUnk
, newSize
* sizeof(IUnknown
*)));
1141 if (newArray
== NULL
)
1144 memset(&m_ppUnk
[m_nSize
], 0, (newSize
- m_nSize
) * sizeof(IUnknown
*));
1145 curCookie
= m_nSize
+ 1;
1147 m_ppUnk
[curCookie
- 1] = pUnk
;
1151 BOOL
Remove(DWORD dwCookie
)
1155 index
= dwCookie
- 1;
1156 ATLASSERT(index
< dwCookie
&& index
< static_cast<DWORD
>(m_nSize
));
1157 if (index
< dwCookie
&& index
< static_cast<DWORD
>(m_nSize
) && m_ppUnk
[index
] != NULL
)
1159 m_ppUnk
[index
] = NULL
;
1166 CComDynamicUnkArray
&operator = (const CComDynamicUnkArray
&)
1171 CComDynamicUnkArray(const CComDynamicUnkArray
&)
1176 struct _ATL_CONNMAP_ENTRY
1181 template <const IID
*piid
>
1185 STDMETHOD(_LocCPQueryInterface
)(REFIID riid
, void **ppvObject
) = 0;
1186 virtual ULONG STDMETHODCALLTYPE
AddRef() = 0;
1187 virtual ULONG STDMETHODCALLTYPE
Release() = 0;
1190 template<class T
, const IID
*piid
, class CDV
= CComDynamicUnkArray
>
1191 class IConnectionPointImpl
: public _ICPLocator
<piid
>
1193 typedef CComEnum
<IEnumConnections
, &IID_IEnumConnections
, CONNECTDATA
, _Copy
<CONNECTDATA
> > CComEnumConnections
;
1197 ~IConnectionPointImpl()
1201 for (x
= m_vec
.begin(); x
< m_vec
.end(); x
++)
1206 STDMETHOD(_LocCPQueryInterface
)(REFIID riid
, void **ppvObject
)
1208 IConnectionPointImpl
<T
, piid
, CDV
> *pThis
;
1210 pThis
= reinterpret_cast<IConnectionPointImpl
<T
, piid
, CDV
>*>(this);
1212 ATLASSERT(ppvObject
!= NULL
);
1213 if (ppvObject
== NULL
)
1216 if (InlineIsEqualGUID(riid
, IID_IConnectionPoint
) || InlineIsEqualUnknown(riid
))
1225 return E_NOINTERFACE
;
1229 STDMETHOD(GetConnectionInterface
)(IID
*piid2
)
1237 STDMETHOD(GetConnectionPointContainer
)(IConnectionPointContainer
**ppCPC
)
1241 pThis
= static_cast<T
*>(this);
1242 return pThis
->QueryInterface(IID_IConnectionPointContainer
, reinterpret_cast<void **>(ppCPC
));
1245 STDMETHOD(Advise
)(IUnknown
*pUnkSink
, DWORD
*pdwCookie
)
1247 IUnknown
*adviseTarget
;
1251 if (pdwCookie
!= NULL
)
1253 if (pUnkSink
== NULL
|| pdwCookie
== NULL
)
1255 GetConnectionInterface(&interfaceID
); // can't fail
1256 hResult
= pUnkSink
->QueryInterface(interfaceID
, reinterpret_cast<void **>(&adviseTarget
));
1257 if (SUCCEEDED(hResult
))
1259 *pdwCookie
= m_vec
.Add(adviseTarget
);
1260 if (*pdwCookie
!= 0)
1264 adviseTarget
->Release();
1265 hResult
= CONNECT_E_ADVISELIMIT
;
1268 else if (hResult
== E_NOINTERFACE
)
1269 hResult
= CONNECT_E_CANNOTCONNECT
;
1273 STDMETHOD(Unadvise
)(DWORD dwCookie
)
1275 IUnknown
*adviseTarget
;
1278 adviseTarget
= m_vec
.GetUnknown(dwCookie
);
1279 if (m_vec
.Remove(dwCookie
))
1281 if (adviseTarget
!= NULL
)
1282 adviseTarget
->Release();
1286 hResult
= CONNECT_E_NOCONNECTION
;
1290 STDMETHOD(EnumConnections
)(IEnumConnections
**ppEnum
)
1292 CComObject
<CComEnumConnections
> *newEnumerator
;
1293 CONNECTDATA
*itemBuffer
;
1294 CONNECTDATA
*itemBufferEnd
;
1298 ATLASSERT(ppEnum
!= NULL
);
1303 ATLTRY(itemBuffer
= new CONNECTDATA
[m_vec
.end() - m_vec
.begin()])
1304 if (itemBuffer
== NULL
)
1305 return E_OUTOFMEMORY
;
1306 itemBufferEnd
= itemBuffer
;
1307 for (x
= m_vec
.begin(); x
< m_vec
.end(); x
++)
1312 itemBufferEnd
->pUnk
= *x
;
1313 itemBufferEnd
->dwCookie
= m_vec
.GetCookie(x
);
1317 ATLTRY(newEnumerator
= new CComObject
<CComEnumConnections
>)
1318 if (newEnumerator
== NULL
)
1319 return E_OUTOFMEMORY
;
1320 newEnumerator
->Init(itemBuffer
, itemBufferEnd
, NULL
, AtlFlagTakeOwnership
); // can't fail
1321 hResult
= newEnumerator
->_InternalQueryInterface(IID_IEnumConnections
, (void **)ppEnum
);
1322 if (FAILED(hResult
))
1323 delete newEnumerator
;
1329 class IConnectionPointContainerImpl
: public IConnectionPointContainer
1331 typedef const _ATL_CONNMAP_ENTRY
* (*handlerFunctionType
)(int *);
1332 typedef CComEnum
<IEnumConnectionPoints
, &IID_IEnumConnectionPoints
, IConnectionPoint
*, _CopyInterface
<IConnectionPoint
> >
1333 CComEnumConnectionPoints
;
1336 STDMETHOD(EnumConnectionPoints
)(IEnumConnectionPoints
**ppEnum
)
1338 const _ATL_CONNMAP_ENTRY
*entryPtr
;
1339 int connectionPointCount
;
1340 IConnectionPoint
**itemBuffer
;
1342 handlerFunctionType handlerFunction
;
1343 CComEnumConnectionPoints
*newEnumerator
;
1346 ATLASSERT(ppEnum
!= NULL
);
1351 entryPtr
= T::GetConnMap(&connectionPointCount
);
1352 ATLTRY(itemBuffer
= new IConnectionPoint
* [connectionPointCount
])
1353 if (itemBuffer
== NULL
)
1354 return E_OUTOFMEMORY
;
1357 while (entryPtr
->dwOffset
!= static_cast<DWORD_PTR
>(-1))
1359 if (entryPtr
->dwOffset
== static_cast<DWORD_PTR
>(-2))
1362 handlerFunction
= reinterpret_cast<handlerFunctionType
>(entryPtr
->dwOffset
);
1363 entryPtr
= handlerFunction(NULL
);
1367 itemBuffer
[destIndex
++] = reinterpret_cast<IConnectionPoint
*>((char *)this + entryPtr
->dwOffset
);
1372 ATLTRY(newEnumerator
= new CComObject
<CComEnumConnectionPoints
>)
1373 if (newEnumerator
== NULL
)
1375 delete [] itemBuffer
;
1376 return E_OUTOFMEMORY
;
1379 newEnumerator
->Init(&itemBuffer
[0], &itemBuffer
[destIndex
], NULL
, AtlFlagTakeOwnership
); // can't fail
1380 hResult
= newEnumerator
->QueryInterface(IID_IEnumConnectionPoints
, (void**)ppEnum
);
1381 if (FAILED(hResult
))
1382 delete newEnumerator
;
1386 STDMETHOD(FindConnectionPoint
)(REFIID riid
, IConnectionPoint
**ppCP
)
1389 const _ATL_CONNMAP_ENTRY
*entryPtr
;
1390 handlerFunctionType handlerFunction
;
1391 IConnectionPoint
*connectionPoint
;
1397 hResult
= CONNECT_E_NOCONNECTION
;
1398 entryPtr
= T::GetConnMap(NULL
);
1399 while (entryPtr
->dwOffset
!= static_cast<DWORD_PTR
>(-1))
1401 if (entryPtr
->dwOffset
== static_cast<DWORD_PTR
>(-2))
1404 handlerFunction
= reinterpret_cast<handlerFunctionType
>(entryPtr
->dwOffset
);
1405 entryPtr
= handlerFunction(NULL
);
1409 connectionPoint
= reinterpret_cast<IConnectionPoint
*>(reinterpret_cast<char *>(this) + entryPtr
->dwOffset
);
1410 if (SUCCEEDED(connectionPoint
->GetConnectionInterface(&interfaceID
)) && InlineIsEqualGUID(riid
, interfaceID
))
1412 *ppCP
= connectionPoint
;
1413 connectionPoint
->AddRef();
1424 #define BEGIN_CONNECTION_POINT_MAP(x) \
1425 typedef x _atl_conn_classtype; \
1426 static const ATL::_ATL_CONNMAP_ENTRY *GetConnMap(int *pnEntries) { \
1427 static const ATL::_ATL_CONNMAP_ENTRY _entries[] = {
1429 #define END_CONNECTION_POINT_MAP() \
1430 {(DWORD_PTR)-1} }; \
1432 *pnEntries = sizeof(_entries) / sizeof(ATL::_ATL_CONNMAP_ENTRY) - 1; \
1435 #define CONNECTION_POINT_ENTRY(iid) \
1436 {offsetofclass(ATL::_ICPLocator<&iid>, _atl_conn_classtype) - \
1437 offsetofclass(ATL::IConnectionPointContainerImpl<_atl_conn_classtype>, _atl_conn_classtype)},
1442 - IDispatchImpl contains a static member of type CComTypeInfoHolder that manages the type information for the dual interface.
1443 If you have multiple objects that implement the same dual interface, only one instance of CComTypeInfoHolder is used.
1444 - By default, the IDispatchImpl class looks up the type information for T in the registry.
1445 To implement an unregistered interface, you can use the IDispatchImpl class without accessing the registry by using a predefined version number.
1446 If you create an IDispatchImpl object that has 0xFFFF as the value for wMajor and 0xFFFF as the value for wMinor,
1447 the IDispatchImpl class retrieves the type library from the .dll file instead of the registry.
1449 template<class T
, const IID
* piid
/*= &__uuidof(T)*/, const GUID
* plibid
= &CAtlModule::m_libid
, WORD wMajor
= 1, WORD wMinor
= 0>
1450 class IDispatchImpl
:
1454 CComPtr
<ITypeInfo
> m_pTypeInfo
;
1456 STDMETHOD(EnsureTILoaded
)(LCID lcid
)
1459 if (m_pTypeInfo
!= NULL
)
1462 if (IsEqualCLSID(CLSID_NULL
, *plibid
))
1463 OutputDebugStringA("IDispatchImpl: plibid is CLSID_NULL!\r\n");
1465 // Should we assert here?
1466 if (wMajor
== 0xffff && wMinor
== 0xffff)
1467 OutputDebugStringA("IDispatchImpl: not fully implemented, missing functionality to load TLB from file!\r\n");
1469 CComPtr
<ITypeLib
> spTypeLib
;
1470 hr
= LoadRegTypeLib(*plibid
, wMajor
, wMinor
, lcid
, &spTypeLib
);
1473 hr
= spTypeLib
->GetTypeInfoOfGuid(*piid
, &m_pTypeInfo
);
1484 // *** IDispatch methods ***
1485 STDMETHOD(GetTypeInfoCount
)(UINT
*pctinfo
)
1487 if (pctinfo
== NULL
)
1494 STDMETHOD(GetTypeInfo
)(UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
1497 return DISP_E_BADINDEX
;
1498 if (ppTInfo
== NULL
)
1501 HRESULT hr
= EnsureTILoaded(lcid
);
1502 *ppTInfo
= m_pTypeInfo
;
1504 (*ppTInfo
)->AddRef();
1509 STDMETHOD(GetIDsOfNames
)(REFIID
/*riid*/, LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
1511 HRESULT hr
= EnsureTILoaded(lcid
);
1513 hr
= m_pTypeInfo
->GetIDsOfNames(rgszNames
, cNames
, rgDispId
);
1517 STDMETHOD(Invoke
)(DISPID dispIdMember
, REFIID
/*riid*/, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1519 HRESULT hr
= EnsureTILoaded(lcid
);
1521 hr
= m_pTypeInfo
->Invoke(this, dispIdMember
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);