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