Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1051 lines
28 KiB

  1. // This is a part of the Active Template Library.
  2. // Copyright (C) 1996-2001 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Active Template Library Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Active Template Library product.
  10. #ifndef __ATLCOM_H__
  11. #define __ATLCOM_H__
  12. #pragma once
  13. #ifndef _ATL_NO_PRAGMA_WARNINGS
  14. #pragma warning (push)
  15. #pragma warning(disable: 4702) // unreachable code
  16. #pragma warning(disable: 4355) // 'this' used in initializer list
  17. #pragma warning(disable: 4511) // copy constructor could not be generated
  18. #pragma warning(disable: 4512) // assignment operator could not be generated
  19. #endif //!_ATL_NO_PRAGMA_WARNINGS
  20. #ifndef __cplusplus
  21. #error ATL requires C++ compilation (use a .cpp suffix)
  22. #endif
  23. #ifndef __ATLBASE_H__
  24. #error atlcom.h requires atlbase.h to be included first
  25. #endif
  26. //REVIEW: Just to fix VSEE
  27. #pragma push_macro("min")
  28. #pragma push_macro("max")
  29. #undef min
  30. #undef max
  31. #define min(a,b) (((a) < (b)) ? (a) : (b))
  32. #define max(a,b) (((a) > (b)) ? (a) : (b))
  33. #pragma pack(push, _ATL_PACKING)
  34. EXTERN_C const IID IID_ITargetFrame;
  35. #include <atlbase.inl>
  36. #include <limits.h>
  37. namespace ATL
  38. {
  39. #define _ATLDUMPIID(iid, name, hr) hr
  40. /////////////////////////////////////////////////////////////////////////////
  41. // AtlReportError
  42. inline HRESULT WINAPI AtlReportError(const CLSID& clsid, UINT nID, const IID& iid = GUID_NULL,
  43. HRESULT hRes = 0, HINSTANCE hInst = _AtlBaseModule.GetResourceInstance())
  44. {
  45. return AtlSetErrorInfo(clsid, (LPCOLESTR)MAKEINTRESOURCE(nID), 0, NULL, iid, hRes, hInst);
  46. }
  47. inline HRESULT WINAPI AtlReportError(const CLSID& clsid, UINT nID, DWORD dwHelpID,
  48. LPCOLESTR lpszHelpFile, const IID& iid = GUID_NULL, HRESULT hRes = 0,
  49. HINSTANCE hInst = _AtlBaseModule.GetResourceInstance())
  50. {
  51. return AtlSetErrorInfo(clsid, (LPCOLESTR)MAKEINTRESOURCE(nID), dwHelpID,
  52. lpszHelpFile, iid, hRes, hInst);
  53. }
  54. inline HRESULT WINAPI AtlReportError(const CLSID& clsid, LPCOLESTR lpszDesc,
  55. const IID& iid = GUID_NULL, HRESULT hRes = 0)
  56. {
  57. return AtlSetErrorInfo(clsid, lpszDesc, 0, NULL, iid, hRes, NULL);
  58. }
  59. inline HRESULT WINAPI AtlReportError(const CLSID& clsid, LPCOLESTR lpszDesc, DWORD dwHelpID,
  60. LPCOLESTR lpszHelpFile, const IID& iid = GUID_NULL, HRESULT hRes = 0)
  61. {
  62. return AtlSetErrorInfo(clsid, lpszDesc, dwHelpID, lpszHelpFile, iid, hRes, NULL);
  63. }
  64. /////////////////////////////////////////////////////////////////////////////
  65. // COM Objects
  66. #define DECLARE_PROTECT_FINAL_CONSTRUCT()\
  67. void InternalFinalConstructAddRef() {InternalAddRef();}\
  68. void InternalFinalConstructRelease() {InternalRelease();}
  69. template <class T1>
  70. class CComCreator
  71. {
  72. public:
  73. static HRESULT WINAPI CreateInstance(void* pv, REFIID riid, LPVOID* ppv)
  74. {
  75. ATLASSERT(ppv != NULL);
  76. if (ppv == NULL)
  77. return E_POINTER;
  78. *ppv = NULL;
  79. HRESULT hRes = E_OUTOFMEMORY;
  80. T1* p = NULL;
  81. ATLTRY(p = new T1(pv))
  82. if (p != NULL)
  83. {
  84. p->SetVoid(pv);
  85. p->InternalFinalConstructAddRef();
  86. hRes = p->FinalConstruct();
  87. if (SUCCEEDED(hRes))
  88. hRes = p->_AtlFinalConstruct();
  89. p->InternalFinalConstructRelease();
  90. if (hRes == S_OK)
  91. hRes = p->QueryInterface(riid, ppv);
  92. if (hRes != S_OK)
  93. delete p;
  94. }
  95. return hRes;
  96. }
  97. };
  98. template <HRESULT hr>
  99. class CComFailCreator
  100. {
  101. public:
  102. static HRESULT WINAPI CreateInstance(void*, REFIID, LPVOID* ppv)
  103. {
  104. if (ppv == NULL)
  105. return E_POINTER;
  106. *ppv = NULL;
  107. return hr;
  108. }
  109. };
  110. template <class T1, class T2>
  111. class CComCreator2
  112. {
  113. public:
  114. static HRESULT WINAPI CreateInstance(void* pv, REFIID riid, LPVOID* ppv)
  115. {
  116. ATLASSERT(ppv != NULL);
  117. return (pv == NULL) ?
  118. T1::CreateInstance(NULL, riid, ppv) :
  119. T2::CreateInstance(pv, riid, ppv);
  120. }
  121. };
  122. #define DECLARE_NOT_AGGREGATABLE(x) public:\
  123. typedef ATL::CComCreator2< ATL::CComCreator< ATL::CComObject< x > >, ATL::CComFailCreator<CLASS_E_NOAGGREGATION> > _CreatorClass;
  124. #define DECLARE_AGGREGATABLE(x) public:\
  125. typedef ATL::CComCreator2< ATL::CComCreator< ATL::CComObject< x > >, ATL::CComCreator< ATL::CComAggObject< x > > > _CreatorClass;
  126. struct _ATL_CREATORDATA
  127. {
  128. _ATL_CREATORFUNC* pFunc;
  129. };
  130. template <class Creator>
  131. class _CComCreatorData
  132. {
  133. public:
  134. static _ATL_CREATORDATA data;
  135. };
  136. template <class Creator>
  137. _ATL_CREATORDATA _CComCreatorData<Creator>::data = {Creator::CreateInstance};
  138. struct _ATL_CACHEDATA
  139. {
  140. DWORD dwOffsetVar;
  141. _ATL_CREATORFUNC* pFunc;
  142. };
  143. template <class Creator, DWORD dwVar>
  144. class _CComCacheData
  145. {
  146. public:
  147. static _ATL_CACHEDATA data;
  148. };
  149. template <class Creator, DWORD dwVar>
  150. _ATL_CACHEDATA _CComCacheData<Creator, dwVar>::data = {dwVar, Creator::CreateInstance};
  151. struct _ATL_CHAINDATA
  152. {
  153. DWORD_PTR dwOffset;
  154. const _ATL_INTMAP_ENTRY* (WINAPI *pFunc)();
  155. };
  156. template <class base, class derived>
  157. class _CComChainData
  158. {
  159. public:
  160. static _ATL_CHAINDATA data;
  161. };
  162. template <class base, class derived>
  163. _ATL_CHAINDATA _CComChainData<base, derived>::data =
  164. {offsetofclass(base, derived), base::_GetEntries};
  165. #ifdef _ATL_DEBUG
  166. #define DEBUG_QI_ENTRY(x) \
  167. {NULL, \
  168. (DWORD_PTR)_T(#x), \
  169. (ATL::_ATL_CREATORARGFUNC*)0},
  170. #else
  171. #define DEBUG_QI_ENTRY(x)
  172. #endif //_ATL_DEBUG
  173. #define _ATL_DECLARE_GET_UNKNOWN(x) IUnknown* GetUnknown() throw() {return _GetRawUnknown();}
  174. //If you get a message that FinalConstruct is ambiguous then you need to
  175. // override it in your class and call each base class' version of this
  176. #define BEGIN_COM_MAP(x) public: \
  177. typedef x _ComMapClass; \
  178. static HRESULT WINAPI _Cache(void* pv, REFIID iid, void** ppvObject, DWORD_PTR dw) throw()\
  179. {\
  180. _ComMapClass* p = (_ComMapClass*)pv;\
  181. p->Lock();\
  182. HRESULT hRes = ATL::CComObjectRootBase::_Cache(pv, iid, ppvObject, dw);\
  183. p->Unlock();\
  184. return hRes;\
  185. }\
  186. IUnknown* _GetRawUnknown() throw() \
  187. { ATLASSERT(_GetEntries()[0].pFunc == _ATL_SIMPLEMAPENTRY); return (IUnknown*)((INT_PTR)this+_GetEntries()->dw); } \
  188. _ATL_DECLARE_GET_UNKNOWN(x)\
  189. HRESULT _InternalQueryInterface(REFIID iid, void** ppvObject) throw() \
  190. { return InternalQueryInterface(this, _GetEntries(), iid, ppvObject); } \
  191. const static ATL::_ATL_INTMAP_ENTRY* WINAPI _GetEntries() throw() { \
  192. static const ATL::_ATL_INTMAP_ENTRY _entries[] = { DEBUG_QI_ENTRY(x)
  193. #define DECLARE_GET_CONTROLLING_UNKNOWN() public:\
  194. virtual IUnknown* GetControllingUnknown() throw() {return GetUnknown();}
  195. #define COM_INTERFACE_ENTRY(x)\
  196. {&_ATL_IIDOF(x), \
  197. offsetofclass(x, _ComMapClass), \
  198. _ATL_SIMPLEMAPENTRY},
  199. #define COM_INTERFACE_ENTRY2(x, x2)\
  200. {&_ATL_IIDOF(x),\
  201. reinterpret_cast<DWORD_PTR>(static_cast<x*>(static_cast<x2*>(reinterpret_cast<_ComMapClass*>(8))))-8,\
  202. _ATL_SIMPLEMAPENTRY},
  203. #define COM_INTERFACE_ENTRY_AGGREGATE(iid, punk)\
  204. {&iid,\
  205. (DWORD_PTR)offsetof(_ComMapClass, punk),\
  206. _Delegate},
  207. #ifdef _ATL_DEBUG
  208. #define END_COM_MAP() \
  209. __if_exists(_GetAttrEntries) {{NULL, (DWORD_PTR)_GetAttrEntries, _ChainAttr }, }\
  210. {NULL, 0, 0}}; return &_entries[1];} \
  211. virtual ULONG STDMETHODCALLTYPE AddRef( void) throw() = 0; \
  212. virtual ULONG STDMETHODCALLTYPE Release( void) throw() = 0; \
  213. STDMETHOD(QueryInterface)(REFIID, void**) throw() = 0;
  214. #else
  215. #define END_COM_MAP() \
  216. __if_exists(_GetAttrEntries) {{NULL, (DWORD_PTR)_GetAttrEntries, _ChainAttr }, }\
  217. {NULL, 0, 0}}; return _entries;} \
  218. virtual ULONG STDMETHODCALLTYPE AddRef( void) throw() = 0; \
  219. virtual ULONG STDMETHODCALLTYPE Release( void) throw() = 0; \
  220. STDMETHOD(QueryInterface)(REFIID, void**) throw() = 0;
  221. #endif // _ATL_DEBUG
  222. #define BEGIN_OBJECT_MAP(x) static ATL::_ATL_OBJMAP_ENTRY x[] = {
  223. #define END_OBJECT_MAP() {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}};
  224. #define OBJECT_ENTRY(clsid, class) {&clsid, class::UpdateRegistry, class::_ClassFactoryCreatorClass::CreateInstance, class::_CreatorClass::CreateInstance, NULL, 0, class::GetObjectDescription, class::GetCategoryMap, class::ObjectMain },
  225. #ifndef OBJECT_ENTRY_PRAGMA
  226. #if defined(_M_IX86)
  227. #define OBJECT_ENTRY_PRAGMA(class) __pragma(comment(linker, "/include:___pobjMap_" #class))
  228. #elif defined(_M_AMD64) || defined(_M_IA64)
  229. #define OBJECT_ENTRY_PRAGMA(class) __pragma(comment(linker, "/include:__pobjMap_" #class))
  230. #else
  231. #error Unknown Platform. define OBJECT_ENTRY_PRAGMA
  232. #endif
  233. #endif //OBJECT_ENTRY_PRAGMA
  234. // the functions in this class don't need to be virtual because
  235. // they are called from CComObject
  236. class CComObjectRootBase
  237. {
  238. public:
  239. CComObjectRootBase()
  240. {
  241. m_dwRef = 0L;
  242. }
  243. HRESULT FinalConstruct()
  244. {
  245. return S_OK;
  246. }
  247. // For library initialization only
  248. HRESULT _AtlFinalConstruct()
  249. {
  250. return S_OK;
  251. }
  252. void FinalRelease() {}
  253. //ObjectMain is called during Module::Init and Module::Term
  254. static void WINAPI ObjectMain(bool /* bStarting */) {}
  255. static const struct _ATL_CATMAP_ENTRY* GetCategoryMap() {return NULL;};
  256. static HRESULT WINAPI InternalQueryInterface(void* pThis,
  257. const _ATL_INTMAP_ENTRY* pEntries, REFIID iid, void** ppvObject)
  258. {
  259. // Only Assert here. AtlInternalQueryInterface will return the correct HRESULT if ppvObject == NULL
  260. #ifndef _ATL_OLEDB_CONFORMANCE_TESTS
  261. ATLASSERT(ppvObject != NULL);
  262. #endif
  263. ATLASSERT(pThis != NULL);
  264. // First entry in the com map should be a simple map entry
  265. ATLASSERT(pEntries->pFunc == _ATL_SIMPLEMAPENTRY);
  266. HRESULT hRes = AtlInternalQueryInterface(pThis, pEntries, iid, ppvObject);
  267. return _ATLDUMPIID(iid, pszClassName, hRes);
  268. }
  269. //Outer funcs
  270. ULONG OuterAddRef()
  271. {
  272. return m_pOuterUnknown->AddRef();
  273. }
  274. ULONG OuterRelease()
  275. {
  276. return m_pOuterUnknown->Release();
  277. }
  278. HRESULT OuterQueryInterface(REFIID iid, void ** ppvObject)
  279. {
  280. return m_pOuterUnknown->QueryInterface(iid, ppvObject);
  281. }
  282. void SetVoid(void*) {}
  283. void InternalFinalConstructAddRef() {}
  284. void InternalFinalConstructRelease()
  285. {
  286. ATLASSERT(m_dwRef == 0);
  287. }
  288. // If this assert occurs, your object has probably been deleted
  289. // Try using DECLARE_PROTECT_FINAL_CONSTRUCT()
  290. static HRESULT WINAPI _Delegate(void* pv, REFIID iid, void** ppvObject, DWORD_PTR dw)
  291. {
  292. HRESULT hRes = E_NOINTERFACE;
  293. IUnknown* p = *(IUnknown**)((DWORD_PTR)pv + dw);
  294. if (p != NULL)
  295. hRes = p->QueryInterface(iid, ppvObject);
  296. return hRes;
  297. }
  298. static HRESULT WINAPI _ChainAttr(void* pv, REFIID iid, void** ppvObject, DWORD_PTR dw)
  299. {
  300. const _ATL_INTMAP_ENTRY* (WINAPI *pFunc)() = (const _ATL_INTMAP_ENTRY* (WINAPI *)())dw;
  301. const _ATL_INTMAP_ENTRY *pEntries = pFunc();
  302. if (pEntries == NULL)
  303. return S_OK;
  304. return InternalQueryInterface(pv, pEntries, iid, ppvObject);
  305. }
  306. static HRESULT WINAPI _Cache(void* pv, REFIID iid, void** ppvObject, DWORD_PTR dw)
  307. {
  308. HRESULT hRes = E_NOINTERFACE;
  309. _ATL_CACHEDATA* pcd = (_ATL_CACHEDATA*)dw;
  310. IUnknown** pp = (IUnknown**)((DWORD_PTR)pv + pcd->dwOffsetVar);
  311. if (*pp == NULL)
  312. hRes = pcd->pFunc(pv, __uuidof(IUnknown), (void**)pp);
  313. if (*pp != NULL)
  314. hRes = (*pp)->QueryInterface(iid, ppvObject);
  315. return hRes;
  316. }
  317. union
  318. {
  319. long m_dwRef;
  320. IUnknown* m_pOuterUnknown;
  321. };
  322. };
  323. template <class ThreadModel>
  324. class CComObjectRootEx : public CComObjectRootBase
  325. {
  326. public:
  327. typedef ThreadModel _ThreadModel;
  328. typedef typename _ThreadModel::AutoCriticalSection _CritSec;
  329. ULONG InternalAddRef()
  330. {
  331. ATLASSERT(m_dwRef != -1L);
  332. return _ThreadModel::Increment(&m_dwRef);
  333. }
  334. ULONG InternalRelease()
  335. {
  336. #ifdef _DEBUG
  337. LONG nRef = _ThreadModel::Decrement(&m_dwRef);
  338. if (nRef < -(LONG_MAX / 2))
  339. {
  340. ATLASSERT(0 && _T("Release called on a pointer that has already been released"));
  341. }
  342. return nRef;
  343. #else
  344. return _ThreadModel::Decrement(&m_dwRef);
  345. #endif
  346. }
  347. void Lock() {m_critsec.Lock();}
  348. void Unlock() {m_critsec.Unlock();}
  349. private:
  350. _CritSec m_critsec;
  351. };
  352. // don't let class factory refcount influence lock count
  353. #define DECLARE_CLASSFACTORY_EX(cf) typedef ATL::CComCreator< ATL::CComObjectNoLock< cf > > _ClassFactoryCreatorClass;
  354. #define DECLARE_CLASSFACTORY() DECLARE_CLASSFACTORY_EX(ATL::CComClassFactory)
  355. #define DECLARE_REGISTRY_RESOURCEID(x)\
  356. static HRESULT WINAPI UpdateRegistry(BOOL bRegister) throw()\
  357. {\
  358. __if_exists(_GetMiscStatus) \
  359. { \
  360. ATL::_ATL_REGMAP_ENTRY regMapEntries[2]; \
  361. memset(&regMapEntries[1], 0, sizeof(ATL::_ATL_REGMAP_ENTRY)); \
  362. regMapEntries[0].szKey = L"OLEMISC"; \
  363. TCHAR szOleMisc[10]; \
  364. wsprintf(szOleMisc, _T("%d"), _GetMiscStatus()); \
  365. USES_CONVERSION; \
  366. regMapEntries[0].szData = szOleMisc; \
  367. __if_exists(_Module) \
  368. { \
  369. return _Module.UpdateRegistryFromResource(x, bRegister, regMapEntries); \
  370. } \
  371. __if_not_exists(_Module) \
  372. { \
  373. return ATL::_pAtlModule->UpdateRegistryFromResource(x, bRegister, regMapEntries); \
  374. } \
  375. } \
  376. __if_not_exists(_GetMiscStatus) \
  377. { \
  378. __if_exists(_Module) \
  379. { \
  380. return _Module.UpdateRegistryFromResource(x, bRegister); \
  381. } \
  382. __if_not_exists(_Module) \
  383. { \
  384. return ATL::_pAtlModule->UpdateRegistryFromResource(x, bRegister); \
  385. } \
  386. } \
  387. }
  388. //Base is the user's class that derives from CComObjectRoot and whatever
  389. //interfaces the user wants to support on the object
  390. template <class Base>
  391. class CComObject : public Base
  392. {
  393. public:
  394. typedef Base _BaseClass;
  395. CComObject(void* = NULL) throw()
  396. {
  397. _pAtlModule->Lock();
  398. }
  399. // Set refcount to -(LONG_MAX/2) to protect destruction and
  400. // also catch mismatched Release in debug builds
  401. ~CComObject() throw()
  402. {
  403. m_dwRef = -(LONG_MAX/2);
  404. FinalRelease();
  405. _pAtlModule->Unlock();
  406. }
  407. //If InternalAddRef or InternalRelease is undefined then your class
  408. //doesn't derive from CComObjectRoot
  409. STDMETHOD_(ULONG, AddRef)() throw() {return InternalAddRef();}
  410. STDMETHOD_(ULONG, Release)() throw()
  411. {
  412. ULONG l = InternalRelease();
  413. if (l == 0)
  414. delete this;
  415. return l;
  416. }
  417. //if _InternalQueryInterface is undefined then you forgot BEGIN_COM_MAP
  418. STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject) throw()
  419. {return _InternalQueryInterface(iid, ppvObject);}
  420. template <class Q>
  421. HRESULT STDMETHODCALLTYPE QueryInterface(Q** pp) throw()
  422. {
  423. return QueryInterface(__uuidof(Q), (void**)pp);
  424. }
  425. static HRESULT WINAPI CreateInstance(CComObject<Base>** pp) throw();
  426. };
  427. template <class Base>
  428. HRESULT WINAPI CComObject<Base>::CreateInstance(CComObject<Base>** pp) throw()
  429. {
  430. ATLASSERT(pp != NULL);
  431. if (pp == NULL)
  432. return E_POINTER;
  433. *pp = NULL;
  434. HRESULT hRes = E_OUTOFMEMORY;
  435. CComObject<Base>* p = NULL;
  436. ATLTRY(p = new CComObject<Base>())
  437. if (p != NULL)
  438. {
  439. p->SetVoid(NULL);
  440. p->InternalFinalConstructAddRef();
  441. hRes = p->FinalConstruct();
  442. if (SUCCEEDED(hRes))
  443. hRes = p->_AtlFinalConstruct();
  444. p->InternalFinalConstructRelease();
  445. if (hRes != S_OK)
  446. {
  447. delete p;
  448. p = NULL;
  449. }
  450. }
  451. *pp = p;
  452. return hRes;
  453. }
  454. //Base is the user's class that derives from CComObjectRoot and whatever
  455. //interfaces the user wants to support on the object
  456. template <class Base>
  457. class CComObjectNoLock : public Base
  458. {
  459. public:
  460. typedef Base _BaseClass;
  461. CComObjectNoLock(void* = NULL){}
  462. // Set refcount to -(LONG_MAX/2) to protect destruction and
  463. // also catch mismatched Release in debug builds
  464. ~CComObjectNoLock()
  465. {
  466. m_dwRef = -(LONG_MAX/2);
  467. FinalRelease();
  468. }
  469. //If InternalAddRef or InternalRelease is undefined then your class
  470. //doesn't derive from CComObjectRoot
  471. STDMETHOD_(ULONG, AddRef)() {return InternalAddRef();}
  472. STDMETHOD_(ULONG, Release)()
  473. {
  474. ULONG l = InternalRelease();
  475. if (l == 0)
  476. delete this;
  477. return l;
  478. }
  479. //if _InternalQueryInterface is undefined then you forgot BEGIN_COM_MAP
  480. STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject)
  481. {return _InternalQueryInterface(iid, ppvObject);}
  482. };
  483. template <class Base> //Base must be derived from CComObjectRoot
  484. class CComContainedObject : public Base
  485. {
  486. public:
  487. typedef Base _BaseClass;
  488. CComContainedObject(void* pv) {m_pOuterUnknown = (IUnknown*)pv;}
  489. STDMETHOD_(ULONG, AddRef)() {return OuterAddRef();}
  490. STDMETHOD_(ULONG, Release)() {return OuterRelease();}
  491. STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject)
  492. {
  493. return OuterQueryInterface(iid, ppvObject);
  494. }
  495. template <class Q>
  496. HRESULT STDMETHODCALLTYPE QueryInterface(Q** pp)
  497. {
  498. return QueryInterface(__uuidof(Q), (void**)pp);
  499. }
  500. //GetControllingUnknown may be virtual if the Base class has declared
  501. //DECLARE_GET_CONTROLLING_UNKNOWN()
  502. IUnknown* GetControllingUnknown()
  503. {
  504. return m_pOuterUnknown;
  505. }
  506. };
  507. //contained is the user's class that derives from CComObjectRoot and whatever
  508. //interfaces the user wants to support on the object
  509. template <class contained>
  510. class CComAggObject :
  511. public IUnknown,
  512. public CComObjectRootEx< typename contained::_ThreadModel::ThreadModelNoCS >
  513. {
  514. public:
  515. typedef contained _BaseClass;
  516. CComAggObject(void* pv) : m_contained(pv)
  517. {
  518. _pAtlModule->Lock();
  519. }
  520. //If you get a message that this call is ambiguous then you need to
  521. // override it in your class and call each base class' version of this
  522. HRESULT FinalConstruct()
  523. {
  524. CComObjectRootEx<contained::_ThreadModel::ThreadModelNoCS>::FinalConstruct();
  525. return m_contained.FinalConstruct();
  526. }
  527. void FinalRelease()
  528. {
  529. CComObjectRootEx<contained::_ThreadModel::ThreadModelNoCS>::FinalRelease();
  530. m_contained.FinalRelease();
  531. }
  532. // Set refcount to -(LONG_MAX/2) to protect destruction and
  533. // also catch mismatched Release in debug builds
  534. ~CComAggObject()
  535. {
  536. m_dwRef = -(LONG_MAX/2);
  537. FinalRelease();
  538. _pAtlModule->Unlock();
  539. }
  540. STDMETHOD_(ULONG, AddRef)() {return InternalAddRef();}
  541. STDMETHOD_(ULONG, Release)()
  542. {
  543. ULONG l = InternalRelease();
  544. if (l == 0)
  545. delete this;
  546. return l;
  547. }
  548. STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject)
  549. {
  550. ATLASSERT(ppvObject != NULL);
  551. if (ppvObject == NULL)
  552. return E_POINTER;
  553. *ppvObject = NULL;
  554. HRESULT hRes = S_OK;
  555. if (InlineIsEqualUnknown(iid))
  556. {
  557. *ppvObject = (void*)(IUnknown*)this;
  558. AddRef();
  559. }
  560. else
  561. hRes = m_contained._InternalQueryInterface(iid, ppvObject);
  562. return hRes;
  563. }
  564. template <class Q>
  565. HRESULT STDMETHODCALLTYPE QueryInterface(Q** pp)
  566. {
  567. return QueryInterface(__uuidof(Q), (void**)pp);
  568. }
  569. static HRESULT WINAPI CreateInstance(LPUNKNOWN pUnkOuter, CComAggObject<contained>** pp)
  570. {
  571. ATLASSERT(pp != NULL);
  572. HRESULT hRes = E_OUTOFMEMORY;
  573. CComAggObject<contained>* p = NULL;
  574. ATLTRY(p = new CComAggObject<contained>(pUnkOuter))
  575. if (p != NULL)
  576. {
  577. p->SetVoid(NULL);
  578. p->InternalFinalConstructAddRef();
  579. hRes = p->FinalConstruct();
  580. if (SUCCEEDED(hRes))
  581. hRes = p->_AtlFinalConstruct();
  582. p->InternalFinalConstructRelease();
  583. if (hRes != S_OK)
  584. {
  585. delete p;
  586. p = NULL;
  587. }
  588. }
  589. *pp = p;
  590. return hRes;
  591. }
  592. CComContainedObject<contained> m_contained;
  593. };
  594. class CComClassFactory :
  595. public IClassFactory,
  596. public CComObjectRootEx<CComGlobalsThreadModel>
  597. {
  598. public:
  599. BEGIN_COM_MAP(CComClassFactory)
  600. COM_INTERFACE_ENTRY(IClassFactory)
  601. END_COM_MAP()
  602. // IClassFactory
  603. STDMETHOD(CreateInstance)(LPUNKNOWN pUnkOuter, REFIID riid, void** ppvObj)
  604. {
  605. ATLASSERT(m_pfnCreateInstance != NULL);
  606. HRESULT hRes = E_POINTER;
  607. if (ppvObj != NULL)
  608. {
  609. *ppvObj = NULL;
  610. // can't ask for anything other than IUnknown when aggregating
  611. if ((pUnkOuter != NULL) && !InlineIsEqualUnknown(riid))
  612. {
  613. hRes = CLASS_E_NOAGGREGATION;
  614. }
  615. else
  616. hRes = m_pfnCreateInstance(pUnkOuter, riid, ppvObj);
  617. }
  618. return hRes;
  619. }
  620. STDMETHOD(LockServer)(BOOL fLock)
  621. {
  622. if (fLock)
  623. _pAtlModule->Lock();
  624. else
  625. _pAtlModule->Unlock();
  626. return S_OK;
  627. }
  628. // helper
  629. void SetVoid(void* pv)
  630. {
  631. m_pfnCreateInstance = (_ATL_CREATORFUNC*)pv;
  632. }
  633. _ATL_CREATORFUNC* m_pfnCreateInstance;
  634. };
  635. template <class T, const CLSID* pclsid = &CLSID_NULL>
  636. class CComCoClass
  637. {
  638. public:
  639. DECLARE_CLASSFACTORY()
  640. DECLARE_AGGREGATABLE(T)
  641. typedef T _CoClass;
  642. static const CLSID& WINAPI GetObjectCLSID() {return *pclsid;}
  643. static LPCTSTR WINAPI GetObjectDescription() {return NULL;}
  644. static HRESULT WINAPI Error(LPCOLESTR lpszDesc,
  645. const IID& iid = GUID_NULL, HRESULT hRes = 0)
  646. {
  647. return AtlReportError(GetObjectCLSID(), lpszDesc, iid, hRes);
  648. }
  649. static HRESULT WINAPI Error(LPCOLESTR lpszDesc, DWORD dwHelpID,
  650. LPCOLESTR lpszHelpFile, const IID& iid = GUID_NULL, HRESULT hRes = 0)
  651. {
  652. return AtlReportError(GetObjectCLSID(), lpszDesc, dwHelpID, lpszHelpFile,
  653. iid, hRes);
  654. }
  655. static HRESULT WINAPI Error(UINT nID, const IID& iid = GUID_NULL,
  656. HRESULT hRes = 0, HINSTANCE hInst = _AtlBaseModule.GetResourceInstance())
  657. {
  658. return AtlReportError(GetObjectCLSID(), nID, iid, hRes, hInst);
  659. }
  660. static HRESULT WINAPI Error(UINT nID, DWORD dwHelpID,
  661. LPCOLESTR lpszHelpFile, const IID& iid = GUID_NULL,
  662. HRESULT hRes = 0, HINSTANCE hInst = _AtlBaseModule.GetResourceInstance())
  663. {
  664. return AtlReportError(GetObjectCLSID(), nID, dwHelpID, lpszHelpFile,
  665. iid, hRes, hInst);
  666. }
  667. static HRESULT WINAPI Error(LPCSTR lpszDesc,
  668. const IID& iid = GUID_NULL, HRESULT hRes = 0)
  669. {
  670. return AtlReportError(GetObjectCLSID(), lpszDesc, iid, hRes);
  671. }
  672. static HRESULT WINAPI Error(LPCSTR lpszDesc, DWORD dwHelpID,
  673. LPCSTR lpszHelpFile, const IID& iid = GUID_NULL, HRESULT hRes = 0)
  674. {
  675. return AtlReportError(GetObjectCLSID(), lpszDesc, dwHelpID,
  676. lpszHelpFile, iid, hRes);
  677. }
  678. template <class Q>
  679. static HRESULT CreateInstance(IUnknown* punkOuter, Q** pp)
  680. {
  681. return T::_CreatorClass::CreateInstance(punkOuter, __uuidof(Q), (void**) pp);
  682. }
  683. template <class Q>
  684. static HRESULT CreateInstance(Q** pp)
  685. {
  686. return T::_CreatorClass::CreateInstance(NULL, __uuidof(Q), (void**) pp);
  687. }
  688. };
  689. // ATL doesn't support multiple LCID's at the same time
  690. // Whatever LCID is queried for first is the one that is used.
  691. class CComTypeInfoHolder
  692. {
  693. // Should be 'protected' but can cause compiler to generate fat code.
  694. public:
  695. const GUID* m_pguid;
  696. const GUID* m_plibid;
  697. WORD m_wMajor;
  698. WORD m_wMinor;
  699. ITypeInfo* m_pInfo;
  700. long m_dwRef;
  701. struct stringdispid
  702. {
  703. CComBSTR bstr;
  704. int nLen;
  705. DISPID id;
  706. };
  707. stringdispid* m_pMap;
  708. int m_nCount;
  709. public:
  710. HRESULT GetTI(LCID lcid, ITypeInfo** ppInfo)
  711. {
  712. ATLASSERT(ppInfo != NULL);
  713. if (ppInfo == NULL)
  714. return E_POINTER;
  715. HRESULT hr = S_OK;
  716. if (m_pInfo == NULL)
  717. hr = GetTI(lcid);
  718. *ppInfo = m_pInfo;
  719. if (m_pInfo != NULL)
  720. {
  721. m_pInfo->AddRef();
  722. hr = S_OK;
  723. }
  724. return hr;
  725. }
  726. HRESULT GetTI(LCID lcid);
  727. HRESULT EnsureTI(LCID lcid)
  728. {
  729. HRESULT hr = S_OK;
  730. if (m_pInfo == NULL || m_pMap == NULL)
  731. hr = GetTI(lcid);
  732. return hr;
  733. }
  734. // This function is called by the module on exit
  735. // It is registered through _pAtlModule->AddTermFunc()
  736. static void __stdcall Cleanup(DWORD_PTR dw)
  737. {
  738. CComTypeInfoHolder* p = (CComTypeInfoHolder*) dw;
  739. if (p->m_pInfo != NULL)
  740. p->m_pInfo->Release();
  741. p->m_pInfo = NULL;
  742. delete [] p->m_pMap;
  743. p->m_pMap = NULL;
  744. }
  745. HRESULT GetTypeInfo(UINT /* itinfo */, LCID lcid, ITypeInfo** pptinfo)
  746. {
  747. HRESULT hRes = E_POINTER;
  748. if (pptinfo != NULL)
  749. hRes = GetTI(lcid, pptinfo);
  750. return hRes;
  751. }
  752. HRESULT GetIDsOfNames(REFIID /* riid */, LPOLESTR* rgszNames, UINT cNames,
  753. LCID lcid, DISPID* rgdispid)
  754. {
  755. HRESULT hRes = EnsureTI(lcid);
  756. if (m_pInfo != NULL)
  757. {
  758. if (m_pMap != NULL)
  759. {
  760. for (int i=0; i<(int)cNames; i++)
  761. {
  762. int n = int( lstrlenW(rgszNames[i]) );
  763. int j;
  764. for (j=m_nCount-1; j>=0; j--)
  765. {
  766. if ((n == m_pMap[j].nLen) &&
  767. (memcmp(m_pMap[j].bstr, rgszNames[i], m_pMap[j].nLen * sizeof(OLECHAR)) == 0))
  768. {
  769. rgdispid[i] = m_pMap[j].id;
  770. break;
  771. }
  772. }
  773. // if name is not in cache, delegate to ITypeInfo::GetIDsOfNames
  774. if (j < 0)
  775. {
  776. hRes = m_pInfo->GetIDsOfNames(rgszNames, cNames, rgdispid);
  777. // since we've gotten all names, break out of loop
  778. break;
  779. }
  780. }
  781. }
  782. else
  783. hRes = m_pInfo->GetIDsOfNames(rgszNames, cNames, rgdispid);
  784. }
  785. return hRes;
  786. }
  787. HRESULT Invoke(IDispatch* p, DISPID dispidMember, REFIID /* riid */,
  788. LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult,
  789. EXCEPINFO* pexcepinfo, UINT* puArgErr)
  790. {
  791. HRESULT hRes = EnsureTI(lcid);
  792. if (m_pInfo != NULL)
  793. hRes = m_pInfo->Invoke(p, dispidMember, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr);
  794. return hRes;
  795. }
  796. HRESULT LoadNameCache(ITypeInfo* pTypeInfo)
  797. {
  798. TYPEATTR* pta;
  799. HRESULT hr = pTypeInfo->GetTypeAttr(&pta);
  800. if (SUCCEEDED(hr))
  801. {
  802. m_nCount = pta->cFuncs;
  803. m_pMap = NULL;
  804. if (m_nCount != 0)
  805. {
  806. ATLTRY(m_pMap = new stringdispid[m_nCount]);
  807. if (m_pMap == NULL)
  808. {
  809. pTypeInfo->ReleaseTypeAttr(pta);
  810. return E_OUTOFMEMORY;
  811. }
  812. }
  813. for (int i=0; i<m_nCount; i++)
  814. {
  815. FUNCDESC* pfd;
  816. if (SUCCEEDED(pTypeInfo->GetFuncDesc(i, &pfd)))
  817. {
  818. CComBSTR bstrName;
  819. if (SUCCEEDED(pTypeInfo->GetDocumentation(pfd->memid, &bstrName, NULL, NULL, NULL)))
  820. {
  821. m_pMap[i].bstr.Attach(bstrName.Detach());
  822. m_pMap[i].nLen = SysStringLen(m_pMap[i].bstr);
  823. m_pMap[i].id = pfd->memid;
  824. }
  825. pTypeInfo->ReleaseFuncDesc(pfd);
  826. }
  827. }
  828. pTypeInfo->ReleaseTypeAttr(pta);
  829. }
  830. return S_OK;
  831. }
  832. };
  833. inline HRESULT CComTypeInfoHolder::GetTI(LCID lcid)
  834. {
  835. //If this assert occurs then most likely didn't initialize properly
  836. ATLASSERT(m_plibid != NULL && m_pguid != NULL);
  837. ATLASSERT(!InlineIsEqualGUID(*m_plibid, GUID_NULL) && "Did you forget to pass the LIBID to CComModule::Init?");
  838. if (m_pInfo != NULL && m_pMap != NULL)
  839. return S_OK;
  840. CComCritSecLock<CComCriticalSection> lock(_pAtlModule->m_csStaticDataInitAndTypeInfo, false);
  841. HRESULT hRes = lock.Lock();
  842. if (FAILED(hRes))
  843. {
  844. ATLASSERT(0);
  845. return hRes;
  846. }
  847. hRes = E_FAIL;
  848. if (m_pInfo == NULL)
  849. {
  850. ITypeLib* pTypeLib;
  851. hRes = LoadRegTypeLib(*m_plibid, m_wMajor, m_wMinor, lcid, &pTypeLib);
  852. if (SUCCEEDED(hRes))
  853. {
  854. CComPtr<ITypeInfo> spTypeInfo;
  855. hRes = pTypeLib->GetTypeInfoOfGuid(*m_pguid, &spTypeInfo);
  856. if (SUCCEEDED(hRes))
  857. {
  858. CComPtr<ITypeInfo> spInfo(spTypeInfo);
  859. CComPtr<ITypeInfo2> spTypeInfo2;
  860. if (SUCCEEDED(spTypeInfo->QueryInterface(&spTypeInfo2)))
  861. spInfo = spTypeInfo2;
  862. m_pInfo = spInfo.Detach();
  863. }
  864. pTypeLib->Release();
  865. _pAtlModule->AddTermFunc(Cleanup, (DWORD_PTR)this);
  866. }
  867. }
  868. else
  869. {
  870. // Another thread has loaded the typeinfo so we're OK.
  871. hRes = S_OK;
  872. }
  873. if (m_pInfo != NULL && m_pMap == NULL)
  874. LoadNameCache(m_pInfo);
  875. return hRes;
  876. }
  877. #ifndef _ATL_MAX_VARTYPES
  878. #define _ATL_MAX_VARTYPES 8
  879. #endif
  880. /////////////////////////////////////////////////////////////////////////////
  881. // IDispatchImpl
  882. template <class T, const IID* piid = &__uuidof(T), const GUID* plibid = &CAtlModule::m_libid, WORD wMajor = 1,
  883. WORD wMinor = 0, class tihclass = CComTypeInfoHolder>
  884. class ATL_NO_VTABLE IDispatchImpl : public T
  885. {
  886. public:
  887. typedef tihclass _tihclass;
  888. // IDispatch
  889. STDMETHOD(GetTypeInfoCount)(UINT* pctinfo)
  890. {
  891. *pctinfo = 1;
  892. return S_OK;
  893. }
  894. STDMETHOD(GetTypeInfo)(UINT itinfo, LCID lcid, ITypeInfo** pptinfo)
  895. {
  896. return _tih.GetTypeInfo(itinfo, lcid, pptinfo);
  897. }
  898. STDMETHOD(GetIDsOfNames)(REFIID riid, LPOLESTR* rgszNames, UINT cNames,
  899. LCID lcid, DISPID* rgdispid)
  900. {
  901. return _tih.GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid);
  902. }
  903. STDMETHOD(Invoke)(DISPID dispidMember, REFIID riid,
  904. LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult,
  905. EXCEPINFO* pexcepinfo, UINT* puArgErr)
  906. {
  907. return _tih.Invoke((IDispatch*)this, dispidMember, riid, lcid,
  908. wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr);
  909. }
  910. protected:
  911. static _tihclass _tih;
  912. static HRESULT GetTI(LCID lcid, ITypeInfo** ppInfo)
  913. {
  914. return _tih.GetTI(lcid, ppInfo);
  915. }
  916. };
  917. template <class T, const IID* piid, const GUID* plibid, WORD wMajor, WORD wMinor, class tihclass>
  918. typename IDispatchImpl<T, piid, plibid, wMajor, wMinor, tihclass>::_tihclass
  919. IDispatchImpl<T, piid, plibid, wMajor, wMinor, tihclass>::_tih =
  920. {piid, plibid, wMajor, wMinor, NULL, 0, NULL, 0};
  921. #pragma pack(pop)
  922. }; //namespace ATL
  923. //REVIEW: Just to fix VSEE
  924. #pragma pop_macro("min")
  925. #pragma pop_macro("max")
  926. #ifndef _ATL_NO_PRAGMA_WARNINGS
  927. #pragma warning (pop)
  928. #endif
  929. #endif // __ATLCOM_H__
  930. /////////////////////////////////////////////////////////////////////////////