Advertisement
Guest User

atlcom.h

a guest
Feb 7th, 2011
964
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 169.13 KB | None | 0 0
  1. // This is a part of the Active Template Library.
  2. // Copyright (C) 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.  
  11. #ifndef __ATLCOM_H__
  12. #define __ATLCOM_H__
  13.  
  14. #pragma once
  15.  
  16. #ifndef _ATL_NO_PRAGMA_WARNINGS
  17. #pragma warning (push)
  18. #pragma warning(disable: 4702) // unreachable code
  19. #pragma warning(disable: 4355) // 'this' used in initializer list
  20. #pragma warning(disable: 4511) // copy constructor could not be generated
  21. #pragma warning(disable: 4512) // assignment operator could not be generated
  22. #pragma warning(disable : 4668) // is not defined as a preprocessor macro, replacing with '0' for '#if/#elif
  23. #pragma warning(disable : 4820) // padding added after member
  24. #pragma warning(disable : 4571) //catch(...) blocks compiled with /EHs do NOT catch or re-throw Structured Exceptions
  25. #endif //!_ATL_NO_PRAGMA_WARNINGS
  26.  
  27. #ifdef _ATL_ALL_WARNINGS
  28. #pragma warning( push )
  29. #endif
  30. #pragma warning(disable: 4127) // constant expression
  31. #pragma warning(disable: 4786) // avoid 255-character limit warnings
  32.  
  33. #ifndef __cplusplus
  34. #error ATL requires C++ compilation (use a .cpp suffix)
  35. #endif
  36.  
  37. #ifndef __ATLBASE_H__
  38. #error atlcom.h requires atlbase.h to be included first
  39. #endif
  40.  
  41. #include <atlstdthunk.h>
  42. #pragma pack(push, _ATL_PACKING)
  43.  
  44. EXTERN_C const IID IID_ITargetFrame;
  45.  
  46. #include <limits.h>
  47.  
  48. #pragma pack(push, _ATL_PACKING)
  49. namespace ATL
  50. {
  51.  
  52. #define CComConnectionPointContainerImpl ATL::IConnectionPointContainerImpl
  53. #define CComISupportErrorInfoImpl ATL::ISupportErrorInfoImpl
  54. #define CComProvideClassInfo2Impl ATL::IProvideClassInfo2Impl
  55. #define CComDualImpl ATL::IDispatchImpl
  56.  
  57. #ifdef _ATL_DEBUG_QI
  58. #ifndef _ATL_DEBUG
  59. #define _ATL_DEBUG
  60. #endif // _ATL_DEBUG
  61. #endif // _ATL_DEBUG_QI
  62.  
  63. #ifdef _ATL_DEBUG_QI
  64. #define _ATLDUMPIID(iid, name, hr) AtlDumpIID(iid, name, hr)
  65. #else
  66. #define _ATLDUMPIID(iid, name, hr) hr
  67. #endif
  68.  
  69. #define _ATL_DEBUG_ADDREF_RELEASE_IMPL(className)\
  70. virtual ULONG STDMETHODCALLTYPE AddRef(void) = 0;\
  71. virtual ULONG STDMETHODCALLTYPE Release(void) = 0;
  72.  
  73. /////////////////////////////////////////////////////////////////////////////
  74. // AtlReportError
  75.  
  76. inline HRESULT WINAPI AtlReportError(const CLSID& clsid, UINT nID, const IID& iid = GUID_NULL,
  77. HRESULT hRes = 0, HINSTANCE hInst = _AtlBaseModule.GetResourceInstance())
  78. {
  79. return AtlSetErrorInfo(clsid, (LPCOLESTR)MAKEINTRESOURCE(nID), 0, NULL, iid, hRes, hInst);
  80. }
  81.  
  82. inline HRESULT WINAPI AtlReportError(const CLSID& clsid, UINT nID, DWORD dwHelpID,
  83. LPCOLESTR lpszHelpFile, const IID& iid = GUID_NULL, HRESULT hRes = 0,
  84. HINSTANCE hInst = _AtlBaseModule.GetResourceInstance())
  85. {
  86. return AtlSetErrorInfo(clsid, (LPCOLESTR)MAKEINTRESOURCE(nID), dwHelpID,
  87. lpszHelpFile, iid, hRes, hInst);
  88. }
  89.  
  90. inline HRESULT WINAPI AtlReportError(const CLSID& clsid, LPCSTR lpszDesc,
  91. DWORD dwHelpID, LPCSTR lpszHelpFile, const IID& iid = GUID_NULL, HRESULT hRes = 0)
  92. {
  93. ATLASSERT(lpszDesc != NULL);
  94. if (lpszDesc == NULL)
  95. return E_POINTER;
  96. USES_CONVERSION_EX;
  97. LPCOLESTR pwszDesc = A2COLE_EX(lpszDesc, _ATL_SAFE_ALLOCA_DEF_THRESHOLD);
  98. if(pwszDesc == NULL)
  99. return E_OUTOFMEMORY;
  100.  
  101. LPCWSTR pwzHelpFile = NULL;
  102. if(lpszHelpFile != NULL)
  103. {
  104. pwzHelpFile = A2CW_EX(lpszHelpFile, _ATL_SAFE_ALLOCA_DEF_THRESHOLD);
  105. if(pwzHelpFile == NULL)
  106. return E_OUTOFMEMORY;
  107. }
  108.  
  109. return AtlSetErrorInfo(clsid, pwszDesc, dwHelpID, pwzHelpFile, iid, hRes, NULL);
  110. }
  111.  
  112. inline HRESULT WINAPI AtlReportError(const CLSID& clsid, LPCSTR lpszDesc,
  113. const IID& iid = GUID_NULL, HRESULT hRes = 0)
  114. {
  115. return AtlReportError(clsid, lpszDesc, 0, NULL, iid, hRes);
  116. }
  117.  
  118. inline HRESULT WINAPI AtlReportError(const CLSID& clsid, LPCOLESTR lpszDesc,
  119. const IID& iid = GUID_NULL, HRESULT hRes = 0)
  120. {
  121. return AtlSetErrorInfo(clsid, lpszDesc, 0, NULL, iid, hRes, NULL);
  122. }
  123.  
  124. inline HRESULT WINAPI AtlReportError(const CLSID& clsid, LPCOLESTR lpszDesc, DWORD dwHelpID,
  125. LPCOLESTR lpszHelpFile, const IID& iid = GUID_NULL, HRESULT hRes = 0)
  126. {
  127. return AtlSetErrorInfo(clsid, lpszDesc, dwHelpID, lpszHelpFile, iid, hRes, NULL);
  128. }
  129.  
  130. // Returns the apartment type that the current thread is in. false is returned
  131. // if the thread isn't in an apartment.
  132. inline bool AtlGetApartmentType(DWORD* pApartmentType)
  133. {
  134. HRESULT hr = CoInitialize(NULL);
  135. if (SUCCEEDED(hr))
  136. CoUninitialize();
  137.  
  138. if (hr == S_FALSE)
  139. {
  140. *pApartmentType = COINIT_APARTMENTTHREADED;
  141. return true;
  142. }
  143. #if ((_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM))
  144. else
  145. if (hr == RPC_E_CHANGED_MODE)
  146. {
  147. *pApartmentType = COINIT_MULTITHREADED;
  148. return true;
  149. }
  150. #endif
  151. return false;
  152. }
  153.  
  154. /////////////////////////////////////////////////////////////////////////////
  155. // CComTypeAttr
  156.  
  157. class CComTypeAttr
  158. {
  159. // Construction
  160. public:
  161. CComTypeAttr( ITypeInfo* pTypeInfo ) throw() :
  162. m_pTypeAttr( NULL ),
  163. m_pTypeInfo( pTypeInfo )
  164. {
  165. }
  166. ~CComTypeAttr() throw()
  167. {
  168. Release();
  169. }
  170.  
  171. // Operators
  172. public:
  173. TYPEATTR* operator->() throw()
  174. {
  175. ATLASSUME( m_pTypeAttr != NULL );
  176.  
  177. return m_pTypeAttr;
  178. }
  179. TYPEATTR** operator&() throw()
  180. {
  181. ATLASSUME( m_pTypeAttr == NULL );
  182.  
  183. return &m_pTypeAttr;
  184. }
  185.  
  186. operator const TYPEATTR*() const throw()
  187. {
  188. return m_pTypeAttr;
  189. }
  190.  
  191. // Operations
  192. public:
  193. void Release() throw()
  194. {
  195. if( m_pTypeAttr != NULL )
  196. {
  197. ATLASSUME( m_pTypeInfo != NULL );
  198. m_pTypeInfo->ReleaseTypeAttr( m_pTypeAttr );
  199. m_pTypeAttr = NULL;
  200. }
  201. }
  202.  
  203. public:
  204. TYPEATTR* m_pTypeAttr;
  205. CComPtr< ITypeInfo > m_pTypeInfo;
  206. };
  207.  
  208.  
  209. /////////////////////////////////////////////////////////////////////////////
  210. // CComVarDesc
  211.  
  212. class CComVarDesc
  213. {
  214. // Construction
  215. public:
  216. CComVarDesc( ITypeInfo* pTypeInfo ) throw() :
  217. m_pVarDesc( NULL ),
  218. m_pTypeInfo( pTypeInfo )
  219. {
  220. }
  221. ~CComVarDesc() throw()
  222. {
  223. Release();
  224. }
  225.  
  226. // Operators
  227. public:
  228. VARDESC* operator->() throw()
  229. {
  230. ATLASSUME( m_pVarDesc != NULL );
  231.  
  232. return m_pVarDesc;
  233. }
  234. VARDESC** operator&() throw()
  235. {
  236. ATLASSUME( m_pVarDesc == NULL );
  237.  
  238. return &m_pVarDesc;
  239. }
  240.  
  241. operator const VARDESC*() const throw()
  242. {
  243. return m_pVarDesc;
  244. }
  245.  
  246. // Operations
  247. public:
  248. void Release() throw()
  249. {
  250. if( m_pVarDesc != NULL )
  251. {
  252. ATLASSUME( m_pTypeInfo != NULL );
  253. m_pTypeInfo->ReleaseVarDesc( m_pVarDesc );
  254. m_pVarDesc = NULL;
  255. }
  256. }
  257.  
  258. public:
  259. VARDESC* m_pVarDesc;
  260. CComPtr< ITypeInfo > m_pTypeInfo;
  261. };
  262.  
  263.  
  264. /////////////////////////////////////////////////////////////////////////////
  265. // CComFuncDesc
  266.  
  267. class CComFuncDesc
  268. {
  269. // Construction
  270. public:
  271. CComFuncDesc( ITypeInfo* pTypeInfo ) throw() :
  272. m_pFuncDesc( NULL ),
  273. m_pTypeInfo( pTypeInfo )
  274. {
  275. }
  276. ~CComFuncDesc() throw()
  277. {
  278. Release();
  279. }
  280.  
  281. // Operators
  282. public:
  283. FUNCDESC* operator->() throw()
  284. {
  285. ATLASSUME( m_pFuncDesc != NULL );
  286.  
  287. return m_pFuncDesc;
  288. }
  289. FUNCDESC** operator&() throw()
  290. {
  291. ATLASSUME( m_pFuncDesc == NULL );
  292.  
  293. return &m_pFuncDesc;
  294. }
  295.  
  296. operator const FUNCDESC*() const throw()
  297. {
  298. return m_pFuncDesc;
  299. }
  300.  
  301. // Operations
  302. public:
  303. void Release() throw()
  304. {
  305. if( m_pFuncDesc != NULL )
  306. {
  307. ATLASSUME( m_pTypeInfo != NULL );
  308. m_pTypeInfo->ReleaseFuncDesc( m_pFuncDesc );
  309. m_pFuncDesc = NULL;
  310. }
  311. }
  312.  
  313. public:
  314. FUNCDESC* m_pFuncDesc;
  315. CComPtr< ITypeInfo > m_pTypeInfo;
  316. };
  317.  
  318.  
  319. /////////////////////////////////////////////////////////////////////////////
  320. // CComExcepInfo
  321.  
  322. class CComExcepInfo :
  323. public EXCEPINFO
  324. {
  325. // Construction
  326. public:
  327. CComExcepInfo()
  328. {
  329. memset( this, 0, sizeof( *this ) );
  330. }
  331. ~CComExcepInfo()
  332. {
  333. Clear();
  334. }
  335.  
  336. // Operations
  337. public:
  338. void Clear()
  339. {
  340. ::SysFreeString(bstrSource);
  341. ::SysFreeString(bstrDescription);
  342. ::SysFreeString(bstrHelpFile);
  343.  
  344. memset(this, 0, sizeof(*this));
  345. }
  346. };
  347.  
  348.  
  349. //////////////////////////////////////////////////////////////////////////////
  350. // IPersistImpl
  351. template <class T>
  352. class ATL_NO_VTABLE IPersistImpl : public IPersist
  353. {
  354. public:
  355. STDMETHOD(GetClassID)(CLSID *pClassID)
  356. {
  357. ATLTRACE(atlTraceCOM, 2, _T("IPersistImpl::GetClassID\n"));
  358. if (pClassID == NULL)
  359. return E_FAIL;
  360. *pClassID = T::GetObjectCLSID();
  361. return S_OK;
  362. }
  363. };
  364.  
  365. //////////////////////////////////////////////////////////////////////////////
  366. // CFakeFirePropNotifyEvent
  367. class CFakeFirePropNotifyEvent
  368. {
  369. public:
  370. static HRESULT FireOnRequestEdit(IUnknown* /*pUnk*/, DISPID /*dispID*/)
  371. {
  372. return S_OK;
  373. }
  374. static HRESULT FireOnChanged(IUnknown* /*pUnk*/, DISPID /*dispID*/)
  375. {
  376. return S_OK;
  377. }
  378. };
  379. typedef CFakeFirePropNotifyEvent _ATL_PROP_NOTIFY_EVENT_CLASS;
  380.  
  381.  
  382. //////////////////////////////////////////////////////////////////////////////
  383. // ALT_PROP_VAL_MAP
  384.  
  385. struct ATL_PROPVALMAP_ENTRY
  386. {
  387. DISPID dispid;
  388. VARIANT val;
  389. LPCOLESTR szDesc;
  390. };
  391.  
  392. #define BEGIN_PROP_VAL_MAP(theClass) \
  393. static ATL::ATL_PROPVALMAP_ENTRY* GetPropValMap(int *cnt)\
  394. {\
  395. static ATL::ATL_PROPVALMAP_ENTRY pPropMap[] = \
  396. {
  397.  
  398. #define PROP_VAL_INT(dispid, ival, str) \
  399. {dispid, {VT_I4, 0, 0, 0, ival}, OLESTR(str)},
  400.  
  401.  
  402. #define END_PROP_VAL_MAP() \
  403. }; \
  404. if (cnt) \
  405. *cnt = sizeof(pPropMap)/sizeof(pPropMap[0]); \
  406. return pPropMap; \
  407. }
  408.  
  409. #define DECLARE_EMPTY_PROP_VAL_MAP() \
  410. public: \
  411. static ATL::ATL_PROPVALMAP_ENTRY* GetPropValMap(int *cnt)\
  412. { \
  413. if (cnt) \
  414. *cnt = 0; \
  415. return NULL; \
  416. }
  417.  
  418. //////////////////////////////////////////////////////////////////////////////
  419. // ATL Persistence
  420.  
  421. struct ATL_PROPMAP_ENTRY
  422. {
  423. LPCOLESTR szDesc;
  424. DISPID dispid;
  425. const CLSID* pclsidPropPage;
  426. const IID* piidDispatch;
  427. DWORD dwOffsetData;
  428. DWORD dwSizeData;
  429. VARTYPE vt;
  430. #if !defined(_ATL_DLL_IMPL) && !defined(_ATL_DLL)
  431. ClassesAllowedInStream rgclsidAllowed;
  432. DWORD cclsidAllowed;
  433. #endif
  434. };
  435.  
  436. template<VARTYPE V>
  437. struct AtlExpectedDispatchOrUnknown
  438. {
  439. //don't allow to compile PROP_ENTRY with wrong vt parameter
  440. typedef int _assert[V == VT_DISPATCH || V == VT_UNKNOWN ? 1 : -1];
  441.  
  442. static const VARTYPE value = V;
  443. };
  444.  
  445. // This one is DEPRECATED and is used for ATL 2.X controls
  446. // it includes an implicit m_sizeExtent
  447. #define BEGIN_PROPERTY_MAP(theClass) \
  448. __if_not_exists(__ATL_PROP_NOTIFY_EVENT_CLASS) \
  449. { \
  450. typedef ATL::_ATL_PROP_NOTIFY_EVENT_CLASS __ATL_PROP_NOTIFY_EVENT_CLASS; \
  451. } \
  452. typedef theClass _PropMapClass; \
  453. static const ATL::ATL_PROPMAP_ENTRY* GetPropertyMap()\
  454. {\
  455. static const ATL::ATL_PROPMAP_ENTRY pPropMap[] = \
  456. { \
  457. {OLESTR("_cx"), 0, &CLSID_NULL, NULL, offsetof(_PropMapClass, m_sizeExtent.cx), sizeof(long), VT_UI4}, \
  458. {OLESTR("_cy"), 0, &CLSID_NULL, NULL, offsetof(_PropMapClass, m_sizeExtent.cy), sizeof(long), VT_UI4},
  459.  
  460. // This one can be used on any type of object, but does not
  461. // include the implicit m_sizeExtent
  462. #define BEGIN_PROP_MAP(theClass) \
  463. __if_not_exists(__ATL_PROP_NOTIFY_EVENT_CLASS) \
  464. { \
  465. typedef ATL::_ATL_PROP_NOTIFY_EVENT_CLASS __ATL_PROP_NOTIFY_EVENT_CLASS; \
  466. } \
  467. typedef theClass _PropMapClass; \
  468. static const ATL::ATL_PROPMAP_ENTRY* GetPropertyMap()\
  469. {\
  470. static const ATL::ATL_PROPMAP_ENTRY pPropMap[] = \
  471. {
  472. #ifndef _ATL_PROP_ENTRY_NO_WARNING
  473. #pragma deprecated(PROP_ENTRY, PROP_ENTRY_EX)
  474. #endif
  475. #if defined(_ATL_DLL)
  476. #define PROP_ENTRY(szDesc, dispid, clsid) \
  477. {OLESTR(szDesc), dispid, &clsid, &__uuidof(IDispatch), 0, 0, VT_EMPTY},
  478. #else
  479. #define PROP_ENTRY(szDesc, dispid, clsid) \
  480. {OLESTR(szDesc), dispid, &clsid, &__uuidof(IDispatch), 0, 0, VT_EMPTY, NULL, 0},
  481.  
  482. #define PROP_ENTRY_INTERFACE(szDesc, dispid, clsid, rgclsidAllowed, cclsidAllowed, vt) \
  483. {OLESTR(szDesc), dispid, &clsid, &__uuidof(IDispatch), 0, 0, \
  484. ATL::AtlExpectedDispatchOrUnknown<vt>::value, rgclsidAllowed, cclsidAllowed},
  485.  
  486. #define PROP_ENTRY_INTERFACE_CALLBACK(szDesc, dispid, clsid, pfnFunc, vt) \
  487. {OLESTR(szDesc), dispid, &clsid, &__uuidof(IDispatch), 0, 0, \
  488. ATL::AtlExpectedDispatchOrUnknown<vt>::value, reinterpret_cast<const CLSID *>(pfnFunc), 0},
  489. #endif
  490.  
  491. #if defined(_ATL_DLL)
  492. #define PROP_ENTRY_EX(szDesc, dispid, clsid, iidDispatch) \
  493. {OLESTR(szDesc), dispid, &clsid, &iidDispatch, 0, 0, VT_EMPTY},
  494. #else
  495. #define PROP_ENTRY_EX(szDesc, dispid, clsid, iidDispatch) \
  496. {OLESTR(szDesc), dispid, &clsid, &iidDispatch, 0, 0, VT_EMPTY, NULL, 0},
  497.  
  498. #define PROP_ENTRY_INTERFACE_EX(szDesc, dispid, clsid, iidDispatch, rgclsidAllowed, cclsidAllowed, vt) \
  499. {OLESTR(szDesc), dispid, &clsid, &iidDispatch, 0, 0, \
  500. ATL::AtlExpectedDispatchOrUnknown<vt>::value, rgclsidAllowed, cclsidAllowed},
  501.  
  502. #define PROP_ENTRY_INTERFACE_CALLBACK_EX(szDesc, dispid, clsid, iidDispatch, pfnFunc, vt) \
  503. {OLESTR(szDesc), dispid, &clsid, &iidDispatch, 0, 0, \
  504. ATL::AtlExpectedDispatchOrUnknown<vt>::value, reinterpret_cast<const CLSID *>(pfnFunc), 0},
  505. #endif
  506.  
  507. #if defined(_ATL_DLL)
  508. #define PROP_ENTRY_TYPE(szDesc, dispid, clsid, vt) \
  509. {OLESTR(szDesc), dispid, &clsid, &__uuidof(IDispatch), 0, 0, vt},
  510.  
  511. #define PROP_ENTRY_TYPE_EX(szDesc, dispid, clsid, iidDispatch, vt) \
  512. {OLESTR(szDesc), dispid, &clsid, &iidDispatch, 0, 0, vt},
  513.  
  514. #define PROP_PAGE(clsid) \
  515. {NULL, NULL, &clsid, &IID_NULL, 0, 0, 0},
  516.  
  517. #define PROP_DATA_ENTRY(szDesc, member, vt) \
  518. {OLESTR(szDesc), 0, &CLSID_NULL, NULL, offsetof(_PropMapClass, member), sizeof(((_PropMapClass*)0)->member), vt},
  519.  
  520. #define END_PROPERTY_MAP() \
  521. {NULL, 0, NULL, &IID_NULL, 0, 0, 0} \
  522. }; \
  523. return pPropMap; \
  524. }
  525.  
  526. #define END_PROP_MAP() \
  527. {NULL, 0, NULL, &IID_NULL, 0, 0, 0} \
  528. }; \
  529. return pPropMap; \
  530. }
  531. #else
  532. #define PROP_ENTRY_TYPE(szDesc, dispid, clsid, vt) \
  533. {OLESTR(szDesc), dispid, &clsid, &__uuidof(IDispatch), 0, 0, vt, NULL, 0},
  534.  
  535. #define PROP_ENTRY_TYPE_EX(szDesc, dispid, clsid, iidDispatch, vt) \
  536. {OLESTR(szDesc), dispid, &clsid, &iidDispatch, 0, 0, vt, NULL, 0},
  537.  
  538. #define PROP_PAGE(clsid) \
  539. {NULL, NULL, &clsid, &IID_NULL, 0, 0, 0, NULL, 0},
  540.  
  541. #define PROP_DATA_ENTRY(szDesc, member, vt) \
  542. {OLESTR(szDesc), 0, &CLSID_NULL, NULL, offsetof(_PropMapClass, member), sizeof(((_PropMapClass*)0)->member), vt, NULL, 0},
  543.  
  544. #define END_PROPERTY_MAP() \
  545. {NULL, 0, NULL, &IID_NULL, 0, 0, 0, NULL, 0} \
  546. }; \
  547. return pPropMap; \
  548. }
  549.  
  550. #define END_PROP_MAP() \
  551. {NULL, 0, NULL, &IID_NULL, 0, 0, 0, NULL, 0} \
  552. }; \
  553. return pPropMap; \
  554. }
  555. #endif
  556.  
  557.  
  558. //////////////////////////////////////////////////////////////////////////////
  559. // IPersist* Helpers
  560.  
  561. ATLAPI AtlIPersistStreamInit_Load(LPSTREAM pStm, const ATL_PROPMAP_ENTRY* pMap, void* pThis, IUnknown* pUnk);
  562. ATLAPI AtlIPersistStreamInit_Save(LPSTREAM pStm, BOOL fClearDirty, const ATL_PROPMAP_ENTRY* pMap, void* pThis, IUnknown* pUnk);
  563. ATLAPI AtlIPersistPropertyBag_Load(LPPROPERTYBAG pPropBag, LPERRORLOG pErrorLog, const ATL_PROPMAP_ENTRY* pMap, void* pThis, IUnknown* pUnk);
  564. ATLAPI AtlIPersistPropertyBag_Save(LPPROPERTYBAG pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties, const ATL_PROPMAP_ENTRY* pMap, void* pThis, IUnknown* pUnk);
  565.  
  566. //////////////////////////////////////////////////////////////////////////////
  567. // IPersistStreamInitImpl
  568. template <class T>
  569. class ATL_NO_VTABLE IPersistStreamInitImpl : public IPersistStreamInit
  570. {
  571. public:
  572. // IPersist
  573. STDMETHOD(GetClassID)(CLSID *pClassID)
  574. {
  575. ATLTRACE(atlTraceCOM, 2, _T("IPersistStreamInitImpl::GetClassID\n"));
  576. if (pClassID == NULL)
  577. return E_POINTER;
  578. *pClassID = T::GetObjectCLSID();
  579. return S_OK;
  580. }
  581.  
  582. // IPersistStream
  583. STDMETHOD(IsDirty)()
  584. {
  585. ATLTRACE(atlTraceCOM, 2, _T("IPersistStreamInitImpl::IsDirty\n"));
  586. T* pT = static_cast<T*>(this);
  587. return (pT->m_bRequiresSave) ? S_OK : S_FALSE;
  588. }
  589. STDMETHOD(Load)(LPSTREAM pStm)
  590. {
  591. ATLTRACE(atlTraceCOM, 2, _T("IPersistStreamInitImpl::Load\n"));
  592.  
  593. T* pT = static_cast<T*>(this);
  594. return pT->IPersistStreamInit_Load(pStm, T::GetPropertyMap());
  595. }
  596. STDMETHOD(Save)(LPSTREAM pStm, BOOL fClearDirty)
  597. {
  598. T* pT = static_cast<T*>(this);
  599. ATLTRACE(atlTraceCOM, 2, _T("IPersistStreamInitImpl::Save\n"));
  600. return pT->IPersistStreamInit_Save(pStm, fClearDirty, T::GetPropertyMap());
  601. }
  602. STDMETHOD(GetSizeMax)(ULARGE_INTEGER* pcbSize)
  603. {
  604. HRESULT hr = S_OK;
  605. T* pT = static_cast<T*>(this);
  606. ATLTRACE(atlTraceCOM, 2, _T("IPersistStreamInitImpl::GetSizeMax\n"));
  607.  
  608. if (pcbSize == NULL)
  609. return E_POINTER;
  610.  
  611. const ATL_PROPMAP_ENTRY* pMap = T::GetPropertyMap();
  612. ATLENSURE_RETURN(pMap != NULL);
  613.  
  614. // Start the size with the size of the ATL version we write out.
  615. ULARGE_INTEGER nSize;
  616. nSize.HighPart = 0;
  617. nSize.LowPart = sizeof(DWORD);
  618.  
  619. CComPtr<IDispatch> pDispatch;
  620. const IID* piidOld = NULL;
  621. for (int i = 0; pMap[i].pclsidPropPage != NULL; i++)
  622. {
  623. if (pMap[i].szDesc == NULL)
  624. continue;
  625.  
  626. // check if raw data entry
  627. if (pMap[i].dwSizeData != 0)
  628. {
  629. ULONG ulSize=0;
  630. //Calculate stream size for BSTRs special case
  631. if (pMap[i].vt == VT_BSTR)
  632. {
  633. void* pData = (void*) (pMap[i].dwOffsetData + (DWORD_PTR)pT);
  634. ATLENSURE_RETURN( pData >= (void*)(DWORD_PTR)pMap[i].dwOffsetData
  635. && pData >= (void*)(DWORD_PTR)pT );
  636. BSTR bstr=*reinterpret_cast<BSTR*>(pData);
  637. ulSize=CComBSTR::GetStreamSize(bstr);
  638. } else
  639. {
  640. ulSize = pMap[i].dwSizeData;
  641. }
  642. nSize.QuadPart += ulSize;
  643. continue;
  644. }
  645.  
  646. CComVariant var;
  647. if (pMap[i].piidDispatch != piidOld)
  648. {
  649. pDispatch.Release();
  650. ATLENSURE_RETURN(pMap[i].piidDispatch);
  651. if (FAILED(pT->GetUnknown()->QueryInterface(*pMap[i].piidDispatch, (void**)&pDispatch)))
  652. {
  653. ATLTRACE(atlTraceCOM, 0, _T("Failed to get a dispatch pointer for property #%i\n"), i);
  654. hr = E_FAIL;
  655. break;
  656. }
  657. piidOld = pMap[i].piidDispatch;
  658. }
  659.  
  660. if (FAILED(pDispatch.GetProperty(pMap[i].dispid, &var)))
  661. {
  662. ATLTRACE(atlTraceCOM, 0, _T("Invoked failed on DISPID %x\n"), pMap[i].dispid);
  663. hr = E_FAIL;
  664. break;
  665. }
  666. nSize.QuadPart += var.GetSize();
  667. }
  668. *pcbSize = nSize;
  669. return hr;
  670. }
  671.  
  672. // IPersistStreamInit
  673. STDMETHOD(InitNew)()
  674. {
  675. ATLTRACE(atlTraceCOM, 2, _T("IPersistStreamInitImpl::InitNew\n"));
  676. T* pT = static_cast<T*>(this);
  677. pT->m_bRequiresSave = TRUE;
  678. return S_OK;
  679. }
  680.  
  681. HRESULT IPersistStreamInit_Load(LPSTREAM pStm, const ATL_PROPMAP_ENTRY* pMap)
  682. {
  683. T* pT = static_cast<T*>(this);
  684. HRESULT hr = AtlIPersistStreamInit_Load(pStm, pMap, pT, pT->GetUnknown());
  685. if (SUCCEEDED(hr))
  686. pT->m_bRequiresSave = FALSE;
  687. return hr;
  688.  
  689. }
  690. HRESULT IPersistStreamInit_Save(LPSTREAM pStm, BOOL fClearDirty, const ATL_PROPMAP_ENTRY* pMap)
  691. {
  692. T* pT = static_cast<T*>(this);
  693. HRESULT hr;
  694. hr = AtlIPersistStreamInit_Save(pStm, fClearDirty, pMap, pT, pT->GetUnknown());
  695. if (fClearDirty && SUCCEEDED(hr))
  696. {
  697. pT->m_bRequiresSave=FALSE;
  698. }
  699. return hr;
  700.  
  701. }
  702. };
  703.  
  704. //////////////////////////////////////////////////////////////////////////////
  705. // IPersistStorageImpl
  706. template <class T>
  707. class ATL_NO_VTABLE IPersistStorageImpl : public IPersistStorage
  708. {
  709. public:
  710. // IPersist
  711. STDMETHOD(GetClassID)(CLSID *pClassID)
  712. {
  713. ATLTRACE(atlTraceCOM, 2, _T("IPersistStorageImpl::GetClassID\n"));
  714. if (pClassID == NULL)
  715. return E_POINTER;
  716. *pClassID = T::GetObjectCLSID();
  717. return S_OK;
  718. }
  719.  
  720. // IPersistStorage
  721. STDMETHOD(IsDirty)(void)
  722. {
  723. ATLTRACE(atlTraceCOM, 2, _T("IPersistStorageImpl::IsDirty\n"));
  724. CComPtr<IPersistStreamInit> p;
  725. p.p = IPSI_GetIPersistStreamInit();
  726. return (p != NULL) ? p->IsDirty() : E_FAIL;
  727. }
  728. STDMETHOD(InitNew)(IStorage*)
  729. {
  730. ATLTRACE(atlTraceCOM, 2, _T("IPersistStorageImpl::InitNew\n"));
  731. CComPtr<IPersistStreamInit> p;
  732. p.p = IPSI_GetIPersistStreamInit();
  733. return (p != NULL) ? p->InitNew() : E_FAIL;
  734. }
  735. STDMETHOD(Load)(IStorage* pStorage)
  736. {
  737. ATLTRACE(atlTraceCOM, 2, _T("IPersistStorageImpl::Load\n"));
  738. if (pStorage == NULL)
  739. return E_INVALIDARG;
  740. CComPtr<IPersistStreamInit> p;
  741. p.p = IPSI_GetIPersistStreamInit();
  742. HRESULT hr = E_FAIL;
  743. if (p != NULL)
  744. {
  745. CComPtr<IStream> spStream;
  746. hr = pStorage->OpenStream(OLESTR("Contents"), NULL,
  747. STGM_DIRECT | STGM_SHARE_EXCLUSIVE, 0, &spStream);
  748. if (SUCCEEDED(hr))
  749. hr = p->Load(spStream);
  750. }
  751. return hr;
  752. }
  753. STDMETHOD(Save)(IStorage* pStorage, BOOL fSameAsLoad)
  754. {
  755. ATLTRACE(atlTraceCOM, 2, _T("IPersistStorageImpl::Save\n"));
  756. if (pStorage == NULL)
  757. return E_INVALIDARG;
  758. CComPtr<IPersistStreamInit> p;
  759. p.p = IPSI_GetIPersistStreamInit();
  760. HRESULT hr = E_FAIL;
  761. if (p != NULL)
  762. {
  763. CComPtr<IStream> spStream;
  764. static LPCOLESTR vszContents = OLESTR("Contents");
  765. hr = pStorage->CreateStream(vszContents,
  766. STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE,
  767. 0, 0, &spStream);
  768. if (SUCCEEDED(hr))
  769. hr = p->Save(spStream, fSameAsLoad);
  770. }
  771. return hr;
  772. }
  773. STDMETHOD(SaveCompleted)(IStorage* /* pStorage */)
  774. {
  775. ATLTRACE(atlTraceCOM, 2, _T("IPersistStorageImpl::SaveCompleted\n"));
  776. return S_OK;
  777. }
  778. STDMETHOD(HandsOffStorage)(void)
  779. {
  780. ATLTRACE(atlTraceCOM, 2, _T("IPersistStorageImpl::HandsOffStorage\n"));
  781. return S_OK;
  782. }
  783. private:
  784. IPersistStreamInit* IPSI_GetIPersistStreamInit();
  785. };
  786.  
  787. template <class T>
  788. IPersistStreamInit* IPersistStorageImpl<T>::IPSI_GetIPersistStreamInit()
  789. {
  790. T* pT = static_cast<T*>(this);
  791. IPersistStreamInit* p;
  792. if (FAILED(pT->GetUnknown()->QueryInterface(__uuidof(IPersistStreamInit), (void**)&p)))
  793. pT->_InternalQueryInterface(__uuidof(IPersistStreamInit), (void**)&p);
  794. return p;
  795. }
  796.  
  797.  
  798. //////////////////////////////////////////////////////////////////////////////
  799. // IPersistPropertyBagImpl
  800. template <class T>
  801. class ATL_NO_VTABLE IPersistPropertyBagImpl : public IPersistPropertyBag
  802. {
  803. public:
  804. // IPersist
  805. STDMETHOD(GetClassID)(CLSID *pClassID)
  806. {
  807. ATLTRACE(atlTraceCOM, 2, _T("IPersistPropertyBagImpl::GetClassID\n"));
  808. if (pClassID == NULL)
  809. return E_POINTER;
  810. *pClassID = T::GetObjectCLSID();
  811. return S_OK;
  812. }
  813.  
  814. // IPersistPropertyBag
  815. //
  816. STDMETHOD(InitNew)()
  817. {
  818. ATLTRACE(atlTraceCOM, 2, _T("IPersistPropertyBagImpl::InitNew\n"));
  819. T* pT = static_cast<T*>(this);
  820. pT->m_bRequiresSave = TRUE;
  821. return S_OK;
  822. }
  823. STDMETHOD(Load)(LPPROPERTYBAG pPropBag, LPERRORLOG pErrorLog)
  824. {
  825. ATLTRACE(atlTraceCOM, 2, _T("IPersistPropertyBagImpl::Load\n"));
  826. T* pT = static_cast<T*>(this);
  827. const ATL_PROPMAP_ENTRY* pMap = T::GetPropertyMap();
  828. ATLASSERT(pMap != NULL);
  829. return pT->IPersistPropertyBag_Load(pPropBag, pErrorLog, pMap);
  830. }
  831. STDMETHOD(Save)(LPPROPERTYBAG pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties)
  832. {
  833. ATLTRACE(atlTraceCOM, 2, _T("IPersistPropertyBagImpl::Save\n"));
  834. T* pT = static_cast<T*>(this);
  835. const ATL_PROPMAP_ENTRY* pMap = T::GetPropertyMap();
  836. ATLASSERT(pMap != NULL);
  837. return pT->IPersistPropertyBag_Save(pPropBag, fClearDirty, fSaveAllProperties, pMap);
  838. }
  839. HRESULT IPersistPropertyBag_Load(LPPROPERTYBAG pPropBag, LPERRORLOG pErrorLog, const ATL_PROPMAP_ENTRY* pMap)
  840. {
  841. T* pT = static_cast<T*>(this);
  842. HRESULT hr = AtlIPersistPropertyBag_Load(pPropBag, pErrorLog, pMap, pT, pT->GetUnknown());
  843. if (SUCCEEDED(hr))
  844. pT->m_bRequiresSave = FALSE;
  845. return hr;
  846. }
  847. HRESULT IPersistPropertyBag_Save(LPPROPERTYBAG pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties, const ATL_PROPMAP_ENTRY* pMap)
  848. {
  849. T* pT = static_cast<T*>(this);
  850. HRESULT hr;
  851. hr = AtlIPersistPropertyBag_Save(pPropBag, fClearDirty, fSaveAllProperties, pMap, pT, pT->GetUnknown());
  852. if (fClearDirty && SUCCEEDED(hr))
  853. {
  854. pT->m_bRequiresSave=FALSE;
  855. }
  856. return hr;
  857.  
  858. }
  859. };
  860.  
  861. //////////////////////////////////////////////////////////////////////////////
  862. // CSecurityDescriptor
  863. ATL_DEPRECATED("CSecurityDescriptor has been replaced by CSID") class CSecurityDescriptor
  864. {
  865. public:
  866. CSecurityDescriptor();
  867. ~CSecurityDescriptor();
  868.  
  869. public:
  870. HRESULT Attach(PSECURITY_DESCRIPTOR pSelfRelativeSD);
  871. HRESULT AttachObject(HANDLE hObject);
  872. HRESULT Initialize();
  873. HRESULT InitializeFromProcessToken(BOOL bDefaulted = FALSE);
  874. HRESULT InitializeFromThreadToken(BOOL bDefaulted = FALSE, BOOL bRevertToProcessToken = TRUE);
  875. HRESULT SetOwner(PSID pOwnerSid, BOOL bDefaulted = FALSE);
  876. HRESULT SetGroup(PSID pGroupSid, BOOL bDefaulted = FALSE);
  877. HRESULT Allow(LPCTSTR pszPrincipal, DWORD dwAccessMask);
  878. HRESULT Deny(LPCTSTR pszPrincipal, DWORD dwAccessMask);
  879. HRESULT Revoke(LPCTSTR pszPrincipal);
  880. HRESULT Allow(PSID pSid, DWORD dwAccessMask);
  881. HRESULT Deny(PSID pSid, DWORD dwAccessMask);
  882. HRESULT Revoke(PSID pSid);
  883.  
  884. // utility functions
  885. // Any PSID you get from these functions should be free()ed
  886. static HRESULT SetPrivilege(LPCTSTR Privilege, BOOL bEnable = TRUE, HANDLE hToken = NULL);
  887. static HRESULT GetTokenSids(HANDLE hToken, PSID* ppUserSid, PSID* ppGroupSid);
  888. static HRESULT GetProcessSids(PSID* ppUserSid, PSID* ppGroupSid = NULL);
  889. static HRESULT GetThreadSids(PSID* ppUserSid, PSID* ppGroupSid = NULL, BOOL bOpenAsSelf = FALSE);
  890. static HRESULT CopyACL(PACL pDest, PACL pSrc);
  891. static HRESULT GetCurrentUserSID(PSID *ppSid);
  892. static HRESULT GetPrincipalSID(LPCTSTR pszPrincipal, PSID *ppSid);
  893. static HRESULT AddAccessAllowedACEToACL(PACL *Acl, PSID pSid, DWORD dwAccessMask);
  894. static HRESULT AddAccessDeniedACEToACL(PACL *Acl, PSID pSid, DWORD dwAccessMask);
  895. static HRESULT RemovePrincipalFromACL(PACL Acl, PSID pSid);
  896. static HRESULT CloneSID(PSID *ppSIDDest, PSID pSIDSrc)
  897. {
  898. HRESULT hr = S_OK;
  899. if (ppSIDDest == NULL)
  900. return E_POINTER;
  901.  
  902. if (*ppSIDDest != NULL)
  903. return E_INVALIDARG;
  904. *ppSIDDest = NULL;
  905.  
  906. if (!IsValidSid(pSIDSrc))
  907. return E_INVALIDARG;
  908.  
  909. DWORD dwSize = GetLengthSid(pSIDSrc);
  910.  
  911. *ppSIDDest = (PSID) malloc(dwSize);
  912. if (*ppSIDDest == NULL)
  913. return E_OUTOFMEMORY;
  914. if (!CopySid(dwSize, *ppSIDDest, pSIDSrc))
  915. {
  916. hr = AtlHresultFromLastError();
  917. ATLASSERT(FALSE);
  918. free(*ppSIDDest);
  919. *ppSIDDest = NULL;
  920. }
  921. return hr;
  922. }
  923. operator PSECURITY_DESCRIPTOR()
  924. {
  925. return m_pSD;
  926. }
  927.  
  928. public:
  929. PSECURITY_DESCRIPTOR m_pSD;
  930. PSID m_pOwner;
  931. PSID m_pGroup;
  932. PACL m_pDACL;
  933. PACL m_pSACL;
  934. };
  935.  
  936. inline CSecurityDescriptor::CSecurityDescriptor()
  937. {
  938. m_pSD = NULL;
  939. m_pOwner = NULL;
  940. m_pGroup = NULL;
  941. m_pDACL = NULL;
  942. m_pSACL= NULL;
  943. }
  944.  
  945. inline CSecurityDescriptor::~CSecurityDescriptor()
  946. {
  947. delete m_pSD;
  948. free(m_pOwner);
  949. free(m_pGroup);
  950. free(m_pDACL);
  951. free(m_pSACL);
  952. }
  953.  
  954. inline HRESULT CSecurityDescriptor::Initialize()
  955. {
  956. delete m_pSD;
  957. m_pSD = NULL;
  958.  
  959. free(m_pOwner);
  960. m_pOwner = NULL;
  961.  
  962. free(m_pGroup);
  963. m_pGroup = NULL;
  964.  
  965. free(m_pDACL);
  966. m_pDACL = NULL;
  967.  
  968. free(m_pSACL);
  969. m_pSACL = NULL;
  970.  
  971. ATLTRY(m_pSD = new SECURITY_DESCRIPTOR);
  972. if (m_pSD != NULL)
  973. {
  974. if (InitializeSecurityDescriptor(m_pSD, SECURITY_DESCRIPTOR_REVISION))
  975. return S_OK;
  976.  
  977. HRESULT hr = AtlHresultFromLastError();
  978. delete m_pSD;
  979. m_pSD = NULL;
  980. ATLASSERT(FALSE);
  981. return hr;
  982. }
  983.  
  984. return E_OUTOFMEMORY;
  985. }
  986.  
  987. inline HRESULT CSecurityDescriptor::InitializeFromProcessToken(BOOL bDefaulted)
  988. {
  989. HRESULT hr = Initialize();
  990. if (SUCCEEDED(hr))
  991. {
  992. PSID pUserSid = NULL;
  993. PSID pGroupSid = NULL;
  994. hr = GetProcessSids(&pUserSid, &pGroupSid);
  995. if (SUCCEEDED(hr))
  996. {
  997. hr = SetOwner(pUserSid, bDefaulted);
  998. if (SUCCEEDED(hr))
  999. {
  1000. hr = SetGroup(pGroupSid, bDefaulted);
  1001. }
  1002. free(pUserSid);
  1003. free(pGroupSid);
  1004. // If something failed reinitialize the object
  1005. if (FAILED(hr))
  1006. Initialize();
  1007. }
  1008. }
  1009. return hr;
  1010. }
  1011.  
  1012. inline HRESULT CSecurityDescriptor::InitializeFromThreadToken(BOOL bDefaulted, BOOL bRevertToProcessToken)
  1013. {
  1014. HRESULT hr = Initialize();
  1015. if (SUCCEEDED(hr))
  1016. {
  1017. PSID pUserSid = NULL;
  1018. PSID pGroupSid = NULL;
  1019.  
  1020. hr = GetThreadSids(&pUserSid, &pGroupSid);
  1021. if (HRESULT_CODE(hr) == ERROR_NO_TOKEN && bRevertToProcessToken)
  1022. hr = GetProcessSids(&pUserSid, &pGroupSid);
  1023. if (SUCCEEDED(hr))
  1024. {
  1025. hr = SetOwner(pUserSid, bDefaulted);
  1026. if (SUCCEEDED(hr))
  1027. hr = SetGroup(pGroupSid, bDefaulted);
  1028. free(pUserSid);
  1029. free(pGroupSid);
  1030. // If something failed reinitialize the object
  1031. if (FAILED(hr))
  1032. Initialize();
  1033. }
  1034. }
  1035. return hr;
  1036. }
  1037.  
  1038. inline HRESULT CSecurityDescriptor::SetOwner(PSID pOwnerSid, BOOL bDefaulted)
  1039. {
  1040. ATLASSUME(m_pSD);
  1041. HRESULT hr = S_OK;
  1042.  
  1043. // Mark the SD as having no owner
  1044. if (SetSecurityDescriptorOwner(m_pSD, NULL, bDefaulted))
  1045. {
  1046. free(m_pOwner);
  1047. m_pOwner = NULL;
  1048.  
  1049. // If they asked for no owner don't do the copy
  1050. if (pOwnerSid == NULL)
  1051. return S_OK;
  1052.  
  1053. // Make a copy of the Sid for the return value
  1054. hr = CloneSID(&m_pOwner, pOwnerSid);
  1055. if (SUCCEEDED(hr))
  1056. {
  1057. ATLASSERT(IsValidSid(m_pOwner));
  1058.  
  1059. if (!SetSecurityDescriptorOwner(m_pSD, m_pOwner, bDefaulted))
  1060. {
  1061. hr = AtlHresultFromLastError();
  1062. ATLASSERT(FALSE);
  1063. free(m_pOwner);
  1064. m_pOwner = NULL;
  1065. }
  1066. }
  1067. }
  1068. else
  1069. {
  1070. hr = AtlHresultFromLastError();
  1071. ATLASSERT(FALSE);
  1072. }
  1073.  
  1074. return hr;
  1075. }
  1076.  
  1077. inline HRESULT CSecurityDescriptor::SetGroup(PSID pGroupSid, BOOL bDefaulted)
  1078. {
  1079. ATLASSUME(m_pSD);
  1080. HRESULT hr = S_OK;
  1081.  
  1082. // Mark the SD as having no Group
  1083. if (SetSecurityDescriptorGroup(m_pSD, NULL, bDefaulted))
  1084. {
  1085. free(m_pGroup);
  1086. m_pGroup = NULL;
  1087.  
  1088. // If they asked for no Group don't do the copy
  1089. if (pGroupSid == NULL)
  1090. return S_OK;
  1091.  
  1092. // Make a copy of the Sid for the return value
  1093. hr = CloneSID(&m_pGroup, pGroupSid);
  1094. if (SUCCEEDED(hr))
  1095. {
  1096. ATLASSERT(IsValidSid(m_pGroup));
  1097.  
  1098. if (!SetSecurityDescriptorGroup(m_pSD, m_pGroup, bDefaulted))
  1099. {
  1100. hr = AtlHresultFromLastError();
  1101. ATLASSERT(FALSE);
  1102. free(m_pGroup);
  1103. m_pGroup = NULL;
  1104. }
  1105. }
  1106. }
  1107. else
  1108. {
  1109. hr = AtlHresultFromLastError();
  1110. ATLASSERT(FALSE);
  1111. }
  1112.  
  1113. return hr;
  1114. }
  1115.  
  1116. inline HRESULT CSecurityDescriptor::Allow(LPCTSTR pszPrincipal, DWORD dwAccessMask)
  1117. {
  1118. PSID pSid;
  1119. HRESULT hr = GetPrincipalSID(pszPrincipal, &pSid);
  1120. if (SUCCEEDED(hr))
  1121. {
  1122. hr = Allow(pSid, dwAccessMask);
  1123. free(pSid);
  1124. }
  1125. return hr;
  1126. }
  1127.  
  1128. inline HRESULT CSecurityDescriptor::Deny(LPCTSTR pszPrincipal, DWORD dwAccessMask)
  1129. {
  1130. PSID pSid;
  1131. HRESULT hr = GetPrincipalSID(pszPrincipal, &pSid);
  1132. if (SUCCEEDED(hr))
  1133. {
  1134. hr = Deny(pSid, dwAccessMask);
  1135. free(pSid);
  1136. }
  1137. return hr;
  1138. }
  1139.  
  1140. inline HRESULT CSecurityDescriptor::Revoke(LPCTSTR pszPrincipal)
  1141. {
  1142. PSID pSid;
  1143. HRESULT hr = GetPrincipalSID(pszPrincipal, &pSid);
  1144. if (SUCCEEDED(hr))
  1145. {
  1146. hr = Revoke(pSid);
  1147. free(pSid);
  1148. }
  1149. return hr;
  1150. }
  1151.  
  1152. inline HRESULT CSecurityDescriptor::Allow(PSID pSid, DWORD dwAccessMask)
  1153. {
  1154. HRESULT hr = AddAccessAllowedACEToACL(&m_pDACL, pSid, dwAccessMask);
  1155. if (SUCCEEDED(hr))
  1156. {
  1157. if (!SetSecurityDescriptorDacl(m_pSD, TRUE, m_pDACL, FALSE))
  1158. hr = AtlHresultFromLastError();
  1159. }
  1160. return hr;
  1161. }
  1162.  
  1163. inline HRESULT CSecurityDescriptor::Deny(PSID pSid, DWORD dwAccessMask)
  1164. {
  1165. HRESULT hr = AddAccessDeniedACEToACL(&m_pDACL, pSid, dwAccessMask);
  1166. if (SUCCEEDED(hr))
  1167. {
  1168. if (!SetSecurityDescriptorDacl(m_pSD, TRUE, m_pDACL, FALSE))
  1169. hr = AtlHresultFromLastError();
  1170. }
  1171. return hr;
  1172. }
  1173.  
  1174. inline HRESULT CSecurityDescriptor::Revoke(PSID pSid)
  1175. {
  1176. HRESULT hr = RemovePrincipalFromACL(m_pDACL, pSid);
  1177. if (SUCCEEDED(hr))
  1178. {
  1179. if (!SetSecurityDescriptorDacl(m_pSD, TRUE, m_pDACL, FALSE))
  1180. hr = AtlHresultFromLastError();
  1181. }
  1182. return hr;
  1183. }
  1184.  
  1185. inline HRESULT CSecurityDescriptor::GetProcessSids(PSID* ppUserSid, PSID* ppGroupSid)
  1186. {
  1187. HRESULT hr = S_OK;
  1188. HANDLE hToken = NULL;
  1189. if (ppUserSid)
  1190. *ppUserSid = NULL;
  1191. if (ppGroupSid)
  1192. *ppGroupSid = NULL;
  1193. if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
  1194. {
  1195. hr = GetTokenSids(hToken, ppUserSid, ppGroupSid);
  1196. CloseHandle(hToken);
  1197. }
  1198. else
  1199. {
  1200. // Couldn't open process token
  1201. hr = AtlHresultFromLastError();
  1202. ATLASSERT(FALSE);
  1203. }
  1204.  
  1205. return hr;
  1206. }
  1207.  
  1208. inline HRESULT CSecurityDescriptor::GetThreadSids(PSID* ppUserSid, PSID* ppGroupSid, BOOL bOpenAsSelf)
  1209. {
  1210. HRESULT hr = S_OK;
  1211. HANDLE hToken = NULL;
  1212. if (ppUserSid)
  1213. *ppUserSid = NULL;
  1214. if (ppGroupSid)
  1215. *ppGroupSid = NULL;
  1216. if(OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, bOpenAsSelf, &hToken))
  1217. {
  1218. hr = GetTokenSids(hToken, ppUserSid, ppGroupSid);
  1219. CloseHandle(hToken);
  1220. }
  1221. else
  1222. // Couldn't open thread token
  1223. hr = AtlHresultFromLastError();
  1224.  
  1225. return hr;
  1226. }
  1227.  
  1228. inline HRESULT CSecurityDescriptor::GetTokenSids(HANDLE hToken, PSID* ppUserSid, PSID* ppGroupSid)
  1229. {
  1230. DWORD dwSize = 0;
  1231. HRESULT hr = S_OK;
  1232. if (ppUserSid != NULL)
  1233. *ppUserSid = NULL;
  1234. if (ppGroupSid != NULL)
  1235. *ppGroupSid = NULL;
  1236.  
  1237. if (ppUserSid != NULL)
  1238. {
  1239. PTOKEN_USER ptkUser = NULL;
  1240.  
  1241. // Get length required for TokenUser by specifying buffer length of 0
  1242. GetTokenInformation(hToken, TokenUser, NULL, 0, &dwSize);
  1243. // Expected ERROR_INSUFFICIENT_BUFFER
  1244. DWORD dwError = GetLastError();
  1245. if (dwError == ERROR_INSUFFICIENT_BUFFER)
  1246. {
  1247. ptkUser = (TOKEN_USER*) malloc(dwSize);
  1248. if (ptkUser != NULL)
  1249. {
  1250. // Get Sid of process token.
  1251. if (GetTokenInformation(hToken, TokenUser, ptkUser, dwSize, &dwSize))
  1252. {
  1253. // Make a copy of the Sid for the return value
  1254. hr = CloneSID(ppUserSid, ptkUser->User.Sid);
  1255.  
  1256. #ifdef _DEBUG
  1257. if (SUCCEEDED(hr))
  1258. {
  1259. ATLASSERT(IsValidSid(*ppUserSid));
  1260. }
  1261. #endif
  1262. }
  1263. else
  1264. // Couldn't get user info
  1265. hr = AtlHresultFromLastError();
  1266.  
  1267. free(ptkUser);
  1268. ptkUser = NULL;
  1269. }
  1270. else
  1271. hr = E_OUTOFMEMORY;
  1272. }
  1273. else
  1274. {
  1275. ATLASSERT(FALSE);
  1276. hr = AtlHresultFromWin32(dwError);
  1277. }
  1278. }
  1279. if (SUCCEEDED(hr) && ppGroupSid != NULL)
  1280. {
  1281. PTOKEN_PRIMARY_GROUP ptkGroup = NULL;
  1282.  
  1283. // Get length required for TokenPrimaryGroup by specifying buffer length of 0
  1284. GetTokenInformation(hToken, TokenPrimaryGroup, NULL, 0, &dwSize);
  1285. DWORD dwError = GetLastError();
  1286. // Expected ERROR_INSUFFICIENT_BUFFER
  1287. if (dwError == ERROR_INSUFFICIENT_BUFFER)
  1288. {
  1289. ptkGroup = (TOKEN_PRIMARY_GROUP*) malloc(dwSize);
  1290. if (ptkGroup != NULL)
  1291. {
  1292. // Get Sid of process token.
  1293. if (GetTokenInformation(hToken, TokenPrimaryGroup, ptkGroup, dwSize, &dwSize))
  1294. {
  1295. // Make a copy of the Sid for the return value
  1296. hr = CloneSID(ppGroupSid, ptkGroup->PrimaryGroup);
  1297.  
  1298. #ifdef _DEBUG
  1299. if (SUCCEEDED(hr))
  1300. {
  1301. ATLASSERT(IsValidSid(*ppGroupSid));
  1302. }
  1303. #endif
  1304. }
  1305. else
  1306. // Couldn't get user info
  1307. hr = AtlHresultFromLastError();
  1308.  
  1309. free(ptkGroup);
  1310. ptkGroup = NULL;
  1311. }
  1312. else
  1313. hr = E_OUTOFMEMORY;
  1314. }
  1315. else
  1316. hr = AtlHresultFromWin32(dwError);
  1317. }
  1318. if (FAILED(hr))
  1319. {
  1320. if (ppUserSid != NULL)
  1321. {
  1322. free (*ppUserSid);
  1323. *ppUserSid = NULL;
  1324. }
  1325. if (ppGroupSid != NULL)
  1326. {
  1327. free (*ppGroupSid);
  1328. *ppGroupSid = NULL;
  1329. }
  1330. }
  1331.  
  1332. return hr;
  1333. }
  1334.  
  1335.  
  1336. inline HRESULT CSecurityDescriptor::GetCurrentUserSID(PSID *ppSid)
  1337. {
  1338. if (ppSid == NULL)
  1339. return E_POINTER;
  1340. *ppSid = NULL;
  1341.  
  1342. HANDLE tkHandle;
  1343. HRESULT hr = S_OK;
  1344.  
  1345. if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &tkHandle))
  1346. {
  1347. TOKEN_USER *tkUser = NULL;
  1348. DWORD tkSize;
  1349.  
  1350. // Get length required for TokenPrimaryGroup by specifying buffer length of 0
  1351. GetTokenInformation(tkHandle, TokenUser, NULL, 0, &tkSize);
  1352. DWORD dwError = GetLastError();
  1353. // Expected ERROR_INSUFFICIENT_BUFFER
  1354. if (dwError == ERROR_INSUFFICIENT_BUFFER)
  1355. {
  1356. tkUser = (TOKEN_USER *) malloc(tkSize);
  1357. if (tkUser != NULL)
  1358. {
  1359. // Now make the real call
  1360. if (GetTokenInformation(tkHandle, TokenUser, tkUser, tkSize, &tkSize))
  1361. {
  1362. hr = CloneSID(ppSid, tkUser->User.Sid);
  1363.  
  1364. #ifdef _DEBUG
  1365. if (SUCCEEDED(hr))
  1366. {
  1367. ATLASSERT(IsValidSid(*ppSid));
  1368. }
  1369. #endif
  1370. }
  1371. else
  1372. hr = AtlHresultFromLastError();
  1373.  
  1374. free (tkUser);
  1375. tkUser = NULL;
  1376. }
  1377. else
  1378. hr = E_OUTOFMEMORY;
  1379. }
  1380. else
  1381. {
  1382. hr = AtlHresultFromWin32(dwError);
  1383. ATLASSERT(FALSE);
  1384. }
  1385. CloseHandle(tkHandle);
  1386. }
  1387. else
  1388. hr = AtlHresultFromLastError();
  1389.  
  1390. return hr;
  1391. }
  1392.  
  1393.  
  1394. inline HRESULT CSecurityDescriptor::GetPrincipalSID(LPCTSTR pszPrincipal, PSID *ppSid)
  1395. {
  1396. if (ppSid == NULL)
  1397. return E_POINTER;
  1398. if (pszPrincipal == NULL)
  1399. return E_INVALIDARG;
  1400. *ppSid = NULL;
  1401.  
  1402. HRESULT hr;
  1403. LPTSTR pszRefDomain = NULL;
  1404. DWORD dwDomainSize = 0;
  1405. DWORD dwSidSize = 0;
  1406. SID_NAME_USE snu;
  1407. DWORD dwError;
  1408.  
  1409. // Call to get size info for alloc
  1410. LookupAccountName(NULL, pszPrincipal, NULL, &dwSidSize, NULL, &dwDomainSize, &snu);
  1411.  
  1412. dwError = GetLastError();
  1413. if (dwError == ERROR_INSUFFICIENT_BUFFER)
  1414. {
  1415. ATLTRY(pszRefDomain = new TCHAR[dwDomainSize]);
  1416. if (pszRefDomain != NULL)
  1417. {
  1418. *ppSid = (PSID) malloc(dwSidSize);
  1419. if (*ppSid != NULL)
  1420. {
  1421. if (LookupAccountName(NULL, pszPrincipal, *ppSid, &dwSidSize, pszRefDomain, &dwDomainSize, &snu))
  1422. {
  1423. hr = S_OK;
  1424. }
  1425. else
  1426. {
  1427. hr = AtlHresultFromLastError();
  1428. free(*ppSid);
  1429. *ppSid = NULL;
  1430. }
  1431. }
  1432. else
  1433. hr = E_OUTOFMEMORY;
  1434. delete[] pszRefDomain;
  1435. }
  1436. else
  1437. hr = E_OUTOFMEMORY;
  1438. }
  1439. else
  1440. hr = AtlHresultFromWin32(dwError);
  1441.  
  1442. return hr;
  1443. }
  1444.  
  1445. inline HRESULT CSecurityDescriptor::Attach(PSECURITY_DESCRIPTOR pSelfRelativeSD)
  1446. {
  1447. PACL pDACL = NULL;
  1448. PACL pSACL = NULL;
  1449. BOOL bDACLPresent, bSACLPresent;
  1450. BOOL bDefaulted;
  1451. HRESULT hr;
  1452. PSID pUserSid;
  1453. PSID pGroupSid;
  1454.  
  1455. if (pSelfRelativeSD == NULL || !IsValidSecurityDescriptor(pSelfRelativeSD))
  1456. return E_INVALIDARG;
  1457.  
  1458. hr = Initialize();
  1459. if(FAILED(hr))
  1460. return hr;
  1461.  
  1462. // get the existing DACL.
  1463. if (GetSecurityDescriptorDacl(pSelfRelativeSD, &bDACLPresent, &pDACL, &bDefaulted))
  1464. {
  1465. if (bDACLPresent)
  1466. {
  1467. // pDACL should be valid if bDACLPresent is true
  1468. ATLENSURE_RETURN(pDACL != NULL);
  1469. // allocate new DACL.
  1470. m_pDACL = (PACL) malloc(pDACL->AclSize);
  1471. if (m_pDACL != NULL)
  1472. {
  1473. // initialize the DACL
  1474. if (InitializeAcl(m_pDACL, pDACL->AclSize, ACL_REVISION))
  1475. {
  1476. // copy the ACL
  1477. hr = CopyACL(m_pDACL, pDACL);
  1478. if (SUCCEEDED(hr) && !IsValidAcl(m_pDACL))
  1479. hr = E_FAIL;
  1480. }
  1481. else
  1482. hr = AtlHresultFromLastError();
  1483. }
  1484. else
  1485. hr = E_OUTOFMEMORY;
  1486. }
  1487. // set the DACL
  1488. if (SUCCEEDED(hr) && !SetSecurityDescriptorDacl(m_pSD, bDACLPresent, m_pDACL, bDefaulted))
  1489. hr = AtlHresultFromLastError();
  1490. }
  1491. else
  1492. hr = AtlHresultFromLastError();
  1493.  
  1494. // get the existing SACL.
  1495. if (SUCCEEDED(hr) && GetSecurityDescriptorSacl(pSelfRelativeSD, &bSACLPresent, &pSACL, &bDefaulted))
  1496. {
  1497. if (bSACLPresent)
  1498. {
  1499. // pSACL should be valid if bSACLPresent is true
  1500. ATLENSURE_RETURN(pSACL != NULL);
  1501. // allocate new SACL.
  1502. m_pSACL = (PACL) malloc(pSACL->AclSize);
  1503. if (m_pSACL != NULL)
  1504. {
  1505. // initialize the SACL
  1506. if (InitializeAcl(m_pSACL, pSACL->AclSize, ACL_REVISION))
  1507. {
  1508. // copy the ACL
  1509. hr = CopyACL(m_pSACL, pSACL);
  1510. if (SUCCEEDED(hr) && !IsValidAcl(m_pSACL))
  1511. hr = E_FAIL;
  1512. }
  1513. else
  1514. hr = AtlHresultFromLastError();
  1515. }
  1516. else
  1517. hr = E_OUTOFMEMORY;
  1518. }
  1519. // set the SACL
  1520. if (SUCCEEDED(hr) && !SetSecurityDescriptorSacl(m_pSD, bSACLPresent, m_pSACL, bDefaulted))
  1521. hr = AtlHresultFromLastError();
  1522. }
  1523. else if (SUCCEEDED(hr))
  1524. hr = AtlHresultFromLastError();
  1525.  
  1526. if (SUCCEEDED(hr))
  1527. {
  1528. if (GetSecurityDescriptorOwner(pSelfRelativeSD, &pUserSid, &bDefaulted))
  1529. {
  1530. if (SUCCEEDED(hr = SetOwner(pUserSid, bDefaulted)))
  1531. {
  1532. if (GetSecurityDescriptorGroup(pSelfRelativeSD, &pGroupSid, &bDefaulted))
  1533. {
  1534. if (SUCCEEDED(hr = SetGroup(pGroupSid, bDefaulted)))
  1535. {
  1536. if (!IsValidSecurityDescriptor(m_pSD))
  1537. hr = E_FAIL;
  1538. }
  1539. }
  1540. else
  1541. hr = AtlHresultFromLastError();
  1542. }
  1543. }
  1544. else
  1545. hr = AtlHresultFromLastError();
  1546. }
  1547.  
  1548. if (FAILED(hr))
  1549. {
  1550. free(m_pDACL);
  1551. m_pDACL = NULL;
  1552.  
  1553. free(m_pSACL);
  1554. m_pSACL = NULL;
  1555.  
  1556. delete m_pSD;
  1557. m_pSD = NULL;
  1558. }
  1559.  
  1560. return hr;
  1561. }
  1562.  
  1563. inline HRESULT CSecurityDescriptor::AttachObject(HANDLE hObject)
  1564. {
  1565. HRESULT hr;
  1566. DWORD dwError;
  1567. DWORD dwSize = 0;
  1568. PSECURITY_DESCRIPTOR pSD = NULL;
  1569.  
  1570. #pragma warning(push)
  1571. #pragma warning(disable: 6309 6387)
  1572. /* prefast noise VSW 497702 */
  1573. GetKernelObjectSecurity(hObject, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, NULL, 0, &dwSize);
  1574. #pragma warning(pop)
  1575.  
  1576. dwError = GetLastError();
  1577. if (dwError != ERROR_INSUFFICIENT_BUFFER)
  1578. return AtlHresultFromWin32(dwError);
  1579.  
  1580. pSD = (PSECURITY_DESCRIPTOR) malloc(dwSize);
  1581. if (pSD != NULL)
  1582. {
  1583. if (GetKernelObjectSecurity(hObject, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
  1584. DACL_SECURITY_INFORMATION, pSD, dwSize, &dwSize))
  1585.  
  1586. hr = Attach(pSD);
  1587. else
  1588. hr = AtlHresultFromLastError();
  1589. free(pSD);
  1590. }
  1591. else
  1592. hr = E_OUTOFMEMORY;
  1593.  
  1594. return hr;
  1595. }
  1596.  
  1597.  
  1598. inline HRESULT CSecurityDescriptor::CopyACL(PACL pDest, PACL pSrc)
  1599. {
  1600. ACL_SIZE_INFORMATION aclSizeInfo;
  1601. LPVOID pAce;
  1602. ACE_HEADER *aceHeader;
  1603.  
  1604. if (pDest == NULL)
  1605. return E_POINTER;
  1606.  
  1607. if (pSrc == NULL)
  1608. return S_OK;
  1609.  
  1610. if (!GetAclInformation(pSrc, (LPVOID) &aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation))
  1611. return AtlHresultFromLastError();
  1612.  
  1613. // Copy all of the ACEs to the new ACL
  1614. for (UINT i = 0; i < aclSizeInfo.AceCount; i++)
  1615. {
  1616. if (!GetAce(pSrc, i, &pAce))
  1617. return AtlHresultFromLastError();
  1618.  
  1619. aceHeader = (ACE_HEADER *) pAce;
  1620.  
  1621. if (!AddAce(pDest, ACL_REVISION, 0xffffffff, pAce, aceHeader->AceSize))
  1622. return AtlHresultFromLastError();
  1623. }
  1624.  
  1625. return S_OK;
  1626. }
  1627.  
  1628. inline HRESULT CSecurityDescriptor::AddAccessDeniedACEToACL(PACL *ppAcl, PSID pSid, DWORD dwAccessMask)
  1629. {
  1630. ACL_SIZE_INFORMATION aclSizeInfo;
  1631. int aclSize;
  1632. PACL oldACL, newACL = NULL;
  1633. HRESULT hr = S_OK;
  1634.  
  1635. if (ppAcl == NULL)
  1636. return E_POINTER;
  1637.  
  1638. oldACL = *ppAcl;
  1639.  
  1640. if (pSid == NULL || !IsValidSid(pSid))
  1641. return E_INVALIDARG;
  1642.  
  1643. aclSizeInfo.AclBytesInUse = 0;
  1644. if (*ppAcl != NULL && !GetAclInformation(oldACL, (LPVOID) &aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation))
  1645. hr = AtlHresultFromLastError();
  1646.  
  1647. if (SUCCEEDED(hr))
  1648. {
  1649. aclSize = aclSizeInfo.AclBytesInUse + sizeof(ACL) + sizeof(ACCESS_DENIED_ACE) + GetLengthSid(pSid) - sizeof(DWORD);
  1650. newACL = (PACL) malloc(aclSize);
  1651. if (newACL != NULL)
  1652. {
  1653. if (InitializeAcl(newACL, aclSize, ACL_REVISION))
  1654. {
  1655. // access denied ACEs should be before access allowed ACEs
  1656. if (AddAccessDeniedAce(newACL, ACL_REVISION2, dwAccessMask, pSid))
  1657. {
  1658. // Copy existing ACEs to the new ACL
  1659. hr = CopyACL(newACL, oldACL);
  1660. if (SUCCEEDED(hr))
  1661. {
  1662. *ppAcl = newACL;
  1663. free(oldACL);
  1664. }
  1665. }
  1666. else
  1667. hr = AtlHresultFromLastError();
  1668. }
  1669. else
  1670. hr = AtlHresultFromLastError();
  1671.  
  1672. if (FAILED(hr))
  1673. free(newACL);
  1674. }
  1675. else
  1676. hr = E_OUTOFMEMORY;
  1677. }
  1678. return hr;
  1679. }
  1680.  
  1681.  
  1682. inline HRESULT CSecurityDescriptor::AddAccessAllowedACEToACL(PACL *ppAcl, PSID pSid, DWORD dwAccessMask)
  1683. {
  1684. ACL_SIZE_INFORMATION aclSizeInfo;
  1685. int aclSize;
  1686. HRESULT hr = S_OK;
  1687. PACL oldACL, newACL = NULL;
  1688.  
  1689. if (ppAcl == NULL)
  1690. return E_POINTER;
  1691.  
  1692. oldACL = *ppAcl;
  1693.  
  1694. if (pSid == NULL || !IsValidSid(pSid))
  1695. return E_INVALIDARG;
  1696.  
  1697. aclSizeInfo.AclBytesInUse = 0;
  1698. if (*ppAcl != NULL && !GetAclInformation(oldACL, (LPVOID) &aclSizeInfo, (DWORD) sizeof(ACL_SIZE_INFORMATION), AclSizeInformation))
  1699. hr = AtlHresultFromLastError();
  1700.  
  1701. if (SUCCEEDED(hr))
  1702. {
  1703. aclSize = aclSizeInfo.AclBytesInUse + sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pSid) - sizeof(DWORD);
  1704. newACL = (PACL) malloc(aclSize);
  1705. if (newACL != NULL)
  1706. {
  1707. if (InitializeAcl(newACL, aclSize, ACL_REVISION))
  1708. {
  1709. // Copy existing ACEs
  1710. hr = CopyACL(newACL, oldACL);
  1711. if (SUCCEEDED(hr))
  1712. {
  1713. // Add access Allowed ACEs after all other existing ACEs (possibly access denied ACEs)
  1714. if (AddAccessAllowedAce(newACL, ACL_REVISION2, dwAccessMask, pSid))
  1715. {
  1716. *ppAcl = newACL;
  1717. free(oldACL);
  1718. }
  1719. else
  1720. hr = AtlHresultFromLastError();
  1721. }
  1722. }
  1723. else
  1724. hr = AtlHresultFromLastError();
  1725.  
  1726. if (FAILED(hr))
  1727. free(newACL);
  1728. }
  1729. else
  1730. hr = E_OUTOFMEMORY;
  1731. }
  1732. return hr;
  1733. }
  1734.  
  1735. inline HRESULT CSecurityDescriptor::RemovePrincipalFromACL(PACL pAcl, PSID principalSID)
  1736. {
  1737. if (pAcl == NULL || principalSID == NULL || !IsValidSid(principalSID))
  1738. return E_INVALIDARG;
  1739.  
  1740. HRESULT hr = S_OK;
  1741. ACL_SIZE_INFORMATION aclSizeInfo;
  1742. if (!GetAclInformation(pAcl, (LPVOID) &aclSizeInfo, (DWORD) sizeof(ACL_SIZE_INFORMATION), AclSizeInformation))
  1743. {
  1744. hr = AtlHresultFromLastError();
  1745. aclSizeInfo.AceCount = 0;
  1746. }
  1747.  
  1748. for (ULONG i = aclSizeInfo.AceCount; i > 0; i--)
  1749. {
  1750. ULONG uIndex = i - 1;
  1751. LPVOID ace;
  1752. if (!GetAce(pAcl, uIndex, &ace))
  1753. {
  1754. hr = AtlHresultFromLastError();
  1755. break;
  1756. }
  1757.  
  1758. ACE_HEADER *aceHeader = (ACE_HEADER *) ace;
  1759.  
  1760. if (aceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE)
  1761. {
  1762. ACCESS_ALLOWED_ACE *accessAllowedAce = (ACCESS_ALLOWED_ACE *) ace;
  1763. if (EqualSid(principalSID, (PSID) &accessAllowedAce->SidStart))
  1764. {
  1765. DeleteAce(pAcl, uIndex);
  1766. }
  1767. }
  1768. else if (aceHeader->AceType == ACCESS_DENIED_ACE_TYPE)
  1769. {
  1770. ACCESS_DENIED_ACE *accessDeniedAce = (ACCESS_DENIED_ACE *) ace;
  1771. if (EqualSid(principalSID, (PSID) &accessDeniedAce->SidStart))
  1772. {
  1773. DeleteAce(pAcl, uIndex);
  1774. }
  1775. }
  1776. else if (aceHeader->AceType == SYSTEM_AUDIT_ACE_TYPE)
  1777. {
  1778. SYSTEM_AUDIT_ACE *systemAuditAce = (SYSTEM_AUDIT_ACE *) ace;
  1779. if (EqualSid(principalSID, (PSID) &systemAuditAce->SidStart))
  1780. {
  1781. DeleteAce(pAcl, uIndex);
  1782. }
  1783. }
  1784. }
  1785. return hr;
  1786. }
  1787.  
  1788. inline HRESULT CSecurityDescriptor::SetPrivilege(LPCTSTR privilege, BOOL bEnable, HANDLE hToken)
  1789. {
  1790. TOKEN_PRIVILEGES tpPrevious;
  1791. TOKEN_PRIVILEGES tp;
  1792. DWORD cbPrevious = sizeof(TOKEN_PRIVILEGES);
  1793. LUID luid;
  1794. HANDLE hTokenUsed;
  1795.  
  1796. if (!LookupPrivilegeValue(NULL, privilege, &luid ))
  1797. goto _Error;
  1798.  
  1799. // if no token specified open process token
  1800. if (hToken != 0)
  1801. hTokenUsed = hToken;
  1802. else
  1803. if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hTokenUsed))
  1804. goto _Error;
  1805.  
  1806. tp.PrivilegeCount = 1;
  1807. tp.Privileges[0].Luid = luid;
  1808. tp.Privileges[0].Attributes = 0;
  1809.  
  1810. memset(&tpPrevious, 0, sizeof(tpPrevious));
  1811.  
  1812. if (!AdjustTokenPrivileges(hTokenUsed, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &tpPrevious, &cbPrevious))
  1813. goto _Error_CloseHandle;
  1814.  
  1815. tpPrevious.PrivilegeCount = 1;
  1816. tpPrevious.Privileges[0].Luid = luid;
  1817.  
  1818. if (bEnable)
  1819. tpPrevious.Privileges[0].Attributes |= SE_PRIVILEGE_ENABLED;
  1820. else
  1821. tpPrevious.Privileges[0].Attributes &= ~SE_PRIVILEGE_ENABLED;
  1822.  
  1823. if (!AdjustTokenPrivileges(hTokenUsed, FALSE, &tpPrevious, cbPrevious, NULL, NULL))
  1824. goto _Error_CloseHandle;
  1825.  
  1826. if(hToken == 0)
  1827. CloseHandle(hTokenUsed);
  1828.  
  1829. return S_OK;
  1830.  
  1831. HRESULT hr;
  1832.  
  1833. _Error:
  1834. hr = AtlHresultFromLastError();
  1835. return hr;
  1836.  
  1837. _Error_CloseHandle:
  1838. hr = AtlHresultFromLastError();
  1839. if (hToken == 0)
  1840. CloseHandle(hTokenUsed);
  1841. return hr;
  1842. }
  1843.  
  1844. /////////////////////////////////////////////////////////////////////////////
  1845. // COM Objects
  1846.  
  1847. #define DECLARE_PROTECT_FINAL_CONSTRUCT()\
  1848. void InternalFinalConstructAddRef() {InternalAddRef();}\
  1849. void InternalFinalConstructRelease() {InternalRelease();}
  1850.  
  1851. template <class T1>
  1852. class CComCreator
  1853. {
  1854. public:
  1855. static HRESULT WINAPI CreateInstance(void* pv, REFIID riid, LPVOID* ppv)
  1856. {
  1857. ATLASSERT(ppv != NULL);
  1858. if (ppv == NULL)
  1859. return E_POINTER;
  1860. *ppv = NULL;
  1861.  
  1862. HRESULT hRes = E_OUTOFMEMORY;
  1863. T1* p = NULL;
  1864. #pragma warning(push)
  1865. #pragma warning(disable: 6014)
  1866. /* prefast noise VSW 489981 */
  1867. ATLTRY(p = new T1(pv))
  1868. #pragma warning(pop)
  1869. if (p != NULL)
  1870. {
  1871. p->SetVoid(pv);
  1872. p->InternalFinalConstructAddRef();
  1873. hRes = p->_AtlInitialConstruct();
  1874. if (SUCCEEDED(hRes))
  1875. hRes = p->FinalConstruct();
  1876. if (SUCCEEDED(hRes))
  1877. hRes = p->_AtlFinalConstruct();
  1878. p->InternalFinalConstructRelease();
  1879. if (hRes == S_OK)
  1880. hRes = p->QueryInterface(riid, ppv);
  1881. if (hRes != S_OK)
  1882. delete p;
  1883. }
  1884. return hRes;
  1885. }
  1886. };
  1887.  
  1888. template <class T1>
  1889. class CComInternalCreator
  1890. {
  1891. public:
  1892. static HRESULT WINAPI CreateInstance(void* pv, REFIID riid, LPVOID* ppv)
  1893. {
  1894. ATLASSERT(ppv != NULL);
  1895. if (ppv == NULL)
  1896. return E_POINTER;
  1897. *ppv = NULL;
  1898.  
  1899. HRESULT hRes = E_OUTOFMEMORY;
  1900. T1* p = NULL;
  1901. #pragma warning(push)
  1902. #pragma warning(disable: 6014)
  1903. ATLTRY(p = new T1(pv))
  1904. #pragma warning(pop)
  1905. if (p != NULL)
  1906. {
  1907. p->SetVoid(pv);
  1908. p->InternalFinalConstructAddRef();
  1909. hRes = p->_AtlInitialConstruct();
  1910. if (SUCCEEDED(hRes))
  1911. hRes = p->FinalConstruct();
  1912. if (SUCCEEDED(hRes))
  1913. hRes = p->_AtlFinalConstruct();
  1914. p->InternalFinalConstructRelease();
  1915. if (hRes == S_OK)
  1916. hRes = p->_InternalQueryInterface(riid, ppv);
  1917. if (hRes != S_OK)
  1918. delete p;
  1919. }
  1920. return hRes;
  1921. }
  1922. };
  1923.  
  1924. template <HRESULT hr>
  1925. class CComFailCreator
  1926. {
  1927. public:
  1928. static HRESULT WINAPI CreateInstance(void*, REFIID, LPVOID* ppv)
  1929. {
  1930. if (ppv == NULL)
  1931. return E_POINTER;
  1932. *ppv = NULL;
  1933.  
  1934. return hr;
  1935. }
  1936. };
  1937.  
  1938. template <class T1, class T2>
  1939. class CComCreator2
  1940. {
  1941. public:
  1942. static HRESULT WINAPI CreateInstance(void* pv, REFIID riid, LPVOID* ppv)
  1943. {
  1944. ATLASSERT(ppv != NULL);
  1945.  
  1946. return (pv == NULL) ?
  1947. T1::CreateInstance(NULL, riid, ppv) :
  1948. T2::CreateInstance(pv, riid, ppv);
  1949. }
  1950. };
  1951.  
  1952. #define DECLARE_NOT_AGGREGATABLE(x) public:\
  1953. typedef ATL::CComCreator2< ATL::CComCreator< ATL::CComObject< x > >, ATL::CComFailCreator<CLASS_E_NOAGGREGATION> > _CreatorClass;
  1954. #define DECLARE_AGGREGATABLE(x) public:\
  1955. typedef ATL::CComCreator2< ATL::CComCreator< ATL::CComObject< x > >, ATL::CComCreator< ATL::CComAggObject< x > > > _CreatorClass;
  1956. #define DECLARE_ONLY_AGGREGATABLE(x) public:\
  1957. typedef ATL::CComCreator2< ATL::CComFailCreator<E_FAIL>, ATL::CComCreator< ATL::CComAggObject< x > > > _CreatorClass;
  1958. #define DECLARE_POLY_AGGREGATABLE(x) public:\
  1959. typedef ATL::CComCreator< ATL::CComPolyObject< x > > _CreatorClass;
  1960.  
  1961. struct _ATL_CREATORDATA
  1962. {
  1963. _ATL_CREATORFUNC* pFunc;
  1964. };
  1965.  
  1966. template <class Creator>
  1967. class _CComCreatorData
  1968. {
  1969. public:
  1970. static _ATL_CREATORDATA data;
  1971. };
  1972.  
  1973. template <class Creator>
  1974. _ATL_CREATORDATA _CComCreatorData<Creator>::data = {Creator::CreateInstance};
  1975.  
  1976. struct _ATL_CACHEDATA
  1977. {
  1978. DWORD dwOffsetVar;
  1979. _ATL_CREATORFUNC* pFunc;
  1980. };
  1981.  
  1982. template <class Creator, DWORD dwVar>
  1983. class _CComCacheData
  1984. {
  1985. public:
  1986. static _ATL_CACHEDATA data;
  1987. };
  1988.  
  1989. template <class Creator, DWORD dwVar>
  1990. _ATL_CACHEDATA _CComCacheData<Creator, dwVar>::data = {dwVar, Creator::CreateInstance};
  1991.  
  1992. struct _ATL_CHAINDATA
  1993. {
  1994. DWORD_PTR dwOffset;
  1995. const _ATL_INTMAP_ENTRY* (WINAPI *pFunc)();
  1996. };
  1997.  
  1998. template <class base, class derived>
  1999. class _CComChainData
  2000. {
  2001. public:
  2002. static _ATL_CHAINDATA data;
  2003. };
  2004.  
  2005. template <class base, class derived>
  2006. _ATL_CHAINDATA _CComChainData<base, derived>::data =
  2007. {offsetofclass(base, derived), base::_GetEntries};
  2008.  
  2009. template <class T, const CLSID* pclsid>
  2010. class CComAggregateCreator
  2011. {
  2012. public:
  2013. static HRESULT WINAPI CreateInstance(void* pv, REFIID/*riid*/, LPVOID* ppv) throw()
  2014. {
  2015. // Only Assert here. CoCreateInstance will return the correct HRESULT if ppv == NULL
  2016. ATLASSERT(ppv != NULL && *ppv == NULL);
  2017.  
  2018. ATLASSERT(pv != NULL);
  2019. if (pv == NULL)
  2020. return E_INVALIDARG;
  2021.  
  2022. T* p = (T*) pv;
  2023. // Add the following line to your object if you get a message about
  2024. // GetControllingUnknown() being undefined
  2025. // DECLARE_GET_CONTROLLING_UNKNOWN()
  2026. return CoCreateInstance(*pclsid, p->GetControllingUnknown(), CLSCTX_INPROC, __uuidof(IUnknown), ppv);
  2027. }
  2028. };
  2029.  
  2030. #ifdef _ATL_DEBUG
  2031. #define DEBUG_QI_ENTRY(x) \
  2032. {NULL, \
  2033. (DWORD_PTR)_T(#x), \
  2034. (ATL::_ATL_CREATORARGFUNC*)0},
  2035. #else
  2036. #define DEBUG_QI_ENTRY(x)
  2037. #endif //_ATL_DEBUG
  2038.  
  2039. #ifdef _ATL_DEBUG_INTERFACES
  2040. #define _ATL_DECLARE_GET_UNKNOWN(x)\
  2041. IUnknown* GetUnknown() throw() \
  2042. { \
  2043. IUnknown* p; \
  2044. ATL::_AtlDebugInterfacesModule.AddNonAddRefThunk(_GetRawUnknown(), _T(#x), &p); \
  2045. return p; \
  2046. }
  2047. #else
  2048. #define _ATL_DECLARE_GET_UNKNOWN(x) IUnknown* GetUnknown() throw() {return _GetRawUnknown();}
  2049. #endif
  2050.  
  2051. //If you get a message that FinalConstruct is ambiguous then you need to
  2052. // override it in your class and call each base class' version of this
  2053. #define BEGIN_COM_MAP(x) public: \
  2054. typedef x _ComMapClass; \
  2055. static HRESULT WINAPI _Cache(void* pv, REFIID iid, void** ppvObject, DWORD_PTR dw) throw()\
  2056. {\
  2057. _ComMapClass* p = (_ComMapClass*)pv;\
  2058. p->Lock();\
  2059. HRESULT hRes = E_FAIL; \
  2060. __try \
  2061. { \
  2062. hRes = ATL::CComObjectRootBase::_Cache(pv, iid, ppvObject, dw);\
  2063. } \
  2064. __finally \
  2065. { \
  2066. p->Unlock();\
  2067. } \
  2068. return hRes;\
  2069. }\
  2070. IUnknown* _GetRawUnknown() throw() \
  2071. { ATLASSERT(_GetEntries()[0].pFunc == _ATL_SIMPLEMAPENTRY); return (IUnknown*)((INT_PTR)this+_GetEntries()->dw); } \
  2072. _ATL_DECLARE_GET_UNKNOWN(x)\
  2073. HRESULT _InternalQueryInterface(REFIID iid, void** ppvObject) throw() \
  2074. { return InternalQueryInterface(this, _GetEntries(), iid, ppvObject); } \
  2075. const static ATL::_ATL_INTMAP_ENTRY* WINAPI _GetEntries() throw() { \
  2076. static const ATL::_ATL_INTMAP_ENTRY _entries[] = { DEBUG_QI_ENTRY(x)
  2077.  
  2078. // For use by attributes for chaining to existing COM_MAP
  2079. #define BEGIN_ATTRCOM_MAP(x) public: \
  2080. typedef x _AttrComMapClass; \
  2081. const static ATL::_ATL_INTMAP_ENTRY* WINAPI _GetAttrEntries() throw() { \
  2082. static const ATL::_ATL_INTMAP_ENTRY _entries[] = {
  2083.  
  2084. #define DECLARE_GET_CONTROLLING_UNKNOWN() public:\
  2085. virtual IUnknown* GetControllingUnknown() throw() {return GetUnknown();}
  2086.  
  2087. #define COM_INTERFACE_ENTRY_BREAK(x)\
  2088. {&_ATL_IIDOF(x), \
  2089. NULL, \
  2090. _Break},
  2091.  
  2092. #define COM_INTERFACE_ENTRY_NOINTERFACE(x)\
  2093. {&_ATL_IIDOF(x), \
  2094. NULL, \
  2095. _NoInterface},
  2096.  
  2097. #define COM_INTERFACE_ENTRY(x)\
  2098. {&_ATL_IIDOF(x), \
  2099. offsetofclass(x, _ComMapClass), \
  2100. _ATL_SIMPLEMAPENTRY},
  2101.  
  2102. #define COM_INTERFACE_ENTRY_IID(iid, x)\
  2103. {&iid,\
  2104. offsetofclass(x, _ComMapClass),\
  2105. _ATL_SIMPLEMAPENTRY},
  2106.  
  2107. // The impl macros are now obsolete
  2108. #define COM_INTERFACE_ENTRY_IMPL(x)\
  2109. COM_INTERFACE_ENTRY_IID(_ATL_IIDOF(x), x##Impl<_ComMapClass>)
  2110.  
  2111. #define COM_INTERFACE_ENTRY_IMPL_IID(iid, x)\
  2112. COM_INTERFACE_ENTRY_IID(iid, x##Impl<_ComMapClass>)
  2113. //
  2114.  
  2115. #define COM_INTERFACE_ENTRY2(x, x2)\
  2116. {&_ATL_IIDOF(x),\
  2117. reinterpret_cast<DWORD_PTR>(static_cast<x*>(static_cast<x2*>(reinterpret_cast<_ComMapClass*>(8))))-8,\
  2118. _ATL_SIMPLEMAPENTRY},
  2119.  
  2120. #define COM_INTERFACE_ENTRY2_IID(iid, x, x2)\
  2121. {&iid,\
  2122. reinterpret_cast<DWORD_PTR>(static_cast<x*>(static_cast<x2*>(reinterpret_cast<_ComMapClass*>(8))))-8,\
  2123. _ATL_SIMPLEMAPENTRY},
  2124.  
  2125. #define COM_INTERFACE_ENTRY_FUNC(iid, dw, func)\
  2126. {&iid, \
  2127. dw, \
  2128. func},
  2129.  
  2130. #define COM_INTERFACE_ENTRY_FUNC_BLIND(dw, func)\
  2131. {NULL, \
  2132. dw, \
  2133. func},
  2134.  
  2135. #define COM_INTERFACE_ENTRY_TEAR_OFF(iid, x)\
  2136. {&iid,\
  2137. (DWORD_PTR)&ATL::_CComCreatorData<\
  2138. ATL::CComInternalCreator< ATL::CComTearOffObject< x > >\
  2139. >::data,\
  2140. _Creator},
  2141.  
  2142. #define COM_INTERFACE_ENTRY_CACHED_TEAR_OFF(iid, x, punk)\
  2143. {&iid,\
  2144. (DWORD_PTR)&ATL::_CComCacheData<\
  2145. ATL::CComCreator< ATL::CComCachedTearOffObject< x > >,\
  2146. (DWORD_PTR)offsetof(_ComMapClass, punk)\
  2147. >::data,\
  2148. _Cache},
  2149.  
  2150. #define COM_INTERFACE_ENTRY_AGGREGATE(iid, punk)\
  2151. {&iid,\
  2152. (DWORD_PTR)offsetof(_ComMapClass, punk),\
  2153. _Delegate},
  2154.  
  2155. #define COM_INTERFACE_ENTRY_AGGREGATE_BLIND(punk)\
  2156. {NULL,\
  2157. (DWORD_PTR)offsetof(_ComMapClass, punk),\
  2158. _Delegate},
  2159.  
  2160. #define COM_INTERFACE_ENTRY_AUTOAGGREGATE(iid, punk, clsid)\
  2161. {&iid,\
  2162. (DWORD_PTR)&ATL::_CComCacheData<\
  2163. ATL::CComAggregateCreator<_ComMapClass, &clsid>,\
  2164. (DWORD_PTR)offsetof(_ComMapClass, punk)\
  2165. >::data,\
  2166. _Cache},
  2167.  
  2168. #define COM_INTERFACE_ENTRY_AUTOAGGREGATE_BLIND(punk, clsid)\
  2169. {NULL,\
  2170. (DWORD_PTR)&ATL::_CComCacheData<\
  2171. ATL::CComAggregateCreator<_ComMapClass, &clsid>,\
  2172. (DWORD_PTR)offsetof(_ComMapClass, punk)\
  2173. >::data,\
  2174. _Cache},
  2175.  
  2176. #define COM_INTERFACE_ENTRY_CHAIN(classname)\
  2177. {NULL,\
  2178. (DWORD_PTR)&ATL::_CComChainData<classname, _ComMapClass>::data,\
  2179. _Chain},
  2180.  
  2181. #ifdef _ATL_DEBUG
  2182. #define END_COM_MAP() \
  2183. __if_exists(_GetAttrEntries) {{NULL, (DWORD_PTR)_GetAttrEntries, _ChainAttr }, }\
  2184. {NULL, 0, 0}}; return &_entries[1];} \
  2185. virtual ULONG STDMETHODCALLTYPE AddRef( void) throw() = 0; \
  2186. virtual ULONG STDMETHODCALLTYPE Release( void) throw() = 0; \
  2187. STDMETHOD(QueryInterface)(REFIID, void**) throw() = 0;
  2188. #else
  2189. #define END_COM_MAP() \
  2190. __if_exists(_GetAttrEntries) {{NULL, (DWORD_PTR)_GetAttrEntries, _ChainAttr }, }\
  2191. {NULL, 0, 0}}; return _entries;} \
  2192. virtual ULONG STDMETHODCALLTYPE AddRef( void) throw() = 0; \
  2193. virtual ULONG STDMETHODCALLTYPE Release( void) throw() = 0; \
  2194. STDMETHOD(QueryInterface)(REFIID, void**) throw() = 0;
  2195. #endif // _ATL_DEBUG
  2196.  
  2197. #define END_ATTRCOM_MAP() \
  2198. {NULL, 0, 0}}; return _entries;}
  2199.  
  2200.  
  2201. #define BEGIN_CATEGORY_MAP(x)\
  2202. static const struct ATL::_ATL_CATMAP_ENTRY* GetCategoryMap() throw() {\
  2203. static const struct ATL::_ATL_CATMAP_ENTRY pMap[] = {
  2204. #define IMPLEMENTED_CATEGORY( catid ) { _ATL_CATMAP_ENTRY_IMPLEMENTED, &catid },
  2205. #define REQUIRED_CATEGORY( catid ) { _ATL_CATMAP_ENTRY_REQUIRED, &catid },
  2206. #define END_CATEGORY_MAP()\
  2207. { _ATL_CATMAP_ENTRY_END, NULL } };\
  2208. return( pMap ); }
  2209.  
  2210. #define BEGIN_OBJECT_MAP(x) static ATL::_ATL_OBJMAP_ENTRY x[] = {
  2211. #define END_OBJECT_MAP() {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}};
  2212. #define OBJECT_ENTRY(clsid, class) {&clsid, class::UpdateRegistry, class::_ClassFactoryCreatorClass::CreateInstance, class::_CreatorClass::CreateInstance, NULL, 0, class::GetObjectDescription, class::GetCategoryMap, class::ObjectMain },
  2213. #define OBJECT_ENTRY_NON_CREATEABLE(class) {&CLSID_NULL, class::UpdateRegistry, NULL, NULL, NULL, 0, NULL, class::GetCategoryMap, class::ObjectMain },
  2214. #define OBJECT_ENTRY_NON_CREATEABLE_EX(clsid, class) {&clsid, class::UpdateRegistry, NULL, NULL, NULL, 0, NULL, class::GetCategoryMap, class::ObjectMain },
  2215.  
  2216. #ifndef OBJECT_ENTRY_PRAGMA
  2217.  
  2218. #if defined(_M_IX86)
  2219. #define OBJECT_ENTRY_PRAGMA(class) __pragma(comment(linker, "/include:___pobjMap_" #class));
  2220. #elif defined(_M_IA64)
  2221. #define OBJECT_ENTRY_PRAGMA(class) __pragma(comment(linker, "/include:__pobjMap_" #class));
  2222. #elif defined(_M_AMD64)
  2223. #define OBJECT_ENTRY_PRAGMA(class) __pragma(comment(linker, "/include:__pobjMap_" #class));
  2224. #else
  2225. #error Unknown Platform. define OBJECT_ENTRY_PRAGMA
  2226. #endif
  2227.  
  2228. #endif //OBJECT_ENTRY_PRAGMA
  2229.  
  2230. #define OBJECT_ENTRY_AUTO(clsid, class) \
  2231. __declspec(selectany) ATL::_ATL_OBJMAP_ENTRY __objMap_##class = {&clsid, class::UpdateRegistry, class::_ClassFactoryCreatorClass::CreateInstance, class::_CreatorClass::CreateInstance, NULL, 0, class::GetObjectDescription, class::GetCategoryMap, class::ObjectMain }; \
  2232. extern "C" __declspec(allocate("ATL$__m")) __declspec(selectany) ATL::_ATL_OBJMAP_ENTRY* const __pobjMap_##class = &__objMap_##class; \
  2233. OBJECT_ENTRY_PRAGMA(class)
  2234.  
  2235.  
  2236. #define OBJECT_ENTRY_NON_CREATEABLE_EX_AUTO(clsid, class) \
  2237. __declspec(selectany) ATL::_ATL_OBJMAP_ENTRY __objMap_##class = {&clsid, class::UpdateRegistry, NULL, NULL, NULL, 0, NULL, class::GetCategoryMap, class::ObjectMain }; \
  2238. extern "C" __declspec(allocate("ATL$__m")) __declspec(selectany) ATL::_ATL_OBJMAP_ENTRY* const __pobjMap_##class = &__objMap_##class; \
  2239. OBJECT_ENTRY_PRAGMA(class)
  2240.  
  2241. // the functions in this class don't need to be virtual because
  2242. // they are called from CComObject
  2243. class CComObjectRootBase
  2244. {
  2245. public:
  2246. CComObjectRootBase()
  2247. {
  2248. m_dwRef = 0L;
  2249. }
  2250. ~CComObjectRootBase()
  2251. {
  2252. }
  2253. HRESULT FinalConstruct()
  2254. {
  2255. return S_OK;
  2256. }
  2257. // For library initialization only
  2258. HRESULT _AtlFinalConstruct()
  2259. {
  2260. return S_OK;
  2261. }
  2262. void FinalRelease() {}
  2263. void _AtlFinalRelease() {} // temp
  2264.  
  2265. void _HRPass(HRESULT hr) // temp
  2266. {
  2267. (hr);
  2268. }
  2269.  
  2270. void _HRFail(HRESULT hr) // temp...
  2271. {
  2272. (hr);
  2273. }
  2274.  
  2275.  
  2276. //ObjectMain is called during Module::Init and Module::Term
  2277. static void WINAPI ObjectMain(bool /* bStarting */);
  2278.  
  2279. static const struct _ATL_CATMAP_ENTRY* GetCategoryMap() {return NULL;};
  2280. static HRESULT WINAPI InternalQueryInterface(void* pThis,
  2281. const _ATL_INTMAP_ENTRY* pEntries, REFIID iid, void** ppvObject)
  2282. {
  2283. // Only Assert here. AtlInternalQueryInterface will return the correct HRESULT if ppvObject == NULL
  2284. #ifndef _ATL_OLEDB_CONFORMANCE_TESTS
  2285. ATLASSERT(ppvObject != NULL);
  2286. #endif
  2287. ATLASSERT(pThis != NULL);
  2288. // First entry in the com map should be a simple map entry
  2289. ATLASSERT(pEntries->pFunc == _ATL_SIMPLEMAPENTRY);
  2290. #if defined(_ATL_DEBUG_INTERFACES) || defined(_ATL_DEBUG_QI)
  2291. LPCTSTR pszClassName = (LPCTSTR) pEntries[-1].dw;
  2292. #endif // _ATL_DEBUG_INTERFACES
  2293. HRESULT hRes = AtlInternalQueryInterface(pThis, pEntries, iid, ppvObject);
  2294. #ifdef _ATL_DEBUG_INTERFACES
  2295. _AtlDebugInterfacesModule.AddThunk((IUnknown**)ppvObject, pszClassName, iid);
  2296. #endif // _ATL_DEBUG_INTERFACES
  2297. return _ATLDUMPIID(iid, pszClassName, hRes);
  2298. }
  2299.  
  2300. //Outer funcs
  2301. ULONG OuterAddRef()
  2302. {
  2303. return m_pOuterUnknown->AddRef();
  2304. }
  2305. ULONG OuterRelease()
  2306. {
  2307. return m_pOuterUnknown->Release();
  2308. }
  2309. HRESULT OuterQueryInterface(REFIID iid, void ** ppvObject)
  2310. {
  2311. return m_pOuterUnknown->QueryInterface(iid, ppvObject);
  2312. }
  2313.  
  2314. void SetVoid(void*) {}
  2315. void InternalFinalConstructAddRef() {}
  2316. void InternalFinalConstructRelease()
  2317. {
  2318. ATLASSUME(m_dwRef == 0);
  2319. }
  2320. // If this assert occurs, your object has probably been deleted
  2321. // Try using DECLARE_PROTECT_FINAL_CONSTRUCT()
  2322.  
  2323.  
  2324. static HRESULT WINAPI _Break(void* /* pv */, REFIID iid, void** /* ppvObject */, DWORD_PTR /* dw */)
  2325. {
  2326. (iid);
  2327. _ATLDUMPIID(iid, _T("Break due to QI for interface "), S_OK);
  2328. DebugBreak();
  2329. return S_FALSE;
  2330. }
  2331. static HRESULT WINAPI _NoInterface(void* /* pv */, REFIID /* iid */, void** /* ppvObject */, DWORD_PTR /* dw */)
  2332. {
  2333. return E_NOINTERFACE;
  2334. }
  2335. static HRESULT WINAPI _Creator(void* pv, REFIID iid, void** ppvObject, DWORD_PTR dw)
  2336. {
  2337. _ATL_CREATORDATA* pcd = (_ATL_CREATORDATA*)dw;
  2338. return pcd->pFunc(pv, iid, ppvObject);
  2339. }
  2340. static HRESULT WINAPI _Delegate(void* pv, REFIID iid, void** ppvObject, DWORD_PTR dw)
  2341. {
  2342. HRESULT hRes = E_NOINTERFACE;
  2343. IUnknown* p = *(IUnknown**)((DWORD_PTR)pv + dw);
  2344. if (p != NULL)
  2345. hRes = p->QueryInterface(iid, ppvObject);
  2346. return hRes;
  2347. }
  2348. static HRESULT WINAPI _Chain(void* pv, REFIID iid, void** ppvObject, DWORD_PTR dw)
  2349. {
  2350. _ATL_CHAINDATA* pcd = (_ATL_CHAINDATA*)dw;
  2351. void* p = (void*)((DWORD_PTR)pv + pcd->dwOffset);
  2352. return InternalQueryInterface(p, pcd->pFunc(), iid, ppvObject);
  2353. }
  2354. static HRESULT WINAPI _ChainAttr(void* pv, REFIID iid, void** ppvObject, DWORD_PTR dw)
  2355. {
  2356. const _ATL_INTMAP_ENTRY* (WINAPI *pFunc)() = (const _ATL_INTMAP_ENTRY* (WINAPI *)())dw;
  2357. const _ATL_INTMAP_ENTRY *pEntries = pFunc();
  2358. if (pEntries == NULL)
  2359. return S_OK;
  2360. return InternalQueryInterface(pv, pEntries, iid, ppvObject);
  2361. }
  2362. static HRESULT WINAPI _Cache(void* pv, REFIID iid, void** ppvObject, DWORD_PTR dw)
  2363. {
  2364. HRESULT hRes = E_NOINTERFACE;
  2365. _ATL_CACHEDATA* pcd = (_ATL_CACHEDATA*)dw;
  2366. IUnknown** pp = (IUnknown**)((DWORD_PTR)pv + pcd->dwOffsetVar);
  2367. if (*pp == NULL)
  2368. hRes = pcd->pFunc(pv, __uuidof(IUnknown), (void**)pp);
  2369. if (*pp != NULL)
  2370. hRes = (*pp)->QueryInterface(iid, ppvObject);
  2371. return hRes;
  2372. }
  2373.  
  2374. union
  2375. {
  2376. long m_dwRef;
  2377. IUnknown* m_pOuterUnknown;
  2378. };
  2379. };
  2380.  
  2381. #pragma managed(push, off)
  2382. inline void WINAPI CComObjectRootBase::ObjectMain(bool /* bStarting */)
  2383. {
  2384. }
  2385. #pragma managed(pop)
  2386.  
  2387.  
  2388. //foward declaration
  2389. template <class ThreadModel>
  2390. class CComObjectRootEx;
  2391.  
  2392. template <class ThreadModel>
  2393. class CComObjectLockT
  2394. {
  2395. public:
  2396. CComObjectLockT(CComObjectRootEx<ThreadModel>* p)
  2397. {
  2398. if (p)
  2399. p->Lock();
  2400. m_p = p;
  2401. }
  2402.  
  2403. ~CComObjectLockT()
  2404. {
  2405. if (m_p)
  2406. m_p->Unlock();
  2407. }
  2408. CComObjectRootEx<ThreadModel>* m_p;
  2409. };
  2410.  
  2411. template <> class CComObjectLockT<CComSingleThreadModel>;
  2412.  
  2413. template <class ThreadModel>
  2414. class CComObjectRootEx : public CComObjectRootBase
  2415. {
  2416. public:
  2417. typedef ThreadModel _ThreadModel;
  2418. typedef typename _ThreadModel::AutoCriticalSection _CritSec;
  2419. typedef typename _ThreadModel::AutoDeleteCriticalSection _AutoDelCritSec;
  2420. typedef CComObjectLockT<_ThreadModel> ObjectLock;
  2421.  
  2422. ~CComObjectRootEx() {}
  2423.  
  2424. ULONG InternalAddRef()
  2425. {
  2426. ATLASSUME(m_dwRef != -1L);
  2427. return _ThreadModel::Increment(&m_dwRef);
  2428. }
  2429. ULONG InternalRelease()
  2430. {
  2431. #ifdef _DEBUG
  2432. LONG nRef = _ThreadModel::Decrement(&m_dwRef);
  2433. if (nRef < -(LONG_MAX / 2))
  2434. {
  2435. ATLASSERT(0 && _T("Release called on a pointer that has already been released"));
  2436. }
  2437. return nRef;
  2438. #else
  2439. return _ThreadModel::Decrement(&m_dwRef);
  2440. #endif
  2441. }
  2442.  
  2443. HRESULT _AtlInitialConstruct()
  2444. {
  2445. return m_critsec.Init();
  2446. }
  2447. void Lock() {m_critsec.Lock();}
  2448. void Unlock() {m_critsec.Unlock();}
  2449. private:
  2450. _AutoDelCritSec m_critsec;
  2451. };
  2452.  
  2453. template <>
  2454. class CComObjectRootEx<CComSingleThreadModel> : public CComObjectRootBase
  2455. {
  2456. public:
  2457. typedef CComSingleThreadModel _ThreadModel;
  2458. typedef _ThreadModel::AutoCriticalSection _CritSec;
  2459. typedef _ThreadModel::AutoDeleteCriticalSection _AutoDelCritSec;
  2460. typedef CComObjectLockT<_ThreadModel> ObjectLock;
  2461.  
  2462. ~CComObjectRootEx() {}
  2463.  
  2464. ULONG InternalAddRef()
  2465. {
  2466. ATLASSUME(m_dwRef != -1L);
  2467. return _ThreadModel::Increment(&m_dwRef);
  2468. }
  2469. ULONG InternalRelease()
  2470. {
  2471. #ifdef _DEBUG
  2472. long nRef = _ThreadModel::Decrement(&m_dwRef);
  2473. if (nRef < -(LONG_MAX / 2))
  2474. {
  2475. ATLASSERT(0 && _T("Release called on a pointer that has already been released"));
  2476. }
  2477. return nRef;
  2478. #else
  2479. return _ThreadModel::Decrement(&m_dwRef);
  2480. #endif
  2481. }
  2482.  
  2483. HRESULT _AtlInitialConstruct()
  2484. {
  2485. return S_OK;
  2486. }
  2487.  
  2488. void Lock() {}
  2489. void Unlock() {}
  2490. };
  2491.  
  2492. template <>
  2493. class CComObjectLockT<CComSingleThreadModel>
  2494. {
  2495. public:
  2496. CComObjectLockT(CComObjectRootEx<CComSingleThreadModel>*) {}
  2497. ~CComObjectLockT() {}
  2498. };
  2499.  
  2500. typedef CComObjectRootEx<CComObjectThreadModel> CComObjectRoot;
  2501.  
  2502. #if defined(_WINDLL) | defined(_USRDLL)
  2503. #define DECLARE_CLASSFACTORY_EX(cf) typedef ATL::CComCreator< ATL::CComObjectCached< cf > > _ClassFactoryCreatorClass;
  2504. #else
  2505. // don't let class factory refcount influence lock count
  2506. #define DECLARE_CLASSFACTORY_EX(cf) typedef ATL::CComCreator< ATL::CComObjectNoLock< cf > > _ClassFactoryCreatorClass;
  2507. #endif
  2508. #define DECLARE_CLASSFACTORY() DECLARE_CLASSFACTORY_EX(ATL::CComClassFactory)
  2509. #define DECLARE_CLASSFACTORY2(lic) DECLARE_CLASSFACTORY_EX(ATL::CComClassFactory2<lic>)
  2510. #define DECLARE_CLASSFACTORY_AUTO_THREAD() DECLARE_CLASSFACTORY_EX(ATL::CComClassFactoryAutoThread)
  2511. #define DECLARE_CLASSFACTORY_SINGLETON(obj) DECLARE_CLASSFACTORY_EX(ATL::CComClassFactorySingleton<obj>)
  2512.  
  2513. #define DECLARE_OBJECT_DESCRIPTION(x)\
  2514. static LPCTSTR WINAPI GetObjectDescription() throw()\
  2515. {\
  2516. return _T(x);\
  2517. }
  2518.  
  2519. #define DECLARE_NO_REGISTRY()\
  2520. static HRESULT WINAPI UpdateRegistry(BOOL /*bRegister*/) throw()\
  2521. {return S_OK;}
  2522.  
  2523. #define DECLARE_REGISTRY(class, pid, vpid, nid, flags)\
  2524. static HRESULT WINAPI UpdateRegistry(BOOL bRegister) throw()\
  2525. {\
  2526. return _Module.UpdateRegistryClass(GetObjectCLSID(), pid, vpid, nid,\
  2527. flags, bRegister);\
  2528. }
  2529.  
  2530. #define DECLARE_REGISTRY_RESOURCE(x)\
  2531. static HRESULT WINAPI UpdateRegistry(BOOL bRegister) throw()\
  2532. {\
  2533. __if_exists(_GetMiscStatus) \
  2534. { \
  2535. ATL::_ATL_REGMAP_ENTRY regMapEntries[2]; \
  2536. memset(&regMapEntries[1], 0, sizeof(ATL::_ATL_REGMAP_ENTRY)); \
  2537. regMapEntries[0].szKey = L"OLEMISC"; \
  2538. TCHAR szOleMisc[32]; \
  2539. ATL::Checked::itot_s(_GetMiscStatus(), szOleMisc, _countof(szOleMisc), 10); \
  2540. USES_CONVERSION_EX; \
  2541. regMapEntries[0].szData = T2OLE_EX(szOleMisc, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); \
  2542. if (regMapEntries[0].szData == NULL) \
  2543. return E_OUTOFMEMORY; \
  2544. __if_exists(_Module) \
  2545. { \
  2546. return _Module.UpdateRegistryFromResource(_T(#x), bRegister, regMapEntries); \
  2547. } \
  2548. __if_not_exists(_Module) \
  2549. { \
  2550. return ATL::_pAtlModule->UpdateRegistryFromResource(_T(#x), bRegister, regMapEntries); \
  2551. } \
  2552. } \
  2553. __if_not_exists(_GetMiscStatus) \
  2554. { \
  2555. __if_exists(_Module) \
  2556. { \
  2557. return _Module.UpdateRegistryFromResource(_T(#x), bRegister); \
  2558. } \
  2559. __if_not_exists(_Module) \
  2560. { \
  2561. return ATL::_pAtlModule->UpdateRegistryFromResource(_T(#x), bRegister); \
  2562. } \
  2563. } \
  2564. }
  2565.  
  2566. #define DECLARE_REGISTRY_RESOURCEID(x)\
  2567. static HRESULT WINAPI UpdateRegistry(BOOL bRegister) throw()\
  2568. {\
  2569. __if_exists(_GetMiscStatus) \
  2570. { \
  2571. ATL::_ATL_REGMAP_ENTRY regMapEntries[2]; \
  2572. memset(&regMapEntries[1], 0, sizeof(ATL::_ATL_REGMAP_ENTRY)); \
  2573. regMapEntries[0].szKey = L"OLEMISC"; \
  2574. TCHAR szOleMisc[32]; \
  2575. ATL::Checked::itot_s(_GetMiscStatus(), szOleMisc, _countof(szOleMisc), 10); \
  2576. USES_CONVERSION_EX; \
  2577. regMapEntries[0].szData = T2OLE_EX(szOleMisc, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); \
  2578. if (regMapEntries[0].szData == NULL) \
  2579. return E_OUTOFMEMORY; \
  2580. __if_exists(_Module) \
  2581. { \
  2582. return _Module.UpdateRegistryFromResource(x, bRegister, regMapEntries); \
  2583. } \
  2584. __if_not_exists(_Module) \
  2585. { \
  2586. return ATL::_pAtlModule->UpdateRegistryFromResource(x, bRegister, regMapEntries); \
  2587. } \
  2588. } \
  2589. __if_not_exists(_GetMiscStatus) \
  2590. { \
  2591. __if_exists(_Module) \
  2592. { \
  2593. return _Module.UpdateRegistryFromResource(x, bRegister); \
  2594. } \
  2595. __if_not_exists(_Module) \
  2596. { \
  2597. return ATL::_pAtlModule->UpdateRegistryFromResource(x, bRegister); \
  2598. } \
  2599. } \
  2600. }
  2601.  
  2602. //DECLARE_STATIC_* provided for backward compatibility
  2603. #ifdef _ATL_STATIC_REGISTRY
  2604. #define DECLARE_STATIC_REGISTRY_RESOURCE(x) DECLARE_REGISTRY_RESOURCE(x)
  2605. #define DECLARE_STATIC_REGISTRY_RESOURCEID(x) DECLARE_REGISTRY_RESOURCEID(x)
  2606. #endif //_ATL_STATIC_REGISTRY
  2607.  
  2608. #define DECLARE_OLEMISC_STATUS(x) \
  2609. static DWORD _GetMiscStatus() throw() \
  2610. { \
  2611. static DWORD m_dwOleMisc = x; \
  2612. return m_dwOleMisc; \
  2613. }
  2614.  
  2615. template<class Base> class CComObject; // fwd decl
  2616.  
  2617. template <class Owner, class ThreadModel = CComObjectThreadModel>
  2618. class CComTearOffObjectBase : public CComObjectRootEx<ThreadModel>
  2619. {
  2620. public:
  2621. typedef Owner _OwnerClass;
  2622. Owner* m_pOwner;
  2623. CComTearOffObjectBase() {m_pOwner = NULL;}
  2624. };
  2625.  
  2626. //Base is the user's class that derives from CComObjectRoot and whatever
  2627. //interfaces the user wants to support on the object
  2628. template <class Base>
  2629. class CComObject : public Base
  2630. {
  2631. public:
  2632. typedef Base _BaseClass;
  2633. CComObject(void* = NULL) throw()
  2634. {
  2635. _pAtlModule->Lock();
  2636. }
  2637. // Set refcount to -(LONG_MAX/2) to protect destruction and
  2638. // also catch mismatched Release in debug builds
  2639. virtual ~CComObject() throw()
  2640. {
  2641. m_dwRef = -(LONG_MAX/2);
  2642. FinalRelease();
  2643. #ifdef _ATL_DEBUG_INTERFACES
  2644. _AtlDebugInterfacesModule.DeleteNonAddRefThunk(_GetRawUnknown());
  2645. #endif
  2646. _pAtlModule->Unlock();
  2647. }
  2648. //If InternalAddRef or InternalRelease is undefined then your class
  2649. //doesn't derive from CComObjectRoot
  2650. STDMETHOD_(ULONG, AddRef)() {return InternalAddRef();}
  2651. STDMETHOD_(ULONG, Release)()
  2652. {
  2653. ULONG l = InternalRelease();
  2654. if (l == 0)
  2655. delete this;
  2656. return l;
  2657. }
  2658. //if _InternalQueryInterface is undefined then you forgot BEGIN_COM_MAP
  2659. STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject) throw()
  2660. {return _InternalQueryInterface(iid, ppvObject);}
  2661. template <class Q>
  2662. HRESULT STDMETHODCALLTYPE QueryInterface(Q** pp) throw()
  2663. {
  2664. return QueryInterface(__uuidof(Q), (void**)pp);
  2665. }
  2666.  
  2667. static HRESULT WINAPI CreateInstance(CComObject<Base>** pp) throw();
  2668. };
  2669.  
  2670. template <class Base>
  2671. HRESULT WINAPI CComObject<Base>::CreateInstance(CComObject<Base>** pp) throw()
  2672. {
  2673. ATLASSERT(pp != NULL);
  2674. if (pp == NULL)
  2675. return E_POINTER;
  2676. *pp = NULL;
  2677.  
  2678. HRESULT hRes = E_OUTOFMEMORY;
  2679. CComObject<Base>* p = NULL;
  2680. ATLTRY(p = new CComObject<Base>())
  2681. if (p != NULL)
  2682. {
  2683. p->SetVoid(NULL);
  2684. p->InternalFinalConstructAddRef();
  2685. hRes = p->_AtlInitialConstruct();
  2686. if (SUCCEEDED(hRes))
  2687. hRes = p->FinalConstruct();
  2688. if (SUCCEEDED(hRes))
  2689. hRes = p->_AtlFinalConstruct();
  2690. p->InternalFinalConstructRelease();
  2691. if (hRes != S_OK)
  2692. {
  2693. delete p;
  2694. p = NULL;
  2695. }
  2696. }
  2697. *pp = p;
  2698. return hRes;
  2699. }
  2700.  
  2701. //Base is the user's class that derives from CComObjectRoot and whatever
  2702. //interfaces the user wants to support on the object
  2703. // CComObjectCached is used primarily for class factories in DLL's
  2704. // but it is useful anytime you want to cache an object
  2705. template <class Base>
  2706. class CComObjectCached : public Base
  2707. {
  2708. public:
  2709. typedef Base _BaseClass;
  2710. CComObjectCached(void* = NULL){}
  2711. // Set refcount to -(LONG_MAX/2) to protect destruction and
  2712. // also catch mismatched Release in debug builds
  2713. virtual ~CComObjectCached()
  2714. {
  2715. m_dwRef = -(LONG_MAX/2);
  2716. FinalRelease();
  2717. #ifdef _ATL_DEBUG_INTERFACES
  2718. _AtlDebugInterfacesModule.DeleteNonAddRefThunk(_GetRawUnknown());
  2719. #endif
  2720. }
  2721. //If InternalAddRef or InternalRelease is undefined then your class
  2722. //doesn't derive from CComObjectRoot
  2723. STDMETHOD_(ULONG, AddRef)() throw()
  2724. {
  2725. ULONG l = InternalAddRef();
  2726. if (l == 2)
  2727. _pAtlModule->Lock();
  2728. return l;
  2729. }
  2730. STDMETHOD_(ULONG, Release)() throw()
  2731. {
  2732. ULONG l = InternalRelease();
  2733. if (l == 0)
  2734. delete this;
  2735. else if (l == 1)
  2736. _pAtlModule->Unlock();
  2737. return l;
  2738. }
  2739. //if _InternalQueryInterface is undefined then you forgot BEGIN_COM_MAP
  2740. STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject) throw()
  2741. {return _InternalQueryInterface(iid, ppvObject);}
  2742. static HRESULT WINAPI CreateInstance(CComObjectCached<Base>** pp) throw();
  2743. };
  2744.  
  2745. template <class Base>
  2746. HRESULT WINAPI CComObjectCached<Base>::CreateInstance(CComObjectCached<Base>** pp) throw()
  2747. {
  2748. ATLASSERT(pp != NULL);
  2749. if (pp == NULL)
  2750. return E_POINTER;
  2751. *pp = NULL;
  2752.  
  2753. HRESULT hRes = E_OUTOFMEMORY;
  2754. CComObjectCached<Base>* p = NULL;
  2755. ATLTRY(p = new CComObjectCached<Base>())
  2756. if (p != NULL)
  2757. {
  2758. p->SetVoid(NULL);
  2759. p->InternalFinalConstructAddRef();
  2760. hRes = p->_AtlInitialConstruct();
  2761. if (SUCCEEDED(hRes))
  2762. hRes = p->FinalConstruct();
  2763. if (SUCCEEDED(hRes))
  2764. hRes = p->_AtlFinalConstruct();
  2765. p->InternalFinalConstructRelease();
  2766. if (hRes != S_OK)
  2767. {
  2768. delete p;
  2769. p = NULL;
  2770. }
  2771. }
  2772. *pp = p;
  2773. return hRes;
  2774. }
  2775.  
  2776.  
  2777. //Base is the user's class that derives from CComObjectRoot and whatever
  2778. //interfaces the user wants to support on the object
  2779. template <class Base>
  2780. class CComObjectNoLock : public Base
  2781. {
  2782. public:
  2783. typedef Base _BaseClass;
  2784. CComObjectNoLock(void* = NULL){}
  2785. // Set refcount to -(LONG_MAX/2) to protect destruction and
  2786. // also catch mismatched Release in debug builds
  2787.  
  2788. virtual ~CComObjectNoLock()
  2789. {
  2790. m_dwRef = -(LONG_MAX/2);
  2791. FinalRelease();
  2792. #ifdef _ATL_DEBUG_INTERFACES
  2793. _AtlDebugInterfacesModule.DeleteNonAddRefThunk(_GetRawUnknown());
  2794. #endif
  2795. }
  2796.  
  2797. //If InternalAddRef or InternalRelease is undefined then your class
  2798. //doesn't derive from CComObjectRoot
  2799. STDMETHOD_(ULONG, AddRef)() throw() {return InternalAddRef();}
  2800. STDMETHOD_(ULONG, Release)() throw()
  2801. {
  2802. ULONG l = InternalRelease();
  2803. if (l == 0)
  2804. delete this;
  2805. return l;
  2806. }
  2807. //if _InternalQueryInterface is undefined then you forgot BEGIN_COM_MAP
  2808. STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject) throw()
  2809. {return _InternalQueryInterface(iid, ppvObject);}
  2810. };
  2811.  
  2812.  
  2813. // It is possible for Base not to derive from CComObjectRoot
  2814. // However, you will need to provide _InternalQueryInterface
  2815. template <class Base>
  2816. class CComObjectGlobal : public Base
  2817. {
  2818. public:
  2819. typedef Base _BaseClass;
  2820. CComObjectGlobal(void* = NULL)
  2821. {
  2822. m_hResFinalConstruct = S_OK;
  2823. __if_exists(FinalConstruct)
  2824. {
  2825. __if_exists(InternalFinalConstructAddRef)
  2826. {
  2827. InternalFinalConstructAddRef();
  2828. }
  2829. m_hResFinalConstruct = _AtlInitialConstruct();
  2830. if (SUCCEEDED(m_hResFinalConstruct))
  2831. m_hResFinalConstruct = FinalConstruct();
  2832. __if_exists(InternalFinalConstructRelease)
  2833. {
  2834. InternalFinalConstructRelease();
  2835. }
  2836. }
  2837. }
  2838. virtual ~CComObjectGlobal()
  2839. {
  2840. __if_exists(FinalRelease)
  2841. {
  2842. FinalRelease();
  2843. }
  2844. #ifdef _ATL_DEBUG_INTERFACES
  2845. _AtlDebugInterfacesModule.DeleteNonAddRefThunk(_GetRawUnknown());
  2846. #endif
  2847. }
  2848.  
  2849. STDMETHOD_(ULONG, AddRef)() throw()
  2850. {
  2851. return _pAtlModule->Lock();
  2852. }
  2853. STDMETHOD_(ULONG, Release)() throw()
  2854. {
  2855. return _pAtlModule->Unlock();
  2856. }
  2857. STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject) throw()
  2858. {
  2859. return _InternalQueryInterface(iid, ppvObject);
  2860. }
  2861. HRESULT m_hResFinalConstruct;
  2862. };
  2863.  
  2864. // It is possible for Base not to derive from CComObjectRoot
  2865. // However, you will need to provide FinalConstruct and InternalQueryInterface
  2866. template <class Base>
  2867. class CComObjectStack : public Base
  2868. {
  2869. public:
  2870. typedef Base _BaseClass;
  2871. CComObjectStack(void* = NULL)
  2872. {
  2873. m_hResFinalConstruct = _AtlInitialConstruct();
  2874. if (SUCCEEDED(m_hResFinalConstruct))
  2875. m_hResFinalConstruct = FinalConstruct();
  2876. }
  2877. virtual ~CComObjectStack()
  2878. {
  2879. FinalRelease();
  2880. #ifdef _ATL_DEBUG_INTERFACES
  2881. _AtlDebugInterfacesModule.DeleteNonAddRefThunk(_GetRawUnknown());
  2882. #endif
  2883. }
  2884.  
  2885.  
  2886. STDMETHOD_(ULONG, AddRef)() throw() {ATLASSERT(FALSE);return 0;}
  2887. STDMETHOD_(ULONG, Release)() throw() {ATLASSERT(FALSE);return 0;}
  2888. STDMETHOD(QueryInterface)(REFIID, void**) throw()
  2889. {ATLASSERT(FALSE);return E_NOINTERFACE;}
  2890. HRESULT m_hResFinalConstruct;
  2891. };
  2892.  
  2893. // Base must be derived from CComObjectRoot
  2894. template <class Base>
  2895. class CComObjectStackEx : public Base
  2896. {
  2897. public:
  2898. typedef Base _BaseClass;
  2899.  
  2900. CComObjectStackEx(void* = NULL)
  2901. {
  2902. #ifdef _DEBUG
  2903. m_dwRef = 0;
  2904. #endif
  2905. m_hResFinalConstruct = _AtlInitialConstruct();
  2906. if (SUCCEEDED(m_hResFinalConstruct))
  2907. m_hResFinalConstruct = FinalConstruct();
  2908. }
  2909.  
  2910. virtual ~CComObjectStackEx()
  2911. {
  2912. // This assert indicates mismatched ref counts.
  2913. //
  2914. // The ref count has no control over the
  2915. // lifetime of this object, so you must ensure
  2916. // by some other means that the object remains
  2917. // alive while clients have references to its interfaces.
  2918. ATLASSUME(m_dwRef == 0);
  2919. FinalRelease();
  2920. #ifdef _ATL_DEBUG_INTERFACES
  2921. _AtlDebugInterfacesModule.DeleteNonAddRefThunk(_GetRawUnknown());
  2922. #endif
  2923. }
  2924.  
  2925. STDMETHOD_(ULONG, AddRef)() throw()
  2926. {
  2927. #ifdef _DEBUG
  2928. return InternalAddRef();
  2929. #else
  2930. return 0;
  2931. #endif
  2932. }
  2933.  
  2934. STDMETHOD_(ULONG, Release)() throw()
  2935. {
  2936. #ifdef _DEBUG
  2937. return InternalRelease();
  2938. #else
  2939. return 0;
  2940. #endif
  2941. }
  2942.  
  2943. STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject) throw()
  2944. {
  2945. return _InternalQueryInterface(iid, ppvObject);
  2946. }
  2947.  
  2948. HRESULT m_hResFinalConstruct;
  2949. };
  2950.  
  2951. template <class Base> //Base must be derived from CComObjectRoot
  2952. class CComContainedObject : public Base
  2953. {
  2954. public:
  2955. typedef Base _BaseClass;
  2956. CComContainedObject(void* pv) {m_pOuterUnknown = (IUnknown*)pv;}
  2957. #ifdef _ATL_DEBUG_INTERFACES
  2958. virtual ~CComContainedObject()
  2959. {
  2960. _AtlDebugInterfacesModule.DeleteNonAddRefThunk(_GetRawUnknown());
  2961. _AtlDebugInterfacesModule.DeleteNonAddRefThunk(m_pOuterUnknown);
  2962. }
  2963. #endif
  2964.  
  2965. STDMETHOD_(ULONG, AddRef)() throw() {return OuterAddRef();}
  2966. STDMETHOD_(ULONG, Release)() throw() {return OuterRelease();}
  2967. STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject) throw()
  2968. {
  2969. return OuterQueryInterface(iid, ppvObject);
  2970. }
  2971. template <class Q>
  2972. HRESULT STDMETHODCALLTYPE QueryInterface(Q** pp)
  2973. {
  2974. return QueryInterface(__uuidof(Q), (void**)pp);
  2975. }
  2976. //GetControllingUnknown may be virtual if the Base class has declared
  2977. //DECLARE_GET_CONTROLLING_UNKNOWN()
  2978. IUnknown* GetControllingUnknown() throw()
  2979. {
  2980. #ifdef _ATL_DEBUG_INTERFACES
  2981. IUnknown* p;
  2982. _AtlDebugInterfacesModule.AddNonAddRefThunk(m_pOuterUnknown, _T("CComContainedObject"), &p);
  2983. return p;
  2984. #else
  2985. return m_pOuterUnknown;
  2986. #endif
  2987. }
  2988. };
  2989.  
  2990. //contained is the user's class that derives from CComObjectRoot and whatever
  2991. //interfaces the user wants to support on the object
  2992. template <class contained>
  2993. class CComAggObject :
  2994. public IUnknown,
  2995. public CComObjectRootEx< typename contained::_ThreadModel::ThreadModelNoCS >
  2996. {
  2997. public:
  2998. typedef contained _BaseClass;
  2999. CComAggObject(void* pv) : m_contained(pv)
  3000. {
  3001. _pAtlModule->Lock();
  3002. }
  3003. HRESULT _AtlInitialConstruct()
  3004. {
  3005. HRESULT hr = m_contained._AtlInitialConstruct();
  3006. if (SUCCEEDED(hr))
  3007. {
  3008. hr = CComObjectRootEx< typename contained::_ThreadModel::ThreadModelNoCS >::_AtlInitialConstruct();
  3009. }
  3010. return hr;
  3011. }
  3012. //If you get a message that this call is ambiguous then you need to
  3013. // override it in your class and call each base class' version of this
  3014. HRESULT FinalConstruct()
  3015. {
  3016. CComObjectRootEx<contained::_ThreadModel::ThreadModelNoCS>::FinalConstruct();
  3017. return m_contained.FinalConstruct();
  3018. }
  3019. void FinalRelease()
  3020. {
  3021. CComObjectRootEx<contained::_ThreadModel::ThreadModelNoCS>::FinalRelease();
  3022. m_contained.FinalRelease();
  3023. }
  3024. // Set refcount to -(LONG_MAX/2) to protect destruction and
  3025. // also catch mismatched Release in debug builds
  3026. virtual ~CComAggObject()
  3027. {
  3028. m_dwRef = -(LONG_MAX/2);
  3029. FinalRelease();
  3030. #ifdef _ATL_DEBUG_INTERFACES
  3031. _AtlDebugInterfacesModule.DeleteNonAddRefThunk(this);
  3032. #endif
  3033. _pAtlModule->Unlock();
  3034. }
  3035.  
  3036. STDMETHOD_(ULONG, AddRef)() {return InternalAddRef();}
  3037. STDMETHOD_(ULONG, Release)()
  3038. {
  3039. ULONG l = InternalRelease();
  3040. if (l == 0)
  3041. delete this;
  3042. return l;
  3043. }
  3044. STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject)
  3045. {
  3046. ATLASSERT(ppvObject != NULL);
  3047. if (ppvObject == NULL)
  3048. return E_POINTER;
  3049. *ppvObject = NULL;
  3050.  
  3051. HRESULT hRes = S_OK;
  3052. if (InlineIsEqualUnknown(iid))
  3053. {
  3054. *ppvObject = (void*)(IUnknown*)this;
  3055. AddRef();
  3056. #ifdef _ATL_DEBUG_INTERFACES
  3057. _AtlDebugInterfacesModule.AddThunk((IUnknown**)ppvObject, (LPCTSTR)contained::_GetEntries()[-1].dw, iid);
  3058. #endif // _ATL_DEBUG_INTERFACES
  3059. }
  3060. else
  3061. hRes = m_contained._InternalQueryInterface(iid, ppvObject);
  3062. return hRes;
  3063. }
  3064. template <class Q>
  3065. HRESULT STDMETHODCALLTYPE QueryInterface(Q** pp)
  3066. {
  3067. return QueryInterface(__uuidof(Q), (void**)pp);
  3068. }
  3069. static HRESULT WINAPI CreateInstance(LPUNKNOWN pUnkOuter, CComAggObject<contained>** pp)
  3070. {
  3071. ATLASSERT(pp != NULL);
  3072. if (pp == NULL)
  3073. return E_POINTER;
  3074. *pp = NULL;
  3075.  
  3076. HRESULT hRes = E_OUTOFMEMORY;
  3077. CComAggObject<contained>* p = NULL;
  3078. ATLTRY(p = new CComAggObject<contained>(pUnkOuter))
  3079. if (p != NULL)
  3080. {
  3081. p->SetVoid(NULL);
  3082. p->InternalFinalConstructAddRef();
  3083. hRes = p->_AtlInitialConstruct();
  3084. if (SUCCEEDED(hRes))
  3085. hRes = p->FinalConstruct();
  3086. if (SUCCEEDED(hRes))
  3087. hRes = p->_AtlFinalConstruct();
  3088. p->InternalFinalConstructRelease();
  3089. if (hRes != S_OK)
  3090. {
  3091. delete p;
  3092. p = NULL;
  3093. }
  3094. }
  3095. *pp = p;
  3096. return hRes;
  3097. }
  3098.  
  3099. CComContainedObject<contained> m_contained;
  3100. };
  3101.  
  3102. ///////////////////////////////////////////////////////////////////////////////
  3103. // CComPolyObject can be either aggregated or not aggregated
  3104.  
  3105. template <class contained>
  3106. class CComPolyObject :
  3107. public IUnknown,
  3108. public CComObjectRootEx< typename contained::_ThreadModel::ThreadModelNoCS >
  3109. {
  3110. public:
  3111. typedef contained _BaseClass;
  3112. CComPolyObject(void* pv) : m_contained(pv ? pv : this)
  3113. {
  3114. _pAtlModule->Lock();
  3115. }
  3116. HRESULT _AtlInitialConstruct()
  3117. {
  3118. HRESULT hr = m_contained._AtlInitialConstruct();
  3119. if (SUCCEEDED(hr))
  3120. {
  3121. hr = CComObjectRootEx< typename contained::_ThreadModel::ThreadModelNoCS >::_AtlInitialConstruct();
  3122. }
  3123. return hr;
  3124. }
  3125. //If you get a message that this call is ambiguous then you need to
  3126. // override it in your class and call each base class' version of this
  3127. HRESULT FinalConstruct()
  3128. {
  3129. InternalAddRef();
  3130. CComObjectRootEx<contained::_ThreadModel::ThreadModelNoCS>::FinalConstruct();
  3131. HRESULT hr = m_contained.FinalConstruct();
  3132. InternalRelease();
  3133. return hr;
  3134. }
  3135. void FinalRelease()
  3136. {
  3137. CComObjectRootEx<contained::_ThreadModel::ThreadModelNoCS>::FinalRelease();
  3138. m_contained.FinalRelease();
  3139. }
  3140. // Set refcount to -(LONG_MAX/2) to protect destruction and
  3141. // also catch mismatched Release in debug builds
  3142. virtual ~CComPolyObject()
  3143. {
  3144. m_dwRef = -(LONG_MAX/2);
  3145. FinalRelease();
  3146. #ifdef _ATL_DEBUG_INTERFACES
  3147. _AtlDebugInterfacesModule.DeleteNonAddRefThunk(this);
  3148. #endif
  3149. _pAtlModule->Unlock();
  3150. }
  3151.  
  3152. STDMETHOD_(ULONG, AddRef)() {return InternalAddRef();}
  3153. STDMETHOD_(ULONG, Release)()
  3154. {
  3155. ULONG l = InternalRelease();
  3156. if (l == 0)
  3157. delete this;
  3158. return l;
  3159. }
  3160. STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject)
  3161. {
  3162. #ifndef _ATL_OLEDB_CONFORMANCE_TESTS
  3163. ATLASSERT(ppvObject != NULL);
  3164. #endif
  3165. if (ppvObject == NULL)
  3166. return E_POINTER;
  3167. *ppvObject = NULL;
  3168.  
  3169. HRESULT hRes = S_OK;
  3170. if (InlineIsEqualUnknown(iid))
  3171. {
  3172. *ppvObject = (void*)(IUnknown*)this;
  3173. AddRef();
  3174. #ifdef _ATL_DEBUG_INTERFACES
  3175. _AtlDebugInterfacesModule.AddThunk((IUnknown**)ppvObject, (LPCTSTR)contained::_GetEntries()[-1].dw, iid);
  3176. #endif // _ATL_DEBUG_INTERFACES
  3177. }
  3178. else
  3179. hRes = m_contained._InternalQueryInterface(iid, ppvObject);
  3180. return hRes;
  3181. }
  3182. template <class Q>
  3183. HRESULT STDMETHODCALLTYPE QueryInterface(Q** pp)
  3184. {
  3185. return QueryInterface(__uuidof(Q), (void**)pp);
  3186. }
  3187. static HRESULT WINAPI CreateInstance(LPUNKNOWN pUnkOuter, CComPolyObject<contained>** pp)
  3188. {
  3189. ATLASSERT(pp != NULL);
  3190. if (pp == NULL)
  3191. return E_POINTER;
  3192. *pp = NULL;
  3193.  
  3194.  
  3195. HRESULT hRes = E_OUTOFMEMORY;
  3196. CComPolyObject<contained>* p = NULL;
  3197. ATLTRY(p = new CComPolyObject<contained>(pUnkOuter))
  3198. if (p != NULL)
  3199. {
  3200. p->SetVoid(NULL);
  3201. p->InternalFinalConstructAddRef();
  3202. hRes = p->_AtlInitialConstruct();
  3203. if (SUCCEEDED(hRes))
  3204. hRes = p->FinalConstruct();
  3205. if (SUCCEEDED(hRes))
  3206. hRes = p->_AtlFinalConstruct();
  3207. p->InternalFinalConstructRelease();
  3208. if (hRes != S_OK)
  3209. {
  3210. delete p;
  3211. p = NULL;
  3212. }
  3213. }
  3214. *pp = p;
  3215. return hRes;
  3216. }
  3217.  
  3218. CComContainedObject<contained> m_contained;
  3219. };
  3220.  
  3221. template <class Base>
  3222. class CComTearOffObject : public Base
  3223. {
  3224. public:
  3225. CComTearOffObject(void* pv)
  3226. {
  3227. ATLASSUME(m_pOwner == NULL);
  3228. m_pOwner = reinterpret_cast<Base::_OwnerClass*>(pv);
  3229. m_pOwner->AddRef();
  3230. }
  3231. // Set refcount to -(LONG_MAX/2) to protect destruction and
  3232. // also catch mismatched Release in debug builds
  3233. virtual ~CComTearOffObject()
  3234. {
  3235. m_dwRef = -(LONG_MAX/2);
  3236. FinalRelease();
  3237. #ifdef _ATL_DEBUG_INTERFACES
  3238. _AtlDebugInterfacesModule.DeleteNonAddRefThunk(_GetRawUnknown());
  3239. #endif
  3240. m_pOwner->Release();
  3241. }
  3242.  
  3243. STDMETHOD_(ULONG, AddRef)() throw() {return InternalAddRef();}
  3244. STDMETHOD_(ULONG, Release)() throw()
  3245. {
  3246. ULONG l = InternalRelease();
  3247. if (l == 0)
  3248. delete this;
  3249. return l;
  3250. }
  3251. STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject) throw()
  3252. {
  3253. return m_pOwner->QueryInterface(iid, ppvObject);
  3254. }
  3255. };
  3256.  
  3257. template <class contained>
  3258. class CComCachedTearOffObject :
  3259. public IUnknown,
  3260. public CComObjectRootEx<typename contained::_ThreadModel::ThreadModelNoCS>
  3261. {
  3262. public:
  3263. typedef contained _BaseClass;
  3264. CComCachedTearOffObject(void* pv) :
  3265. m_contained(((contained::_OwnerClass*)pv)->GetControllingUnknown())
  3266. {
  3267. ATLASSUME(m_contained.m_pOwner == NULL);
  3268. m_contained.m_pOwner = reinterpret_cast<contained::_OwnerClass*>(pv);
  3269. }
  3270. HRESULT _AtlInitialConstruct()
  3271. {
  3272. HRESULT hr = m_contained._AtlInitialConstruct();
  3273. if (SUCCEEDED(hr))
  3274. {
  3275. hr = CComObjectRootEx< typename contained::_ThreadModel::ThreadModelNoCS >::_AtlInitialConstruct();
  3276. }
  3277. return hr;
  3278. }
  3279. //If you get a message that this call is ambiguous then you need to
  3280. // override it in your class and call each base class' version of this
  3281. HRESULT FinalConstruct()
  3282. {
  3283. CComObjectRootEx<contained::_ThreadModel::ThreadModelNoCS>::FinalConstruct();
  3284. return m_contained.FinalConstruct();
  3285. }
  3286. void FinalRelease()
  3287. {
  3288. CComObjectRootEx<contained::_ThreadModel::ThreadModelNoCS>::FinalRelease();
  3289. m_contained.FinalRelease();
  3290. }
  3291. // Set refcount to -(LONG_MAX/2) to protect destruction and
  3292. // also catch mismatched Release in debug builds
  3293. virtual ~CComCachedTearOffObject()
  3294. {
  3295. m_dwRef = -(LONG_MAX/2);
  3296. FinalRelease();
  3297. #ifdef _ATL_DEBUG_INTERFACES
  3298. _AtlDebugInterfacesModule.DeleteNonAddRefThunk(this);
  3299. #endif
  3300. }
  3301.  
  3302.  
  3303. STDMETHOD_(ULONG, AddRef)() {return InternalAddRef();}
  3304. STDMETHOD_(ULONG, Release)()
  3305. {
  3306. ULONG l = InternalRelease();
  3307. if (l == 0)
  3308. delete this;
  3309. return l;
  3310. }
  3311. STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject)
  3312. {
  3313. ATLASSERT(ppvObject != NULL);
  3314. if (ppvObject == NULL)
  3315. return E_POINTER;
  3316. *ppvObject = NULL;
  3317.  
  3318. HRESULT hRes = S_OK;
  3319. if (InlineIsEqualUnknown(iid))
  3320. {
  3321. *ppvObject = (void*)(IUnknown*)this;
  3322. AddRef();
  3323. #ifdef _ATL_DEBUG_INTERFACES
  3324. _AtlDebugInterfacesModule.AddThunk((IUnknown**)ppvObject, (LPCTSTR)contained::_GetEntries()[-1].dw, iid);
  3325. #endif // _ATL_DEBUG_INTERFACES
  3326. }
  3327. else
  3328. hRes = m_contained._InternalQueryInterface(iid, ppvObject);
  3329. return hRes;
  3330. }
  3331. CComContainedObject<contained> m_contained;
  3332. };
  3333.  
  3334.  
  3335. class CComClassFactory :
  3336. public IClassFactory,
  3337. public CComObjectRootEx<CComGlobalsThreadModel>
  3338. {
  3339. public:
  3340. BEGIN_COM_MAP(CComClassFactory)
  3341. COM_INTERFACE_ENTRY(IClassFactory)
  3342. END_COM_MAP()
  3343.  
  3344. virtual ~CComClassFactory()
  3345. {
  3346. }
  3347.  
  3348. // IClassFactory
  3349. STDMETHOD(CreateInstance)(LPUNKNOWN pUnkOuter, REFIID riid, void** ppvObj)
  3350. {
  3351. ATLASSUME(m_pfnCreateInstance != NULL);
  3352. HRESULT hRes = E_POINTER;
  3353. if (ppvObj != NULL)
  3354. {
  3355. *ppvObj = NULL;
  3356. // can't ask for anything other than IUnknown when aggregating
  3357.  
  3358. if ((pUnkOuter != NULL) && !InlineIsEqualUnknown(riid))
  3359. {
  3360. ATLTRACE(atlTraceCOM, 0, _T("CComClassFactory: asked for non IUnknown interface while creating an aggregated object"));
  3361. hRes = CLASS_E_NOAGGREGATION;
  3362. }
  3363. else
  3364. hRes = m_pfnCreateInstance(pUnkOuter, riid, ppvObj);
  3365. }
  3366. return hRes;
  3367. }
  3368.  
  3369. STDMETHOD(LockServer)(BOOL fLock)
  3370. {
  3371. if (fLock)
  3372. _pAtlModule->Lock();
  3373. else
  3374. _pAtlModule->Unlock();
  3375. return S_OK;
  3376. }
  3377. // helper
  3378. void SetVoid(void* pv)
  3379. {
  3380. m_pfnCreateInstance = (_ATL_CREATORFUNC*)pv;
  3381. }
  3382. _ATL_CREATORFUNC* m_pfnCreateInstance;
  3383. };
  3384.  
  3385. template <class license>
  3386. class CComClassFactory2 :
  3387. public IClassFactory2,
  3388. public CComObjectRootEx<CComGlobalsThreadModel>,
  3389. public license
  3390. {
  3391. public:
  3392. typedef license _LicenseClass;
  3393. typedef CComClassFactory2<license> _ComMapClass;
  3394. BEGIN_COM_MAP(CComClassFactory2<license>)
  3395. COM_INTERFACE_ENTRY(IClassFactory)
  3396. COM_INTERFACE_ENTRY(IClassFactory2)
  3397. END_COM_MAP()
  3398. // IClassFactory
  3399. STDMETHOD(LockServer)(BOOL fLock)
  3400. {
  3401. if (fLock)
  3402. _pAtlModule->Lock();
  3403. else
  3404. _pAtlModule->Unlock();
  3405. return S_OK;
  3406. }
  3407. STDMETHOD(CreateInstance)(LPUNKNOWN pUnkOuter,
  3408. REFIID riid, void** ppvObj)
  3409. {
  3410. ATLASSUME(m_pfnCreateInstance != NULL);
  3411. if (ppvObj == NULL)
  3412. return E_POINTER;
  3413. *ppvObj = NULL;
  3414. if (!IsLicenseValid())
  3415. return CLASS_E_NOTLICENSED;
  3416.  
  3417. if ((pUnkOuter != NULL) && !InlineIsEqualUnknown(riid))
  3418. return CLASS_E_NOAGGREGATION;
  3419. else
  3420. return m_pfnCreateInstance(pUnkOuter, riid, ppvObj);
  3421. }
  3422. // IClassFactory2
  3423. STDMETHOD(CreateInstanceLic)(IUnknown* pUnkOuter,
  3424. IUnknown* /* pUnkReserved */, REFIID riid, BSTR bstrKey,
  3425. void** ppvObject)
  3426. {
  3427. ATLASSUME(m_pfnCreateInstance != NULL);
  3428. if (ppvObject == NULL)
  3429. return E_POINTER;
  3430. *ppvObject = NULL;
  3431. if ( ((bstrKey != NULL) && !VerifyLicenseKey(bstrKey)) ||
  3432. ((bstrKey == NULL) && !IsLicenseValid()) )
  3433. return CLASS_E_NOTLICENSED;
  3434. if ((pUnkOuter != NULL) && !InlineIsEqualUnknown(riid))
  3435. return CLASS_E_NOAGGREGATION;
  3436. else
  3437. return m_pfnCreateInstance(pUnkOuter, riid, ppvObject);
  3438. }
  3439. STDMETHOD(RequestLicKey)(DWORD dwReserved, BSTR* pbstrKey)
  3440. {
  3441. if (pbstrKey == NULL)
  3442. return E_POINTER;
  3443. *pbstrKey = NULL;
  3444.  
  3445. if (!IsLicenseValid())
  3446. return CLASS_E_NOTLICENSED;
  3447. return GetLicenseKey(dwReserved,pbstrKey) ? S_OK : E_FAIL;
  3448. }
  3449. STDMETHOD(GetLicInfo)(LICINFO* pLicInfo)
  3450. {
  3451. if (pLicInfo == NULL)
  3452. return E_POINTER;
  3453. pLicInfo->cbLicInfo = sizeof(LICINFO);
  3454. pLicInfo->fLicVerified = IsLicenseValid();
  3455. BSTR bstr = NULL;
  3456. pLicInfo->fRuntimeKeyAvail = GetLicenseKey(0,&bstr);
  3457. ::SysFreeString(bstr);
  3458. return S_OK;
  3459. }
  3460. void SetVoid(void* pv)
  3461. {
  3462. m_pfnCreateInstance = (_ATL_CREATORFUNC*)pv;
  3463. }
  3464. _ATL_CREATORFUNC* m_pfnCreateInstance;
  3465. };
  3466.  
  3467. /////////////////////////////////////////////////////////////////////////////////////////////
  3468. // Thread Pooling class factory
  3469. class CComClassFactoryAutoThread :
  3470. public IClassFactory,
  3471. public CComObjectRootEx<CComGlobalsThreadModel>
  3472. {
  3473. public:
  3474. BEGIN_COM_MAP(CComClassFactoryAutoThread)
  3475. COM_INTERFACE_ENTRY(IClassFactory)
  3476. END_COM_MAP()
  3477.  
  3478. virtual ~CComClassFactoryAutoThread()
  3479. {
  3480. }
  3481.  
  3482. // helper
  3483. void SetVoid(void* pv)
  3484. {
  3485. m_pfnCreateInstance = (_ATL_CREATORFUNC*)pv;
  3486. }
  3487. STDMETHODIMP CreateInstance(LPUNKNOWN pUnkOuter,
  3488. REFIID riid, void** ppvObj)
  3489. {
  3490. ATLASSUME(m_pfnCreateInstance != NULL);
  3491. HRESULT hRes = E_POINTER;
  3492. if (ppvObj != NULL)
  3493. {
  3494. *ppvObj = NULL;
  3495. // cannot aggregate across apartments
  3496. ATLASSERT(pUnkOuter == NULL);
  3497. if (pUnkOuter != NULL)
  3498. hRes = CLASS_E_NOAGGREGATION;
  3499. else
  3500. {
  3501. ATLASSERT(_pAtlAutoThreadModule && _T("Global instance of CAtlAutoThreadModule not declared"));
  3502. if (_pAtlAutoThreadModule == NULL)
  3503. return E_FAIL;
  3504.  
  3505. hRes = _pAtlAutoThreadModule->CreateInstance(m_pfnCreateInstance, riid, ppvObj);
  3506. }
  3507. }
  3508. return hRes;
  3509. }
  3510. STDMETHODIMP LockServer(BOOL fLock)
  3511. {
  3512. if (fLock)
  3513. _pAtlModule->Lock();
  3514. else
  3515. _pAtlModule->Unlock();
  3516. return S_OK;
  3517. }
  3518. _ATL_CREATORFUNC* m_pfnCreateInstance;
  3519. };
  3520.  
  3521.  
  3522. /////////////////////////////////////////////////////////////////////////////////////////////
  3523. // Singleton Class Factory
  3524. template <class T>
  3525. class CComClassFactorySingleton : public CComClassFactory
  3526. {
  3527. public:
  3528. CComClassFactorySingleton() : m_hrCreate(S_OK)
  3529. {
  3530. }
  3531. virtual ~CComClassFactorySingleton()
  3532. {
  3533. }
  3534. // IClassFactory
  3535. STDMETHOD(CreateInstance)(LPUNKNOWN pUnkOuter, REFIID riid, void** ppvObj)
  3536. {
  3537. HRESULT hRes = E_POINTER;
  3538. if (ppvObj != NULL)
  3539. {
  3540. *ppvObj = NULL;
  3541. // aggregation is not supported in Singletons
  3542. ATLASSERT(pUnkOuter == NULL);
  3543. if (pUnkOuter != NULL)
  3544. hRes = CLASS_E_NOAGGREGATION;
  3545. else
  3546. {
  3547. if (m_hrCreate == S_OK && m_spObj == NULL)
  3548. {
  3549. __try
  3550. {
  3551. Lock();
  3552. // Did another thread get here first?
  3553. if (m_hrCreate == S_OK && m_spObj == NULL)
  3554. {
  3555. CComObjectCached<T> *p;
  3556. m_hrCreate = CComObjectCached<T>::CreateInstance(&p);
  3557. if (SUCCEEDED(m_hrCreate))
  3558. {
  3559. m_hrCreate = p->QueryInterface(IID_IUnknown, (void**)&m_spObj);
  3560. if (FAILED(m_hrCreate))
  3561. {
  3562. delete p;
  3563. }
  3564. }
  3565. }
  3566. }
  3567. __finally
  3568. {
  3569. Unlock();
  3570. }
  3571. }
  3572. if (m_hrCreate == S_OK)
  3573. {
  3574. hRes = m_spObj->QueryInterface(riid, ppvObj);
  3575. }
  3576. else
  3577. {
  3578. hRes = m_hrCreate;
  3579. }
  3580. }
  3581. }
  3582. return hRes;
  3583. }
  3584. HRESULT m_hrCreate;
  3585. CComPtr<IUnknown> m_spObj;
  3586. };
  3587.  
  3588.  
  3589. template <class T, const CLSID* pclsid = &CLSID_NULL>
  3590. class CComCoClass
  3591. {
  3592. public:
  3593. DECLARE_CLASSFACTORY()
  3594. DECLARE_AGGREGATABLE(T)
  3595. typedef T _CoClass;
  3596. static const CLSID& WINAPI GetObjectCLSID() {return *pclsid;}
  3597. static LPCTSTR WINAPI GetObjectDescription() {return NULL;}
  3598. static HRESULT WINAPI Error(LPCOLESTR lpszDesc,
  3599. const IID& iid = GUID_NULL, HRESULT hRes = 0)
  3600. {
  3601. return AtlReportError(GetObjectCLSID(), lpszDesc, iid, hRes);
  3602. }
  3603. static HRESULT WINAPI Error(LPCOLESTR lpszDesc, DWORD dwHelpID,
  3604. LPCOLESTR lpszHelpFile, const IID& iid = GUID_NULL, HRESULT hRes = 0)
  3605. {
  3606. return AtlReportError(GetObjectCLSID(), lpszDesc, dwHelpID, lpszHelpFile,
  3607. iid, hRes);
  3608. }
  3609. static HRESULT WINAPI Error(UINT nID, const IID& iid = GUID_NULL,
  3610. HRESULT hRes = 0, HINSTANCE hInst = _AtlBaseModule.GetResourceInstance())
  3611. {
  3612. return AtlReportError(GetObjectCLSID(), nID, iid, hRes, hInst);
  3613. }
  3614. static HRESULT WINAPI Error(UINT nID, DWORD dwHelpID,
  3615. LPCOLESTR lpszHelpFile, const IID& iid = GUID_NULL,
  3616. HRESULT hRes = 0, HINSTANCE hInst = _AtlBaseModule.GetResourceInstance())
  3617. {
  3618. return AtlReportError(GetObjectCLSID(), nID, dwHelpID, lpszHelpFile,
  3619. iid, hRes, hInst);
  3620. }
  3621. static HRESULT WINAPI Error(LPCSTR lpszDesc,
  3622. const IID& iid = GUID_NULL, HRESULT hRes = 0)
  3623. {
  3624. return AtlReportError(GetObjectCLSID(), lpszDesc, iid, hRes);
  3625. }
  3626. static HRESULT WINAPI Error(LPCSTR lpszDesc, DWORD dwHelpID,
  3627. LPCSTR lpszHelpFile, const IID& iid = GUID_NULL, HRESULT hRes = 0)
  3628. {
  3629. return AtlReportError(GetObjectCLSID(), lpszDesc, dwHelpID,
  3630. lpszHelpFile, iid, hRes);
  3631. }
  3632. template <class Q>
  3633. static HRESULT CreateInstance(IUnknown* punkOuter, Q** pp)
  3634. {
  3635. return T::_CreatorClass::CreateInstance(punkOuter, __uuidof(Q), (void**) pp);
  3636. }
  3637. template <class Q>
  3638. static HRESULT CreateInstance(Q** pp)
  3639. {
  3640. return T::_CreatorClass::CreateInstance(NULL, __uuidof(Q), (void**) pp);
  3641. }
  3642. };
  3643.  
  3644. // ATL doesn't support multiple LCID's at the same time
  3645. // Whatever LCID is queried for first is the one that is used.
  3646. class CComTypeInfoHolder
  3647. {
  3648. // Should be 'protected' but can cause compiler to generate fat code.
  3649. public:
  3650. const GUID* m_pguid;
  3651. const GUID* m_plibid;
  3652. WORD m_wMajor;
  3653. WORD m_wMinor;
  3654.  
  3655. ITypeInfo* m_pInfo;
  3656. long m_dwRef;
  3657. struct stringdispid
  3658. {
  3659. CComBSTR bstr;
  3660. int nLen;
  3661. DISPID id;
  3662. stringdispid() : nLen(0), id(DISPID_UNKNOWN){}
  3663. };
  3664. stringdispid* m_pMap;
  3665. int m_nCount;
  3666.  
  3667. public:
  3668.  
  3669. #ifdef _ATL_DLL_IMPL
  3670. CComTypeInfoHolder(const GUID* pguid, const GUID* plibid, WORD wMajor, WORD wMinor) :
  3671. m_pguid(pguid), m_plibid(plibid), m_wMajor(wMajor), m_wMinor(wMinor),
  3672. m_pInfo(NULL), m_dwRef(0), m_pMap(NULL), m_nCount(0)
  3673. {
  3674. }
  3675.  
  3676. ~CComTypeInfoHolder()
  3677. {
  3678. if (m_pInfo != NULL)
  3679. m_pInfo->Release();
  3680. m_pInfo = NULL;
  3681. delete [] m_pMap;
  3682. m_pMap = NULL;
  3683. }
  3684. #endif
  3685.  
  3686. HRESULT GetTI(LCID lcid, ITypeInfo** ppInfo)
  3687. {
  3688. ATLASSERT(ppInfo != NULL);
  3689. if (ppInfo == NULL)
  3690. return E_POINTER;
  3691.  
  3692. HRESULT hr = S_OK;
  3693. if (m_pInfo == NULL)
  3694. hr = GetTI(lcid);
  3695. *ppInfo = m_pInfo;
  3696. if (m_pInfo != NULL)
  3697. {
  3698. m_pInfo->AddRef();
  3699. hr = S_OK;
  3700. }
  3701. return hr;
  3702. }
  3703. HRESULT GetTI(LCID lcid);
  3704. HRESULT EnsureTI(LCID lcid)
  3705. {
  3706. HRESULT hr = S_OK;
  3707. if (m_pInfo == NULL || m_pMap == NULL)
  3708. hr = GetTI(lcid);
  3709. return hr;
  3710. }
  3711.  
  3712. // This function is called by the module on exit
  3713. // It is registered through _pAtlModule->AddTermFunc()
  3714. static void __stdcall Cleanup(DWORD_PTR dw);
  3715.  
  3716. HRESULT GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo** pptinfo)
  3717. {
  3718. if (itinfo != 0)
  3719. {
  3720. return DISP_E_BADINDEX;
  3721. }
  3722. return GetTI(lcid, pptinfo);
  3723. }
  3724. HRESULT GetIDsOfNames(REFIID /* riid */, _In_count_(cNames) LPOLESTR* rgszNames, UINT cNames,
  3725. LCID lcid, DISPID* rgdispid)
  3726. {
  3727. HRESULT hRes = EnsureTI(lcid);
  3728. if (m_pInfo != NULL)
  3729. {
  3730. hRes = E_FAIL;
  3731. // Look in cache if
  3732. // cache is populated
  3733. // parameter names are not requested
  3734. if (m_pMap != NULL && cNames == 1)
  3735. {
  3736. int n = int( ocslen(rgszNames[0]) );
  3737. for (int j=m_nCount-1; j>=0; j--)
  3738. {
  3739. if ((n == m_pMap[j].nLen) &&
  3740. (memcmp(m_pMap[j].bstr, rgszNames[0], m_pMap[j].nLen * sizeof(OLECHAR)) == 0))
  3741. {
  3742. rgdispid[0] = m_pMap[j].id;
  3743. hRes = S_OK;
  3744. break;
  3745. }
  3746. }
  3747. }
  3748. // if cache is empty or name not in cache or parameter names are requested,
  3749. // delegate to ITypeInfo::GetIDsOfNames
  3750. if (FAILED(hRes))
  3751. {
  3752. hRes = m_pInfo->GetIDsOfNames(rgszNames, cNames, rgdispid);
  3753. }
  3754. }
  3755. return hRes;
  3756. }
  3757.  
  3758. HRESULT Invoke(IDispatch* p, DISPID dispidMember, REFIID /* riid */,
  3759. LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult,
  3760. EXCEPINFO* pexcepinfo, UINT* puArgErr)
  3761. {
  3762. HRESULT hRes = EnsureTI(lcid);
  3763. if (m_pInfo != NULL)
  3764. hRes = m_pInfo->Invoke(p, dispidMember, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr);
  3765. return hRes;
  3766. }
  3767. _Check_return_ HRESULT LoadNameCache(ITypeInfo* pTypeInfo)
  3768. {
  3769. TYPEATTR* pta;
  3770. HRESULT hr = pTypeInfo->GetTypeAttr(&pta);
  3771. if (SUCCEEDED(hr))
  3772. {
  3773. stringdispid* pMap = NULL;
  3774. m_nCount = pta->cFuncs;
  3775. m_pMap = NULL;
  3776. if (m_nCount != 0)
  3777. {
  3778. ATLTRY(pMap = new stringdispid[m_nCount]);
  3779. if (pMap == NULL)
  3780. {
  3781. pTypeInfo->ReleaseTypeAttr(pta);
  3782. return E_OUTOFMEMORY;
  3783. }
  3784. }
  3785. for (int i=0; i<m_nCount; i++)
  3786. {
  3787. FUNCDESC* pfd;
  3788. if (SUCCEEDED(pTypeInfo->GetFuncDesc(i, &pfd)))
  3789. {
  3790. CComBSTR bstrName;
  3791. if (SUCCEEDED(pTypeInfo->GetDocumentation(pfd->memid, &bstrName, NULL, NULL, NULL)))
  3792. {
  3793. pMap[i].bstr.Attach(bstrName.Detach());
  3794. pMap[i].nLen = SysStringLen(pMap[i].bstr);
  3795. pMap[i].id = pfd->memid;
  3796. }
  3797. pTypeInfo->ReleaseFuncDesc(pfd);
  3798. }
  3799. }
  3800. m_pMap = pMap;
  3801. pTypeInfo->ReleaseTypeAttr(pta);
  3802. }
  3803. return S_OK;
  3804. }
  3805. };
  3806.  
  3807. inline void __stdcall CComTypeInfoHolder::Cleanup(DWORD_PTR dw)
  3808. {
  3809. ATLASSERT(dw != 0);
  3810. if (dw == 0)
  3811. return;
  3812.  
  3813. CComTypeInfoHolder* p = (CComTypeInfoHolder*) dw;
  3814. if (p->m_pInfo != NULL)
  3815. p->m_pInfo->Release();
  3816. p->m_pInfo = NULL;
  3817. delete [] p->m_pMap;
  3818. p->m_pMap = NULL;
  3819. }
  3820.  
  3821. inline HRESULT CComTypeInfoHolder::GetTI(LCID lcid)
  3822. {
  3823. //If this assert occurs then most likely didn't initialize properly
  3824. ATLASSUME(m_plibid != NULL && m_pguid != NULL);
  3825.  
  3826. if (m_pInfo != NULL && m_pMap != NULL)
  3827. return S_OK;
  3828.  
  3829. CComCritSecLock<CComCriticalSection> lock(_pAtlModule->m_csStaticDataInitAndTypeInfo, false);
  3830. HRESULT hRes = lock.Lock();
  3831. if (FAILED(hRes))
  3832. {
  3833. ATLTRACE(atlTraceCOM, 0, _T("ERROR : Unable to lock critical section in CComTypeInfoHolder::GetTI\n"));
  3834. ATLASSERT(0);
  3835. return hRes;
  3836. }
  3837. hRes = E_FAIL;
  3838. if (m_pInfo == NULL)
  3839. {
  3840. ITypeLib* pTypeLib = NULL;
  3841. if (InlineIsEqualGUID(CAtlModule::m_libid, *m_plibid) && m_wMajor == 0xFFFF && m_wMinor == 0xFFFF)
  3842. {
  3843. TCHAR szFilePath[MAX_PATH];
  3844. DWORD dwFLen = ::GetModuleFileName(_AtlBaseModule.GetModuleInstance(), szFilePath, MAX_PATH);
  3845. if( dwFLen != 0 && dwFLen != MAX_PATH )
  3846. {
  3847. USES_CONVERSION_EX;
  3848. LPOLESTR pszFile = T2OLE_EX(szFilePath, _ATL_SAFE_ALLOCA_DEF_THRESHOLD);
  3849. #ifndef _UNICODE
  3850. if (pszFile == NULL)
  3851. return E_OUTOFMEMORY;
  3852. #endif
  3853. hRes = LoadTypeLib(pszFile, &pTypeLib);
  3854. }
  3855. }
  3856. else
  3857. {
  3858. ATLASSUME(!InlineIsEqualGUID(*m_plibid, GUID_NULL) && "Module LIBID not initialized. See DECLARE_LIBID documentation.");
  3859. hRes = LoadRegTypeLib(*m_plibid, m_wMajor, m_wMinor, lcid, &pTypeLib);
  3860. #ifdef _DEBUG
  3861. if (SUCCEEDED(hRes))
  3862. {
  3863. // Trace out an warning if the requested TypelibID is the same as the modules TypelibID
  3864. // and versions do not match.
  3865. //
  3866. // In most cases it is due to wrong version template parameters to IDispatchImpl,
  3867. // IProvideClassInfoImpl or IProvideClassInfo2Impl.
  3868. // Set major and minor versions to 0xFFFF if the modules type lib has to be loaded
  3869. // irrespective of its version.
  3870. //
  3871. // Get the module's file path
  3872. TCHAR szFilePath[MAX_PATH];
  3873. DWORD dwFLen = ::GetModuleFileName(_AtlBaseModule.GetModuleInstance(), szFilePath, MAX_PATH);
  3874. if( dwFLen != 0 && dwFLen != MAX_PATH )
  3875. {
  3876. USES_CONVERSION_EX;
  3877. CComPtr<ITypeLib> spTypeLibModule;
  3878. HRESULT hRes2 = S_OK;
  3879. LPOLESTR pszFile = T2OLE_EX(szFilePath, _ATL_SAFE_ALLOCA_DEF_THRESHOLD);
  3880. if (pszFile == NULL)
  3881. hRes2 = E_OUTOFMEMORY;
  3882. else
  3883. hRes2 = LoadTypeLib(pszFile, &spTypeLibModule);
  3884. if (SUCCEEDED(hRes2))
  3885. {
  3886. TLIBATTR* pLibAttr;
  3887. hRes2 = spTypeLibModule->GetLibAttr(&pLibAttr);
  3888. if (SUCCEEDED(hRes2))
  3889. {
  3890. if (InlineIsEqualGUID(pLibAttr->guid, *m_plibid) &&
  3891. (pLibAttr->wMajorVerNum != m_wMajor ||
  3892. pLibAttr->wMinorVerNum != m_wMinor))
  3893. {
  3894. ATLTRACE(atlTraceCOM, 0, _T("Warning : CComTypeInfoHolder::GetTI : Loaded typelib does not match the typelib in the module : %s\n"), szFilePath);
  3895. ATLTRACE(atlTraceCOM, 0, _T("\tSee IDispatchImpl overview help topic for more information\n"), szFilePath);
  3896. }
  3897. spTypeLibModule->ReleaseTLibAttr(pLibAttr);
  3898. }
  3899. }
  3900. }
  3901. }
  3902. else
  3903. {
  3904. ATLTRACE(atlTraceCOM, 0, _T("ERROR : Unable to load Typelibrary. (HRESULT = 0x%x)\n"), hRes);
  3905. ATLTRACE(atlTraceCOM, 0, _T("\tVerify TypelibID and major version specified with\n"));
  3906. ATLTRACE(atlTraceCOM, 0, _T("\tIDispatchImpl, CStockPropImpl, IProvideClassInfoImpl or IProvideCLassInfo2Impl\n"));
  3907. }
  3908. #endif
  3909. }
  3910. if (SUCCEEDED(hRes))
  3911. {
  3912. CComPtr<ITypeInfo> spTypeInfo;
  3913. hRes = pTypeLib->GetTypeInfoOfGuid(*m_pguid, &spTypeInfo);
  3914. if (SUCCEEDED(hRes))
  3915. {
  3916. CComPtr<ITypeInfo> spInfo(spTypeInfo);
  3917. CComPtr<ITypeInfo2> spTypeInfo2;
  3918. if (SUCCEEDED(spTypeInfo->QueryInterface(&spTypeInfo2)))
  3919. spInfo = spTypeInfo2;
  3920.  
  3921. m_pInfo = spInfo.Detach();
  3922. #ifndef _ATL_DLL_IMPL
  3923. _pAtlModule->AddTermFunc(Cleanup, (DWORD_PTR)this);
  3924. #endif
  3925. }
  3926. pTypeLib->Release();
  3927. }
  3928. }
  3929. else
  3930. {
  3931. // Another thread has loaded the typeinfo so we're OK.
  3932. hRes = S_OK;
  3933. }
  3934.  
  3935. if (m_pInfo != NULL && m_pMap == NULL)
  3936. {
  3937. hRes=LoadNameCache(m_pInfo);
  3938. }
  3939.  
  3940. return hRes;
  3941. }
  3942.  
  3943.  
  3944. //////////////////////////////////////////////////////////////////////////////
  3945. // IObjectWithSite
  3946. //
  3947. template <class T>
  3948. class ATL_NO_VTABLE IObjectWithSiteImpl : public IObjectWithSite
  3949. {
  3950. public:
  3951. virtual ~IObjectWithSiteImpl()
  3952. {
  3953. }
  3954.  
  3955. STDMETHOD(SetSite)(IUnknown *pUnkSite)
  3956. {
  3957. ATLTRACE(atlTraceCOM, 2, _T("IObjectWithSiteImpl::SetSite\n"));
  3958. T* pT = static_cast<T*>(this);
  3959. pT->m_spUnkSite = pUnkSite;
  3960. return S_OK;
  3961. }
  3962. STDMETHOD(GetSite)(REFIID riid, void **ppvSite)
  3963. {
  3964. ATLTRACE(atlTraceCOM, 2, _T("IObjectWithSiteImpl::GetSite\n"));
  3965. T* pT = static_cast<T*>(this);
  3966. ATLASSERT(ppvSite);
  3967. HRESULT hRes = E_POINTER;
  3968. if (ppvSite != NULL)
  3969. {
  3970. if (pT->m_spUnkSite)
  3971. hRes = pT->m_spUnkSite->QueryInterface(riid, ppvSite);
  3972. else
  3973. {
  3974. *ppvSite = NULL;
  3975. hRes = E_FAIL;
  3976. }
  3977. }
  3978. return hRes;
  3979. }
  3980.  
  3981. HRESULT SetChildSite(IUnknown* punkChild)
  3982. {
  3983. if (punkChild == NULL)
  3984. return E_POINTER;
  3985.  
  3986. HRESULT hr;
  3987. CComPtr<IObjectWithSite> spChildSite;
  3988. hr = punkChild->QueryInterface(__uuidof(IObjectWithSite), (void**)&spChildSite);
  3989. if (SUCCEEDED(hr))
  3990. hr = spChildSite->SetSite((IUnknown*)this);
  3991.  
  3992. return hr;
  3993. }
  3994.  
  3995. static HRESULT SetChildSite(IUnknown* punkChild, IUnknown* punkParent)
  3996. {
  3997. return AtlSetChildSite(punkChild, punkParent);
  3998. }
  3999.  
  4000. CComPtr<IUnknown> m_spUnkSite;
  4001. };
  4002.  
  4003. //////////////////////////////////////////////////////////////////////////////
  4004. // IServiceProvider
  4005. //
  4006. template <class T>
  4007. class ATL_NO_VTABLE IServiceProviderImpl : public IServiceProvider
  4008. {
  4009. public:
  4010. STDMETHOD(QueryService)(REFGUID guidService, REFIID riid, void** ppvObject)
  4011. {
  4012. ATLTRACE(atlTraceCOM, 2, _T("IServiceProviderImpl::QueryService\n"));
  4013.  
  4014. T* pT = static_cast<T*>(this);
  4015. return pT->_InternalQueryService(guidService, riid, ppvObject);
  4016. }
  4017. };
  4018.  
  4019. #define BEGIN_SERVICE_MAP(x) public: \
  4020. HRESULT _InternalQueryService(REFGUID guidService, REFIID riid, void** ppvObject) \
  4021. { \
  4022. ATLASSERT(ppvObject != NULL); \
  4023. if (ppvObject == NULL) \
  4024. return E_POINTER; \
  4025. *ppvObject = NULL;
  4026.  
  4027. #define SERVICE_ENTRY(x) \
  4028. if (InlineIsEqualGUID(guidService, x)) \
  4029. return QueryInterface(riid, ppvObject);
  4030.  
  4031. #define SERVICE_ENTRY_CHAIN(x) \
  4032. ATL::CComQIPtr<IServiceProvider, &__uuidof(IServiceProvider)> spProvider(x); \
  4033. if (spProvider != NULL) \
  4034. return spProvider->QueryService(guidService, riid, ppvObject);
  4035.  
  4036. #define END_SERVICE_MAP() \
  4037. return E_NOINTERFACE; \
  4038. }
  4039.  
  4040.  
  4041. /////////////////////////////////////////////////////////////////////////////
  4042. // IDispEventImpl
  4043.  
  4044. ATLAPI AtlGetObjectSourceInterface(IUnknown* punkObj, GUID* plibid, IID* piid, unsigned short* pdwMajor, unsigned short* pdwMinor);
  4045.  
  4046. #ifdef _M_IA64
  4047. template <class T>
  4048. class CComStdCallThunk
  4049. {
  4050. public:
  4051. typedef void (__stdcall T::*TMFP)();
  4052. void* pVtable;
  4053. void* pFunc;
  4054. _stdcallthunk thunk;
  4055. void Init(TMFP dw, void* pThis)
  4056. {
  4057. pVtable = &pFunc;
  4058. pFunc = &thunk;
  4059. union {
  4060. DWORD_PTR dwFunc;
  4061. TMFP pfn;
  4062. } pfn;
  4063. pfn.pfn = dw;
  4064. thunk.Init(pfn.dwFunc, pThis);
  4065. }
  4066. };
  4067.  
  4068. #elif defined ( _M_IX86 ) || defined ( _M_AMD64 )
  4069.  
  4070. extern "C"
  4071. {
  4072. void __stdcall CComStdCallThunkHelper();
  4073. }
  4074.  
  4075. template <class T>
  4076. class CComStdCallThunk
  4077. {
  4078. public:
  4079. typedef void (__stdcall T::*TMFP)();
  4080. void *pVTable; // pointer to artificial VTABLE
  4081. void *pThis; // pointer to the class
  4082. TMFP pfn; // Pointer to member function to call
  4083. void (__stdcall *pfnHelper)(); // Artificial VTABLE entry. Points to CComStdCallThunkHelper
  4084. // which modifies the stack and jumps to pfn
  4085.  
  4086. void Init(TMFP pf, void *p)
  4087. {
  4088. pfnHelper = CComStdCallThunkHelper;
  4089. pVTable = &pfnHelper;
  4090. pThis = p;
  4091. pfn = pf;
  4092. }
  4093. };
  4094. #else
  4095. #error X86, AMD64 and IA64
  4096. #endif // _M_IX86 |
  4097.  
  4098. #ifndef _ATL_MAX_VARTYPES
  4099. #define _ATL_MAX_VARTYPES 8
  4100. #endif
  4101.  
  4102. struct _ATL_FUNC_INFO
  4103. {
  4104. CALLCONV cc;
  4105. VARTYPE vtReturn;
  4106. SHORT nParams;
  4107. VARTYPE pVarTypes[_ATL_MAX_VARTYPES];
  4108. };
  4109.  
  4110. class ATL_NO_VTABLE _IDispEvent
  4111. {
  4112. public:
  4113. _IDispEvent() : m_libid(GUID_NULL), m_iid(IID_NULL), m_wMajorVerNum(0), m_wMinorVerNum(0), m_dwEventCookie(0xFEFEFEFE) { }
  4114. //this method needs a different name than QueryInterface
  4115. STDMETHOD(_LocDEQueryInterface)(REFIID riid, void ** ppvObject) = 0;
  4116. virtual ULONG STDMETHODCALLTYPE AddRef(void) = 0;
  4117. virtual ULONG STDMETHODCALLTYPE Release(void) = 0;
  4118. GUID m_libid; // used for dynamic case
  4119. IID m_iid; // used for dynamic case
  4120. unsigned short m_wMajorVerNum; // Major version number. used for dynamic case
  4121. unsigned short m_wMinorVerNum; // Minor version number. used for dynamic case
  4122. DWORD m_dwEventCookie;
  4123. HRESULT DispEventAdvise(IUnknown* pUnk, const IID* piid)
  4124. {
  4125. ATLENSURE(m_dwEventCookie == 0xFEFEFEFE);
  4126. return AtlAdvise(pUnk, (IUnknown*)this, *piid, &m_dwEventCookie);
  4127. }
  4128. HRESULT DispEventUnadvise(IUnknown* pUnk, const IID* piid)
  4129. {
  4130. HRESULT hr = AtlUnadvise(pUnk, *piid, m_dwEventCookie);
  4131. m_dwEventCookie = 0xFEFEFEFE;
  4132. return hr;
  4133. }
  4134. //---- add Advise & Unadvise for ease of calling from attribute code ----
  4135. HRESULT Advise(IUnknown *punk)
  4136. {
  4137. HRESULT hr = AtlGetObjectSourceInterface(punk, &m_libid, &m_iid, &m_wMajorVerNum, &m_wMinorVerNum);
  4138. if (FAILED(hr))
  4139. return hr;
  4140. return DispEventAdvise(punk, &m_iid);
  4141. }
  4142. HRESULT Unadvise(IUnknown *punk)
  4143. {
  4144. HRESULT hr = AtlGetObjectSourceInterface(punk, &m_libid, &m_iid, &m_wMajorVerNum, &m_wMinorVerNum);
  4145. if (FAILED(hr))
  4146. return hr;
  4147. return DispEventUnadvise(punk, &m_iid);
  4148. }
  4149. };
  4150.  
  4151. template <UINT nID, const IID* piid>
  4152. class ATL_NO_VTABLE _IDispEventLocator : public _IDispEvent
  4153. {
  4154. public:
  4155. };
  4156.  
  4157. template <UINT nID, class T, const IID* pdiid>
  4158. class ATL_NO_VTABLE IDispEventSimpleImpl : public _IDispEventLocator<nID, pdiid>
  4159. {
  4160. public:
  4161. STDMETHOD(_LocDEQueryInterface)(REFIID riid, void ** ppvObject)
  4162. {
  4163. ATLASSERT(ppvObject != NULL);
  4164. if (ppvObject == NULL)
  4165. return E_POINTER;
  4166. *ppvObject = NULL;
  4167.  
  4168. if (InlineIsEqualGUID(riid, IID_NULL))
  4169. return E_NOINTERFACE;
  4170.  
  4171. if (InlineIsEqualGUID(riid, *pdiid) ||
  4172. InlineIsEqualUnknown(riid) ||
  4173. InlineIsEqualGUID(riid, __uuidof(IDispatch)) ||
  4174. InlineIsEqualGUID(riid, m_iid))
  4175. {
  4176. *ppvObject = this;
  4177. AddRef();
  4178. #ifdef _ATL_DEBUG_INTERFACES
  4179. _AtlDebugInterfacesModule.AddThunk((IUnknown**)ppvObject, _T("IDispEventImpl"), riid);
  4180. #endif // _ATL_DEBUG_INTERFACES
  4181. return S_OK;
  4182. }
  4183. else
  4184. return E_NOINTERFACE;
  4185. }
  4186.  
  4187. // These are here only to support use in non-COM objects
  4188. virtual ULONG STDMETHODCALLTYPE AddRef()
  4189. {
  4190. return 1;
  4191. }
  4192. virtual ULONG STDMETHODCALLTYPE Release()
  4193. {
  4194. return 1;
  4195. }
  4196.  
  4197. STDMETHOD(GetTypeInfoCount)(UINT* /*pctinfo*/)
  4198. {ATLTRACENOTIMPL(_T("IDispEventSimpleImpl::GetTypeInfoCount"));}
  4199.  
  4200. STDMETHOD(GetTypeInfo)(UINT /*itinfo*/, LCID /*lcid*/, ITypeInfo** /*pptinfo*/)
  4201. {ATLTRACENOTIMPL(_T("IDispEventSimpleImpl::GetTypeInfo"));}
  4202.  
  4203. STDMETHOD(GetIDsOfNames)(REFIID /*riid*/, LPOLESTR* /*rgszNames*/, UINT /*cNames*/,
  4204. LCID /*lcid*/, DISPID* /*rgdispid*/)
  4205. {ATLTRACENOTIMPL(_T("IDispEventSimpleImpl::GetIDsOfNames"));}
  4206.  
  4207. STDMETHOD(Invoke)(DISPID dispidMember, REFIID /*riid*/,
  4208. LCID lcid, WORD /*wFlags*/, DISPPARAMS* pdispparams, VARIANT* pvarResult,
  4209. EXCEPINFO* /*pexcepinfo*/, UINT* /*puArgErr*/)
  4210. {
  4211. const _ATL_EVENT_ENTRY<T>* pMap = T::_GetSinkMap();
  4212. const _ATL_EVENT_ENTRY<T>* pFound = NULL;
  4213. while (pMap->piid != NULL)
  4214. {
  4215. if ((pMap->nControlID == nID) && (pMap->dispid == dispidMember) &&
  4216. (IsEqualIID(*(pMap->piid), *pdiid)))
  4217. {
  4218. pFound = pMap;
  4219. break;
  4220. }
  4221. pMap++;
  4222. }
  4223. if (pFound == NULL)
  4224. return S_OK;
  4225.  
  4226.  
  4227. _ATL_FUNC_INFO info;
  4228. _ATL_FUNC_INFO* pInfo;
  4229. if (pFound->pInfo != NULL)
  4230. pInfo = pFound->pInfo;
  4231. else
  4232. {
  4233. pInfo = &info;
  4234. HRESULT hr = GetFuncInfoFromId(*pdiid, dispidMember, lcid, info);
  4235. if (FAILED(hr))
  4236. return S_OK;
  4237. }
  4238. return InvokeFromFuncInfo(pFound->pfn, *pInfo, pdispparams, pvarResult);
  4239. }
  4240.  
  4241. //Helper for invoking the event
  4242. HRESULT InvokeFromFuncInfo(void (__stdcall T::*pEvent)(), _ATL_FUNC_INFO& info, DISPPARAMS* pdispparams, VARIANT* pvarResult)
  4243. {
  4244. ATLASSERT(pdispparams->cArgs == (UINT)info.nParams);
  4245.  
  4246. T* pT = static_cast<T*>(this);
  4247.  
  4248. // If this assert occurs, then add
  4249. // #define _ATL_MAX_VARTYPES nnnn
  4250. // before including atlcom.h
  4251. ATLASSERT(info.nParams <= _ATL_MAX_VARTYPES);
  4252. if (info.nParams > _ATL_MAX_VARTYPES)
  4253. {
  4254. return E_FAIL;
  4255. }
  4256. VARIANTARG* rgVarArgs[_ATL_MAX_VARTYPES];
  4257. VARIANTARG** pVarArgs = info.nParams ? rgVarArgs : 0;
  4258.  
  4259. UINT nIndex = 0;
  4260.  
  4261. #ifndef _ATL_IGNORE_NAMED_ARGS
  4262. for (nIndex; nIndex < pdispparams->cNamedArgs; nIndex++)
  4263. {
  4264. ATLASSERT( ( NULL != pVarArgs ) && ( pdispparams->rgdispidNamedArgs[nIndex] < _countof(rgVarArgs) ) );
  4265. if( ( NULL == pVarArgs ) || ( pdispparams->rgdispidNamedArgs[nIndex] >= _countof(rgVarArgs) ) )
  4266. {
  4267. return E_FAIL;
  4268. }
  4269. pVarArgs[pdispparams->rgdispidNamedArgs[nIndex]] = &pdispparams->rgvarg[nIndex];
  4270. }
  4271. #endif
  4272.  
  4273. for (; nIndex < pdispparams->cArgs; nIndex++)
  4274. {
  4275. ATLASSERT( NULL != pVarArgs );
  4276. if( NULL == pVarArgs )
  4277. {
  4278. return E_FAIL;
  4279. }
  4280. pVarArgs[info.nParams-nIndex-1] = &pdispparams->rgvarg[nIndex];
  4281. }
  4282.  
  4283. CComStdCallThunk<T> thunk;
  4284. thunk.Init(pEvent, pT);
  4285.  
  4286. CComVariant tmpResult;
  4287. if (pvarResult == NULL)
  4288. pvarResult = &tmpResult;
  4289.  
  4290. HRESULT hr = DispCallFunc(
  4291. &thunk,
  4292. 0,
  4293. info.cc,
  4294. info.vtReturn,
  4295. info.nParams,
  4296. info.pVarTypes,
  4297. pVarArgs,
  4298. pvarResult);
  4299. ATLASSERT(SUCCEEDED(hr));
  4300. return hr;
  4301. }
  4302.  
  4303. //Helper for finding the function index for a DISPID
  4304. virtual HRESULT GetFuncInfoFromId(const IID& /*iid*/, DISPID /*dispidMember*/, LCID /*lcid*/, _ATL_FUNC_INFO& /*info*/)
  4305. {
  4306. ATLTRACE(_T("TODO: Classes using IDispEventSimpleImpl should override this method\n"));
  4307. ATLASSERT(0);
  4308. ATLTRACENOTIMPL(_T("IDispEventSimpleImpl::GetFuncInfoFromId"));
  4309. }
  4310. //Helpers for sinking events on random IUnknown*
  4311. HRESULT DispEventAdvise(IUnknown* pUnk, const IID* piid)
  4312. {
  4313. ATLENSURE(m_dwEventCookie == 0xFEFEFEFE);
  4314. return AtlAdvise(pUnk, (IUnknown*)this, *piid, &m_dwEventCookie);
  4315. }
  4316. HRESULT DispEventUnadvise(IUnknown* pUnk, const IID* piid)
  4317. {
  4318. HRESULT hr = AtlUnadvise(pUnk, *piid, m_dwEventCookie);
  4319. m_dwEventCookie = 0xFEFEFEFE;
  4320. return hr;
  4321. }
  4322. HRESULT DispEventAdvise(IUnknown* pUnk)
  4323. {
  4324. return _IDispEvent::DispEventAdvise(pUnk, pdiid);
  4325. }
  4326. HRESULT DispEventUnadvise(IUnknown* pUnk)
  4327. {
  4328. return _IDispEvent::DispEventUnadvise(pUnk, pdiid);
  4329. }
  4330. };
  4331.  
  4332. //Helper for advising connections points from a sink map
  4333. template <class T>
  4334. inline HRESULT AtlAdviseSinkMap(T* pT, bool bAdvise)
  4335. {
  4336. ATLASSERT(::IsWindow(pT->m_hWnd));
  4337. const _ATL_EVENT_ENTRY<T>* pEntries = T::_GetSinkMap();
  4338. if (pEntries == NULL)
  4339. return S_OK;
  4340. HRESULT hr = S_OK;
  4341. while (pEntries->piid != NULL)
  4342. {
  4343. _IDispEvent* pDE = (_IDispEvent*)((DWORD_PTR)pT+pEntries->nOffset);
  4344. bool bNotAdvised = pDE->m_dwEventCookie == 0xFEFEFEFE;
  4345. if (bAdvise ^ bNotAdvised)
  4346. {
  4347. pEntries++;
  4348. continue;
  4349. }
  4350. hr = E_FAIL;
  4351. HWND h = pT->GetDlgItem(pEntries->nControlID);
  4352. ATLASSERT(h != NULL);
  4353. if (h != NULL)
  4354. {
  4355. CComPtr<IUnknown> spUnk;
  4356. AtlAxGetControl(h, &spUnk);
  4357. ATLASSERT(spUnk != NULL);
  4358. if (spUnk != NULL)
  4359. {
  4360. if (bAdvise)
  4361. {
  4362. if (!InlineIsEqualGUID(IID_NULL, *pEntries->piid))
  4363. hr = pDE->DispEventAdvise(spUnk, pEntries->piid);
  4364. else
  4365. {
  4366. hr = AtlGetObjectSourceInterface(spUnk, &pDE->m_libid, &pDE->m_iid, &pDE->m_wMajorVerNum, &pDE->m_wMinorVerNum);
  4367. if (FAILED(hr))
  4368. return hr;
  4369. hr = pDE->DispEventAdvise(spUnk, &pDE->m_iid);
  4370. }
  4371. }
  4372. else
  4373. {
  4374. if (!InlineIsEqualGUID(IID_NULL, *pEntries->piid))
  4375. hr = pDE->DispEventUnadvise(spUnk, pEntries->piid);
  4376. else
  4377. hr = pDE->DispEventUnadvise(spUnk, &pDE->m_iid);
  4378. }
  4379. ATLASSERT(hr == S_OK);
  4380. }
  4381. }
  4382. if (FAILED(hr))
  4383. break;
  4384. pEntries++;
  4385. }
  4386. return hr;
  4387. }
  4388.  
  4389. #pragma warning(push)
  4390. #pragma warning(disable: 4061) // enumerate XXX not explicitly handled by a case label
  4391. inline VARTYPE AtlGetUserDefinedType(ITypeInfo *pTI, HREFTYPE hrt)
  4392. {
  4393. ATLENSURE_THROW(pTI != NULL, E_INVALIDARG);
  4394.  
  4395. CComPtr<ITypeInfo> spTypeInfo;
  4396. VARTYPE vt = VT_USERDEFINED;
  4397. HRESULT hr = E_FAIL;
  4398. hr = pTI->GetRefTypeInfo(hrt, &spTypeInfo);
  4399. if(FAILED(hr))
  4400. return vt;
  4401. TYPEATTR *pta = NULL;
  4402.  
  4403. hr = spTypeInfo->GetTypeAttr(&pta);
  4404. if(SUCCEEDED(hr) && pta && (pta->typekind == TKIND_ALIAS || pta->typekind == TKIND_ENUM))
  4405. {
  4406. if (pta->tdescAlias.vt == VT_USERDEFINED)
  4407. vt = AtlGetUserDefinedType(spTypeInfo, pta->tdescAlias.hreftype);
  4408. else
  4409. {
  4410. switch (pta->typekind)
  4411. {
  4412. case TKIND_ENUM :
  4413. vt = VT_I4;
  4414. break;
  4415. case TKIND_INTERFACE :
  4416. vt = VT_UNKNOWN;
  4417. break;
  4418. case TKIND_DISPATCH :
  4419. vt = VT_DISPATCH;
  4420. break;
  4421. default:
  4422. vt = pta->tdescAlias.vt;
  4423. }
  4424. }
  4425. }
  4426.  
  4427. if(pta)
  4428. spTypeInfo->ReleaseTypeAttr(pta);
  4429. return vt;
  4430.  
  4431. }
  4432. #pragma warning(pop)
  4433.  
  4434. inline HRESULT AtlGetFuncInfoFromId(ITypeInfo* pTypeInfo, const IID& /*iid*/, DISPID dispidMember, LCID /*lcid*/, _ATL_FUNC_INFO& info)
  4435. {
  4436. if (pTypeInfo == NULL)
  4437. return E_INVALIDARG;
  4438.  
  4439. HRESULT hr = S_OK;
  4440. FUNCDESC* pFuncDesc = NULL;
  4441. TYPEATTR* pAttr;
  4442. hr = pTypeInfo->GetTypeAttr(&pAttr);
  4443. if (FAILED(hr))
  4444. return hr;
  4445. int i;
  4446. for (i=0;i<pAttr->cFuncs;i++)
  4447. {
  4448. hr = pTypeInfo->GetFuncDesc(i, &pFuncDesc);
  4449. if (FAILED(hr))
  4450. return hr;
  4451. if (pFuncDesc->memid == dispidMember)
  4452. break;
  4453. pTypeInfo->ReleaseFuncDesc(pFuncDesc);
  4454. pFuncDesc = NULL;
  4455. }
  4456. pTypeInfo->ReleaseTypeAttr(pAttr);
  4457. if (pFuncDesc == NULL)
  4458. return E_FAIL;
  4459.  
  4460. // If this assert occurs, then add a #define _ATL_MAX_VARTYPES nnnn
  4461. // before including atlcom.h
  4462. ATLASSERT(pFuncDesc->cParams <= _ATL_MAX_VARTYPES);
  4463. if (pFuncDesc->cParams > _ATL_MAX_VARTYPES)
  4464. return E_FAIL;
  4465.  
  4466. for (i = 0; i < pFuncDesc->cParams; i++)
  4467. {
  4468. info.pVarTypes[i] = pFuncDesc->lprgelemdescParam[i].tdesc.vt;
  4469. if (info.pVarTypes[i] == VT_PTR)
  4470. info.pVarTypes[i] = (VARTYPE)(pFuncDesc->lprgelemdescParam[i].tdesc.lptdesc->vt | VT_BYREF);
  4471. if (info.pVarTypes[i] == VT_USERDEFINED)
  4472. info.pVarTypes[i] = AtlGetUserDefinedType(pTypeInfo, pFuncDesc->lprgelemdescParam[i].tdesc.hreftype);
  4473. }
  4474.  
  4475. VARTYPE vtReturn = pFuncDesc->elemdescFunc.tdesc.vt;
  4476. switch(vtReturn)
  4477. {
  4478. case VT_INT:
  4479. vtReturn = VT_I4;
  4480. break;
  4481. case VT_UINT:
  4482. vtReturn = VT_UI4;
  4483. break;
  4484. case VT_VOID:
  4485. vtReturn = VT_EMPTY; // this is how DispCallFunc() represents void
  4486. break;
  4487. case VT_HRESULT:
  4488. vtReturn = VT_ERROR;
  4489. break;
  4490. }
  4491. info.vtReturn = vtReturn;
  4492. info.cc = pFuncDesc->callconv;
  4493. info.nParams = pFuncDesc->cParams;
  4494. pTypeInfo->ReleaseFuncDesc(pFuncDesc);
  4495. return S_OK;
  4496. }
  4497.  
  4498. template <UINT nID, class T, const IID* pdiid = &IID_NULL, const GUID* plibid = &GUID_NULL,
  4499. WORD wMajor = 0, WORD wMinor = 0, class tihclass = CComTypeInfoHolder>
  4500. class ATL_NO_VTABLE IDispEventImpl : public IDispEventSimpleImpl<nID, T, pdiid>
  4501. {
  4502. public:
  4503. typedef tihclass _tihclass;
  4504.  
  4505. IDispEventImpl()
  4506. {
  4507. m_libid = *plibid;
  4508. m_iid = *pdiid;
  4509. m_wMajorVerNum = wMajor;
  4510. m_wMinorVerNum = wMinor;
  4511. }
  4512.  
  4513. STDMETHOD(GetTypeInfoCount)(UINT* pctinfo)
  4514. {
  4515. if (pctinfo == NULL)
  4516. return E_POINTER;
  4517. *pctinfo = 1;
  4518. return S_OK;
  4519. }
  4520.  
  4521. STDMETHOD(GetTypeInfo)(UINT itinfo, LCID lcid, ITypeInfo** pptinfo)
  4522. {return _tih.GetTypeInfo(itinfo, lcid, pptinfo);}
  4523.  
  4524. STDMETHOD(GetIDsOfNames)(REFIID riid, LPOLESTR* rgszNames, UINT cNames,
  4525. LCID lcid, DISPID* rgdispid)
  4526. {return _tih.GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid);}
  4527.  
  4528. //Helper for finding the function index for a DISPID
  4529. HRESULT GetFuncInfoFromId(const IID& iid, DISPID dispidMember, LCID lcid, _ATL_FUNC_INFO& info)
  4530. {
  4531. CComPtr<ITypeInfo> spTypeInfo;
  4532.  
  4533. if (InlineIsEqualGUID(*_tih.m_plibid, GUID_NULL))
  4534. {
  4535. m_InnerLibid = m_libid;
  4536. m_InnerIid = m_iid;
  4537. _tih.m_plibid = &m_InnerLibid;
  4538. _tih.m_pguid = &m_InnerIid;
  4539. _tih.m_wMajor = m_wMajorVerNum;
  4540. _tih.m_wMinor = m_wMinorVerNum;
  4541.  
  4542. }
  4543. HRESULT hr = _tih.GetTI(lcid, &spTypeInfo);
  4544. if (FAILED(hr))
  4545. return hr;
  4546. return AtlGetFuncInfoFromId(spTypeInfo, iid, dispidMember, lcid, info);
  4547. }
  4548. VARTYPE GetUserDefinedType(ITypeInfo *pTI, HREFTYPE hrt)
  4549. {
  4550. return AtlGetUserDefinedType(pTI, hrt);
  4551. }
  4552. protected:
  4553. static _tihclass _tih;
  4554. static GUID m_InnerLibid; // used for dynamic case
  4555. static IID m_InnerIid; // used for dynamic case
  4556. static HRESULT GetTI(LCID lcid, ITypeInfo** ppInfo)
  4557. {return _tih.GetTI(lcid, ppInfo);}
  4558. };
  4559.  
  4560. template <UINT nID, class T, const IID* piid, const GUID* plibid, WORD wMajor, WORD wMinor, class tihclass>
  4561. typename IDispEventImpl<nID, T, piid, plibid, wMajor, wMinor, tihclass>::_tihclass
  4562. IDispEventImpl<nID, T, piid, plibid, wMajor, wMinor, tihclass>::_tih =
  4563. {piid, plibid, wMajor, wMinor, NULL, 0, NULL, 0};
  4564.  
  4565. template <UINT nID, class T, const IID* piid, const GUID* plibid, WORD wMajor, WORD wMinor, class tihclass>
  4566. GUID IDispEventImpl<nID, T, piid, plibid, wMajor, wMinor, tihclass>::m_InnerLibid=GUID_NULL;
  4567.  
  4568. template <UINT nID, class T, const IID* piid, const GUID* plibid, WORD wMajor, WORD wMinor, class tihclass>
  4569. IID IDispEventImpl<nID, T, piid, plibid, wMajor, wMinor, tihclass>::m_InnerIid=IID_NULL;
  4570.  
  4571. template <class T>
  4572. struct _ATL_EVENT_ENTRY
  4573. {
  4574. UINT nControlID; //ID identifying object instance
  4575. const IID* piid; //dispinterface IID
  4576. int nOffset; //offset of dispinterface from this pointer
  4577. DISPID dispid; //DISPID of method/property
  4578. void (__stdcall T::*pfn)(); //method to invoke
  4579. _ATL_FUNC_INFO* pInfo;
  4580. };
  4581.  
  4582.  
  4583.  
  4584. //Sink map is used to set up event handling
  4585. #define BEGIN_SINK_MAP(_class)\
  4586. typedef _class _GetSinkMapFinder;\
  4587. static const ATL::_ATL_EVENT_ENTRY<_class>* _GetSinkMap()\
  4588. {\
  4589. PTM_WARNING_DISABLE \
  4590. typedef _class _atl_event_classtype;\
  4591. static const ATL::_ATL_EVENT_ENTRY<_class> map[] = {
  4592.  
  4593.  
  4594.  
  4595.  
  4596. #define SINK_ENTRY_INFO(id, iid, dispid, fn, info) {id, &iid, (int)(INT_PTR)(static_cast<ATL::_IDispEventLocator<id, &iid>*>((_atl_event_classtype*)8))-8, dispid, (void (__stdcall _atl_event_classtype::*)())fn, info},
  4597. #define SINK_ENTRY_EX(id, iid, dispid, fn) SINK_ENTRY_INFO(id, iid, dispid, fn, NULL)
  4598. #define SINK_ENTRY(id, dispid, fn) SINK_ENTRY_EX(id, IID_NULL, dispid, fn)
  4599. #define END_SINK_MAP() \
  4600. {0, NULL, 0, 0, NULL, NULL} }; return map;\
  4601. PTM_WARNING_RESTORE \
  4602. }
  4603.  
  4604. /////////////////////////////////////////////////////////////////////////////
  4605. // IDispatchImpl
  4606.  
  4607. template <class T, const IID* piid = &__uuidof(T), const GUID* plibid = &CAtlModule::m_libid, WORD wMajor = 1,
  4608. WORD wMinor = 0, class tihclass = CComTypeInfoHolder>
  4609. class ATL_NO_VTABLE IDispatchImpl : public T
  4610. {
  4611. public:
  4612. typedef tihclass _tihclass;
  4613. // IDispatch
  4614. STDMETHOD(GetTypeInfoCount)(UINT* pctinfo)
  4615. {
  4616. if (pctinfo == NULL)
  4617. return E_POINTER;
  4618. *pctinfo = 1;
  4619. return S_OK;
  4620. }
  4621. STDMETHOD(GetTypeInfo)(UINT itinfo, LCID lcid, ITypeInfo** pptinfo)
  4622. {
  4623. return _tih.GetTypeInfo(itinfo, lcid, pptinfo);
  4624. }
  4625. STDMETHOD(GetIDsOfNames)(REFIID riid, LPOLESTR* rgszNames, UINT cNames,
  4626. LCID lcid, DISPID* rgdispid)
  4627. {
  4628. return _tih.GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid);
  4629. }
  4630. STDMETHOD(Invoke)(DISPID dispidMember, REFIID riid,
  4631. LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult,
  4632. EXCEPINFO* pexcepinfo, UINT* puArgErr)
  4633. {
  4634. return _tih.Invoke((IDispatch*)this, dispidMember, riid, lcid,
  4635. wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr);
  4636. }
  4637.  
  4638. #ifdef _ATL_DLL_IMPL
  4639. // Do not cache type info if it is used in the ATL dll
  4640. IDispatchImpl() : _tih(piid, plibid, wMajor, wMinor)
  4641. {
  4642. }
  4643. virtual ~IDispatchImpl()
  4644. {
  4645. }
  4646.  
  4647. protected:
  4648. _tihclass _tih;
  4649. HRESULT GetTI(LCID lcid, ITypeInfo** ppInfo)
  4650. {
  4651. return _tih.GetTI(lcid, ppInfo);
  4652. }
  4653.  
  4654. #else
  4655.  
  4656. protected:
  4657. static _tihclass _tih;
  4658. static HRESULT GetTI(LCID lcid, ITypeInfo** ppInfo)
  4659. {
  4660. return _tih.GetTI(lcid, ppInfo);
  4661. }
  4662.  
  4663. #endif
  4664.  
  4665. };
  4666.  
  4667. #ifndef _ATL_DLL_IMPL
  4668.  
  4669. template <class T, const IID* piid, const GUID* plibid, WORD wMajor, WORD wMinor, class tihclass>
  4670. typename IDispatchImpl<T, piid, plibid, wMajor, wMinor, tihclass>::_tihclass
  4671. IDispatchImpl<T, piid, plibid, wMajor, wMinor, tihclass>::_tih =
  4672. {piid, plibid, wMajor, wMinor, NULL, 0, NULL, 0};
  4673.  
  4674. #endif
  4675.  
  4676. /////////////////////////////////////////////////////////////////////////////
  4677. // IProvideClassInfoImpl
  4678. template <const CLSID* pcoclsid, const GUID* plibid = &CAtlModule::m_libid,
  4679. WORD wMajor = 1, WORD wMinor = 0, class tihclass = CComTypeInfoHolder>
  4680. class ATL_NO_VTABLE IProvideClassInfoImpl : public IProvideClassInfo
  4681. {
  4682. public:
  4683. typedef tihclass _tihclass;
  4684.  
  4685. STDMETHOD(GetClassInfo)(ITypeInfo** pptinfo)
  4686. {
  4687. return _tih.GetTypeInfo(0, LANG_NEUTRAL, pptinfo);
  4688. }
  4689.  
  4690. protected:
  4691. static _tihclass _tih;
  4692. };
  4693.  
  4694. template <const CLSID* pcoclsid, const GUID* plibid, WORD wMajor, WORD wMinor, class tihclass>
  4695. typename IProvideClassInfoImpl<pcoclsid, plibid, wMajor, wMinor, tihclass>::_tihclass
  4696. IProvideClassInfoImpl<pcoclsid, plibid, wMajor, wMinor, tihclass>::_tih =
  4697. {pcoclsid,plibid, wMajor, wMinor, NULL, 0, NULL, 0};
  4698.  
  4699. /////////////////////////////////////////////////////////////////////////////
  4700. // IProvideClassInfo2Impl
  4701. template <const CLSID* pcoclsid, const IID* psrcid, const GUID* plibid = &CAtlModule::m_libid,
  4702. WORD wMajor = 1, WORD wMinor = 0, class tihclass = CComTypeInfoHolder>
  4703. class ATL_NO_VTABLE IProvideClassInfo2Impl : public IProvideClassInfo2
  4704. {
  4705. public:
  4706. typedef tihclass _tihclass;
  4707.  
  4708. STDMETHOD(GetClassInfo)(ITypeInfo** pptinfo)
  4709. {
  4710. return _tih.GetTypeInfo(0, LANG_NEUTRAL, pptinfo);
  4711. }
  4712. STDMETHOD(GetGUID)(DWORD dwGuidKind, GUID* pGUID)
  4713. {
  4714. if (pGUID == NULL)
  4715. {
  4716. return E_POINTER;
  4717. }
  4718. *pGUID = GUID_NULL;
  4719. if(dwGuidKind!=GUIDKIND_DEFAULT_SOURCE_DISP_IID)
  4720. {
  4721. return E_INVALIDARG;
  4722. }
  4723. if (psrcid != NULL)
  4724. {
  4725. *pGUID = *psrcid;
  4726. return S_OK;
  4727. }
  4728. return E_FAIL;
  4729. }
  4730.  
  4731. protected:
  4732. static _tihclass _tih;
  4733. };
  4734.  
  4735.  
  4736. template <const CLSID* pcoclsid, const IID* psrcid, const GUID* plibid, WORD wMajor, WORD wMinor, class tihclass>
  4737. typename IProvideClassInfo2Impl<pcoclsid, psrcid, plibid, wMajor, wMinor, tihclass>::_tihclass
  4738. IProvideClassInfo2Impl<pcoclsid, psrcid, plibid, wMajor, wMinor, tihclass>::_tih =
  4739. {pcoclsid,plibid, wMajor, wMinor, NULL, 0, NULL, 0};
  4740.  
  4741.  
  4742. /////////////////////////////////////////////////////////////////////////////
  4743. // ISupportErrorInfoImpl
  4744.  
  4745. template <const IID* piid>
  4746. class ATL_NO_VTABLE ISupportErrorInfoImpl : public ISupportErrorInfo
  4747. {
  4748. public:
  4749. STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid)
  4750. {
  4751. return (InlineIsEqualGUID(riid,*piid)) ? S_OK : S_FALSE;
  4752. }
  4753. };
  4754.  
  4755.  
  4756. /////////////////////////////////////////////////////////////////////////////
  4757. // CComEnumImpl
  4758.  
  4759. // These _CopyXXX classes are used with enumerators in order to control
  4760. // how enumerated items are initialized, copied, and deleted
  4761.  
  4762. // Default is shallow copy with no special init or cleanup
  4763. template <class T>
  4764. class _Copy
  4765. {
  4766. public:
  4767. static HRESULT copy(T* p1, const T* p2) { Checked::memcpy_s(p1, sizeof(T), p2, sizeof(T)); return S_OK;}
  4768. static void init(T*) {}
  4769. static void destroy(T*) {}
  4770. };
  4771.  
  4772. template<>
  4773. class _Copy<VARIANT>
  4774. {
  4775. public:
  4776. static HRESULT copy(VARIANT* p1, const VARIANT* p2) {p1->vt = VT_EMPTY; return VariantCopy(p1, const_cast<VARIANT*>(p2));}
  4777. static void init(VARIANT* p) {p->vt = VT_EMPTY;}
  4778. static void destroy(VARIANT* p) {VariantClear(p);}
  4779. };
  4780.  
  4781. template<>
  4782. class _Copy<LPOLESTR>
  4783. {
  4784. public:
  4785. static HRESULT copy(LPOLESTR* p1, const LPOLESTR* p2)
  4786. {
  4787. ATLENSURE(p1 != NULL && p2 != NULL);
  4788. HRESULT hr = S_OK;
  4789. ULONG len = ocslen(*p2)+1;
  4790. (*p1) = (LPOLESTR)::ATL::AtlCoTaskMemCAlloc(len, static_cast<ULONG>(sizeof(OLECHAR)));
  4791. if (*p1 == NULL)
  4792. {
  4793. hr = E_OUTOFMEMORY;
  4794. }
  4795. else
  4796. {
  4797. if(!ocscpy_s(*p1, len, *p2))
  4798. {
  4799. hr = E_FAIL;
  4800. }
  4801. }
  4802. return hr;
  4803. }
  4804. static void init(LPOLESTR* p) {*p = NULL;}
  4805. static void destroy(LPOLESTR* p) { CoTaskMemFree(*p);}
  4806. };
  4807.  
  4808. template<>
  4809. class _Copy<OLEVERB>
  4810. {
  4811. public:
  4812. static HRESULT copy(OLEVERB* p1, const OLEVERB* p2)
  4813. {
  4814. ATLENSURE(p1 != NULL && p2 != NULL);
  4815. HRESULT hr = S_OK;
  4816. *p1 = *p2;
  4817. if (p2->lpszVerbName == NULL)
  4818. {
  4819. return S_OK;
  4820. }
  4821.  
  4822. ULONG len = ocslen(p2->lpszVerbName)+1;
  4823. p1->lpszVerbName = (LPOLESTR)::ATL::AtlCoTaskMemCAlloc(len, static_cast<ULONG>(sizeof(OLECHAR)));
  4824. if (p1->lpszVerbName == NULL)
  4825. {
  4826. hr = E_OUTOFMEMORY;
  4827. }
  4828. else
  4829. {
  4830. if(!ocscpy_s(p1->lpszVerbName, len, p2->lpszVerbName))
  4831. {
  4832. hr = E_FAIL;
  4833. }
  4834. }
  4835. return hr;
  4836. }
  4837. static void init(OLEVERB* p) { p->lpszVerbName = NULL;}
  4838. static void destroy(OLEVERB* p) { if (p->lpszVerbName) CoTaskMemFree(p->lpszVerbName);}
  4839. };
  4840.  
  4841. template<>
  4842. class _Copy<CONNECTDATA>
  4843. {
  4844. public:
  4845. static HRESULT copy(CONNECTDATA* p1, const CONNECTDATA* p2)
  4846. {
  4847. ATLENSURE(p1 != NULL && p2 != NULL);
  4848. *p1 = *p2;
  4849. if (p1->pUnk)
  4850. p1->pUnk->AddRef();
  4851. return S_OK;
  4852. }
  4853. static void init(CONNECTDATA* ) {}
  4854. static void destroy(CONNECTDATA* p) {if (p->pUnk) p->pUnk->Release();}
  4855. };
  4856.  
  4857. template <class T>
  4858. class _CopyInterface
  4859. {
  4860. public:
  4861. static HRESULT copy(T* * p1, T * const * p2)
  4862. {
  4863. ATLENSURE(p1 != NULL && p2 != NULL);
  4864. *p1 = *p2;
  4865. if (*p1)
  4866. (*p1)->AddRef();
  4867. return S_OK;
  4868. }
  4869. static void init(T** ) {}
  4870. static void destroy(T** p) {if (*p) (*p)->Release();}
  4871. };
  4872.  
  4873. template<class T>
  4874. class ATL_NO_VTABLE CComIEnum : public IUnknown
  4875. {
  4876. public:
  4877. STDMETHOD(Next)(ULONG celt, T* rgelt, ULONG* pceltFetched) = 0;
  4878. STDMETHOD(Skip)(ULONG celt) = 0;
  4879. STDMETHOD(Reset)(void) = 0;
  4880. STDMETHOD(Clone)(CComIEnum<T>** ppEnum) = 0;
  4881. };
  4882.  
  4883.  
  4884. enum CComEnumFlags
  4885. {
  4886. //see FlagBits in CComEnumImpl
  4887. AtlFlagNoCopy = 0,
  4888. AtlFlagTakeOwnership = 2,
  4889. AtlFlagCopy = 3 // copy implies ownership
  4890. };
  4891.  
  4892. template <class Base, const IID* piid, class T, class Copy>
  4893. class ATL_NO_VTABLE CComEnumImpl : public Base
  4894. {
  4895. public:
  4896. CComEnumImpl() {m_begin = m_end = m_iter = NULL; m_dwFlags = 0;}
  4897. virtual ~CComEnumImpl();
  4898. STDMETHOD(Next)(ULONG celt, T* rgelt, ULONG* pceltFetched);
  4899. STDMETHOD(Skip)(ULONG celt);
  4900. STDMETHOD(Reset)(void){m_iter = m_begin;return S_OK;}
  4901. STDMETHOD(Clone)(Base** ppEnum);
  4902. HRESULT Init(T* begin, T* end, IUnknown* pUnk,
  4903. CComEnumFlags flags = AtlFlagNoCopy);
  4904. CComPtr<IUnknown> m_spUnk;
  4905. T* m_begin;
  4906. T* m_end;
  4907. T* m_iter;
  4908. DWORD m_dwFlags;
  4909. protected:
  4910. enum FlagBits
  4911. {
  4912. BitCopy=1,
  4913. BitOwn=2
  4914. };
  4915. };
  4916.  
  4917. template <class Base, const IID* piid, class T, class Copy>
  4918. CComEnumImpl<Base, piid, T, Copy>::~CComEnumImpl()
  4919. {
  4920. if (m_dwFlags & BitOwn)
  4921. {
  4922. for (T* p = m_begin; p != m_end; p++)
  4923. Copy::destroy(p);
  4924. delete [] m_begin;
  4925. }
  4926. }
  4927.  
  4928. template <class Base, const IID* piid, class T, class Copy>
  4929. STDMETHODIMP CComEnumImpl<Base, piid, T, Copy>::Next(ULONG celt, T* rgelt,
  4930. ULONG* pceltFetched)
  4931. {
  4932. if (pceltFetched != NULL)
  4933. *pceltFetched = 0;
  4934. if (celt == 0)
  4935. return E_INVALIDARG;
  4936. if (rgelt == NULL || (celt != 1 && pceltFetched == NULL))
  4937. return E_POINTER;
  4938. if (m_begin == NULL || m_end == NULL || m_iter == NULL)
  4939. return E_FAIL;
  4940. ULONG nRem = (ULONG)(m_end - m_iter);
  4941. HRESULT hRes = S_OK;
  4942. if (nRem < celt)
  4943. hRes = S_FALSE;
  4944. ULONG nMin = celt < nRem ? celt : nRem ;
  4945. if (pceltFetched != NULL)
  4946. *pceltFetched = nMin;
  4947. T* pelt = rgelt;
  4948. while(nMin--)
  4949. {
  4950. HRESULT hr = Copy::copy(pelt, m_iter);
  4951. if (FAILED(hr))
  4952. {
  4953. while (rgelt < pelt)
  4954. Copy::destroy(rgelt++);
  4955. if (pceltFetched != NULL)
  4956. *pceltFetched = 0;
  4957. return hr;
  4958. }
  4959. pelt++;
  4960. m_iter++;
  4961. }
  4962. return hRes;
  4963. }
  4964.  
  4965. template <class Base, const IID* piid, class T, class Copy>
  4966. STDMETHODIMP CComEnumImpl<Base, piid, T, Copy>::Skip(ULONG celt)
  4967. {
  4968. if (celt == 0)
  4969. return E_INVALIDARG;
  4970.  
  4971. ULONG nRem = ULONG(m_end - m_iter);
  4972. ULONG nSkip = (celt > nRem) ? nRem : celt;
  4973. m_iter += nSkip;
  4974. return (celt == nSkip) ? S_OK : S_FALSE;
  4975. }
  4976.  
  4977. template <class Base, const IID* piid, class T, class Copy>
  4978. STDMETHODIMP CComEnumImpl<Base, piid, T, Copy>::Clone(Base** ppEnum)
  4979. {
  4980. typedef CComObject<CComEnum<Base, piid, T, Copy> > _class;
  4981. HRESULT hRes = E_POINTER;
  4982. if (ppEnum != NULL)
  4983. {
  4984. *ppEnum = NULL;
  4985. _class* p;
  4986. hRes = _class::CreateInstance(&p);
  4987. if (SUCCEEDED(hRes))
  4988. {
  4989. // If this object has ownership of the data then we need to keep it around
  4990. hRes = p->Init(m_begin, m_end, (m_dwFlags & BitOwn) ? this : m_spUnk);
  4991. if (SUCCEEDED(hRes))
  4992. {
  4993. p->m_iter = m_iter;
  4994. hRes = p->_InternalQueryInterface(*piid, (void**)ppEnum);
  4995. }
  4996. if (FAILED(hRes))
  4997. delete p;
  4998. }
  4999. }
  5000. return hRes;
  5001. }
  5002.  
  5003. template <class Base, const IID* piid, class T, class Copy>
  5004. HRESULT CComEnumImpl<Base, piid, T, Copy>::Init(T* begin, T* end, IUnknown* pUnk,
  5005. CComEnumFlags flags)
  5006. {
  5007. if (flags == AtlFlagCopy)
  5008. {
  5009. ATLASSUME(m_begin == NULL); //Init called twice?
  5010. ATLTRY(m_begin = new T[end-begin])
  5011. m_iter = m_begin;
  5012. if (m_begin == NULL)
  5013. return E_OUTOFMEMORY;
  5014. for (T* i=begin; i != end; i++)
  5015. {
  5016. Copy::init(m_iter);
  5017. HRESULT hr = Copy::copy(m_iter, i);
  5018. if (FAILED(hr))
  5019. {
  5020. T* p = m_begin;
  5021. while (p < m_iter)
  5022. Copy::destroy(p++);
  5023. delete [] m_begin;
  5024. m_begin = m_end = m_iter = NULL;
  5025. return hr;
  5026. }
  5027. m_iter++;
  5028. }
  5029. m_end = m_begin + (end-begin);
  5030. }
  5031. else
  5032. {
  5033. m_begin = begin;
  5034. m_end = end;
  5035. }
  5036. m_spUnk = pUnk;
  5037. m_iter = m_begin;
  5038. m_dwFlags = flags;
  5039. return S_OK;
  5040. }
  5041.  
  5042. template <class Base, const IID* piid, class T, class Copy, class ThreadModel = CComObjectThreadModel>
  5043. class ATL_NO_VTABLE CComEnum :
  5044. public CComEnumImpl<Base, piid, T, Copy>,
  5045. public CComObjectRootEx< ThreadModel >
  5046. {
  5047. public:
  5048. typedef CComEnum<Base, piid, T, Copy > _CComEnum;
  5049. typedef CComEnumImpl<Base, piid, T, Copy > _CComEnumBase;
  5050. BEGIN_COM_MAP(_CComEnum)
  5051. COM_INTERFACE_ENTRY_IID(*piid, _CComEnumBase)
  5052. END_COM_MAP()
  5053. };
  5054.  
  5055. template <class Base, const IID* piid, class T, class Copy, class CollType>
  5056. class ATL_NO_VTABLE IEnumOnSTLImpl : public Base
  5057. {
  5058. public:
  5059. HRESULT Init(IUnknown *pUnkForRelease, CollType& collection)
  5060. {
  5061. m_spUnk = pUnkForRelease;
  5062. m_pcollection = &collection;
  5063. m_iter = m_pcollection->begin();
  5064. return S_OK;
  5065. }
  5066. STDMETHOD(Next)(ULONG celt, T* rgelt, ULONG* pceltFetched);
  5067. STDMETHOD(Skip)(ULONG celt);
  5068. STDMETHOD(Reset)(void)
  5069. {
  5070. if (m_pcollection == NULL)
  5071. return E_FAIL;
  5072. m_iter = m_pcollection->begin();
  5073. return S_OK;
  5074. }
  5075. STDMETHOD(Clone)(Base** ppEnum);
  5076. //Data
  5077. CComPtr<IUnknown> m_spUnk;
  5078. CollType* m_pcollection;
  5079. typename CollType::const_iterator m_iter;
  5080. };
  5081.  
  5082. template <class Base, const IID* piid, class T, class Copy, class CollType>
  5083. STDMETHODIMP IEnumOnSTLImpl<Base, piid, T, Copy, CollType>::Next(ULONG celt, T* rgelt,
  5084. ULONG* pceltFetched)
  5085. {
  5086. if (rgelt == NULL || (celt != 1 && pceltFetched == NULL))
  5087. return E_POINTER;
  5088. if (pceltFetched != NULL)
  5089. *pceltFetched = 0;
  5090. if (m_pcollection == NULL)
  5091. return E_FAIL;
  5092.  
  5093. ULONG nActual = 0;
  5094. HRESULT hr = S_OK;
  5095. T* pelt = rgelt;
  5096. while (SUCCEEDED(hr) && m_iter != m_pcollection->end() && nActual < celt)
  5097. {
  5098. hr = Copy::copy(pelt, &*m_iter);
  5099. if (FAILED(hr))
  5100. {
  5101. while (rgelt < pelt)
  5102. Copy::destroy(rgelt++);
  5103. nActual = 0;
  5104. }
  5105. else
  5106. {
  5107. pelt++;
  5108. m_iter++;
  5109. nActual++;
  5110. }
  5111. }
  5112. if (SUCCEEDED(hr))
  5113. {
  5114. if (pceltFetched)
  5115. *pceltFetched = nActual;
  5116. if (nActual < celt)
  5117. hr = S_FALSE;
  5118. }
  5119. return hr;
  5120. }
  5121.  
  5122. template <class Base, const IID* piid, class T, class Copy, class CollType>
  5123. STDMETHODIMP IEnumOnSTLImpl<Base, piid, T, Copy, CollType>::Skip(ULONG celt)
  5124. {
  5125. HRESULT hr = S_OK;
  5126. while (celt--)
  5127. {
  5128. if (m_iter != m_pcollection->end())
  5129. m_iter++;
  5130. else
  5131. {
  5132. hr = S_FALSE;
  5133. break;
  5134. }
  5135. }
  5136. return hr;
  5137. }
  5138.  
  5139. template <class Base, const IID* piid, class T, class Copy, class CollType>
  5140. STDMETHODIMP IEnumOnSTLImpl<Base, piid, T, Copy, CollType>::Clone(Base** ppEnum)
  5141. {
  5142. typedef CComObject<CComEnumOnSTL<Base, piid, T, Copy, CollType> > _class;
  5143. HRESULT hRes = E_POINTER;
  5144. if (ppEnum != NULL)
  5145. {
  5146. *ppEnum = NULL;
  5147. _class* p;
  5148. hRes = _class::CreateInstance(&p);
  5149. if (SUCCEEDED(hRes))
  5150. {
  5151. hRes = p->Init(m_spUnk, *m_pcollection);
  5152. if (SUCCEEDED(hRes))
  5153. {
  5154. p->m_iter = m_iter;
  5155. hRes = p->_InternalQueryInterface(*piid, (void**)ppEnum);
  5156. }
  5157. if (FAILED(hRes))
  5158. delete p;
  5159. }
  5160. }
  5161. return hRes;
  5162. }
  5163.  
  5164. template <class Base, const IID* piid, class T, class Copy, class CollType, class ThreadModel = CComObjectThreadModel>
  5165. class ATL_NO_VTABLE CComEnumOnSTL :
  5166. public IEnumOnSTLImpl<Base, piid, T, Copy, CollType>,
  5167. public CComObjectRootEx< ThreadModel >
  5168. {
  5169. public:
  5170. typedef CComEnumOnSTL<Base, piid, T, Copy, CollType, ThreadModel > _CComEnum;
  5171. typedef IEnumOnSTLImpl<Base, piid, T, Copy, CollType > _CComEnumBase;
  5172. BEGIN_COM_MAP(_CComEnum)
  5173. COM_INTERFACE_ENTRY_IID(*piid, _CComEnumBase)
  5174. END_COM_MAP()
  5175. };
  5176.  
  5177. template <class T, class CollType, class ItemType, class CopyItem, class EnumType>
  5178. class ICollectionOnSTLImpl : public T
  5179. {
  5180. public:
  5181. STDMETHOD(get_Count)(long* pcount)
  5182. {
  5183. if (pcount == NULL)
  5184. return E_POINTER;
  5185. ATLASSUME(m_coll.size()<=LONG_MAX);
  5186.  
  5187. *pcount = (long)m_coll.size();
  5188.  
  5189. return S_OK;
  5190. }
  5191. STDMETHOD(get_Item)(long Index, ItemType* pvar)
  5192. {
  5193. //Index is 1-based
  5194. if (pvar == NULL)
  5195. return E_POINTER;
  5196. if (Index < 1)
  5197. return E_INVALIDARG;
  5198. HRESULT hr = E_FAIL;
  5199. Index--;
  5200. CollType::const_iterator iter = m_coll.begin();
  5201. while (iter != m_coll.end() && Index > 0)
  5202. {
  5203. iter++;
  5204. Index--;
  5205. }
  5206. if (iter != m_coll.end())
  5207. hr = CopyItem::copy(pvar, &*iter);
  5208. return hr;
  5209. }
  5210. STDMETHOD(get__NewEnum)(IUnknown** ppUnk)
  5211. {
  5212. if (ppUnk == NULL)
  5213. return E_POINTER;
  5214. *ppUnk = NULL;
  5215. HRESULT hRes = S_OK;
  5216. CComObject<EnumType>* p;
  5217. hRes = CComObject<EnumType>::CreateInstance(&p);
  5218. if (SUCCEEDED(hRes))
  5219. {
  5220. hRes = p->Init(this, m_coll);
  5221. if (hRes == S_OK)
  5222. hRes = p->QueryInterface(__uuidof(IUnknown), (void**)ppUnk);
  5223. }
  5224. if (hRes != S_OK)
  5225. delete p;
  5226. return hRes;
  5227. }
  5228. CollType m_coll;
  5229. };
  5230.  
  5231. //////////////////////////////////////////////////////////////////////////////
  5232. // ISpecifyPropertyPagesImpl
  5233. template <class T>
  5234. class ATL_NO_VTABLE ISpecifyPropertyPagesImpl : public ISpecifyPropertyPages
  5235. {
  5236. public:
  5237. // ISpecifyPropertyPages
  5238. //
  5239. STDMETHOD(GetPages)(CAUUID* pPages)
  5240. {
  5241. ATLTRACE(atlTraceCOM, 2, _T("ISpecifyPropertyPagesImpl::GetPages\n"));
  5242. const ATL_PROPMAP_ENTRY* pMap = T::GetPropertyMap();
  5243. return GetPagesHelper(pPages, pMap);
  5244. }
  5245. protected:
  5246. HRESULT GetPagesHelper(CAUUID* pPages, const ATL_PROPMAP_ENTRY* pMap)
  5247. {
  5248. if (pPages == NULL)
  5249. return E_POINTER;
  5250. ATLASSERT(pMap != NULL);
  5251. if (pMap == NULL)
  5252. return E_POINTER;
  5253.  
  5254. int nCnt = 0;
  5255. int i;
  5256. // Get count of unique pages to alloc the array
  5257. for (i = 0; pMap[i].pclsidPropPage != NULL; i++)
  5258. {
  5259. // only allow non data entry types
  5260. if (pMap[i].vt == 0)
  5261. {
  5262. // Does this property have a page? CLSID_NULL means it does not
  5263. if (!InlineIsEqualGUID(*pMap[i].pclsidPropPage, CLSID_NULL))
  5264. nCnt++;
  5265. }
  5266. }
  5267. pPages->pElems = (GUID*) ::ATL::AtlCoTaskMemCAlloc(nCnt, static_cast<ULONG>(sizeof(CLSID)));
  5268. if (pPages->pElems == NULL)
  5269. return E_OUTOFMEMORY;
  5270. // reset count of items we have added to the array
  5271. nCnt = 0;
  5272. for (i = 0; pMap[i].pclsidPropPage != NULL; i++)
  5273. {
  5274. // only allow non data entry types
  5275. if (pMap[i].vt == 0)
  5276. {
  5277. // Does this property have a page? CLSID_NULL means it does not
  5278. if (!InlineIsEqualGUID(*pMap[i].pclsidPropPage, CLSID_NULL))
  5279. {
  5280. BOOL bFound = FALSE;
  5281. // Search through array we are building up to see
  5282. // if it is already in there
  5283. for (int j=0; j<nCnt; j++)
  5284. {
  5285. if (InlineIsEqualGUID(*(pMap[i].pclsidPropPage), pPages->pElems[j]))
  5286. {
  5287. // It's already there, so no need to add it again
  5288. bFound = TRUE;
  5289. break;
  5290. }
  5291. }
  5292. // If we didn't find it in there then add it
  5293. if (!bFound)
  5294. pPages->pElems[nCnt++] = *pMap[i].pclsidPropPage;
  5295. }
  5296. }
  5297. }
  5298. pPages->cElems = nCnt;
  5299. return S_OK;
  5300. }
  5301.  
  5302. };
  5303.  
  5304. #ifndef _ATL_NO_CONNECTION_POINTS
  5305. /////////////////////////////////////////////////////////////////////////////
  5306. // Connection Points
  5307.  
  5308. struct _ATL_CONNMAP_ENTRY
  5309. {
  5310. DWORD_PTR dwOffset;
  5311. };
  5312.  
  5313.  
  5314. // We want the offset of the connection point relative to the connection
  5315. // point container base class
  5316. #define BEGIN_CONNECTION_POINT_MAP(x)\
  5317. __if_not_exists(_atl_conn_classtype) \
  5318. { \
  5319. typedef x _atl_conn_classtype;\
  5320. } \
  5321. static const ATL::_ATL_CONNMAP_ENTRY* GetConnMap(int* pnEntries) {\
  5322. static const ATL::_ATL_CONNMAP_ENTRY _entries[] = {
  5323. #define BEGIN_ATTRCONNECTION_POINT_MAP(x)\
  5324. __if_not_exists(_atl_conn_classtype) \
  5325. { \
  5326. typedef x _atl_conn_classtype;\
  5327. } \
  5328. static const ATL::_ATL_CONNMAP_ENTRY* GetAttrConnMap(int* pnEntries) {\
  5329. static const ATL::_ATL_CONNMAP_ENTRY _entries[] = {
  5330.  
  5331. // CONNECTION_POINT_ENTRY computes the offset of the connection point to the
  5332. // IConnectionPointContainer interface
  5333. #define CONNECTION_POINT_ENTRY(iid){offsetofclass(ATL::_ICPLocator<&iid>, _atl_conn_classtype)-\
  5334. offsetofclass(ATL::IConnectionPointContainerImpl<_atl_conn_classtype>, _atl_conn_classtype)},
  5335. #define END_CONNECTION_POINT_MAP() \
  5336. __if_exists(GetAttrConnMap) \
  5337. { \
  5338. {(DWORD_PTR) -2}, \
  5339. {(DWORD_PTR) GetAttrConnMap }, \
  5340. } \
  5341. {(DWORD_PTR)-1} }; \
  5342. if (pnEntries) \
  5343. { \
  5344. __if_exists(GetAttrConnMap) \
  5345. { \
  5346. GetAttrConnMap(pnEntries); \
  5347. *pnEntries += sizeof(_entries)/sizeof(ATL::_ATL_CONNMAP_ENTRY) - 3; \
  5348. } \
  5349. __if_not_exists(GetAttrConnMap) \
  5350. { \
  5351. *pnEntries = sizeof(_entries)/sizeof(ATL::_ATL_CONNMAP_ENTRY) - 1; \
  5352. } \
  5353. } \
  5354. return _entries;}
  5355. #define END_ATTRCONNECTION_POINT_MAP() \
  5356. {(DWORD_PTR)-1} }; \
  5357. if (pnEntries) \
  5358. { \
  5359. *pnEntries = sizeof(_entries)/sizeof(ATL::_ATL_CONNMAP_ENTRY) - 1; \
  5360. } \
  5361. return _entries;}
  5362.  
  5363.  
  5364. #ifndef _DEFAULT_VECTORLENGTH
  5365. #define _DEFAULT_VECTORLENGTH 4
  5366. #endif
  5367.  
  5368. template <unsigned int nMaxSize>
  5369. class CComUnkArray
  5370. {
  5371. public:
  5372. CComUnkArray()
  5373. {
  5374. memset(m_arr, 0, sizeof(IUnknown*)*nMaxSize);
  5375. }
  5376. DWORD Add(IUnknown* pUnk);
  5377. BOOL Remove(DWORD dwCookie);
  5378. // If there is more than one instance of the same IUnknown*,
  5379. // this function returns the cookie for the first one.
  5380. DWORD WINAPI GetCookie(IUnknown** ppFind)
  5381. {
  5382. ATLASSERT(ppFind && *ppFind);
  5383. if (ppFind && *ppFind)
  5384. {
  5385. // find IUnknown* in array
  5386. for (DWORD dwCookie = 0; dwCookie < nMaxSize; dwCookie++)
  5387. {
  5388. if (m_arr[dwCookie] == *ppFind)
  5389. return dwCookie+1; // cookie minus one is an index into the array
  5390. }
  5391. }
  5392. return 0;
  5393. }
  5394. IUnknown* WINAPI GetUnknown(DWORD dwCookie)
  5395. {
  5396. ATLASSERT(dwCookie != 0 && dwCookie <= nMaxSize);
  5397. if (dwCookie != 0 && dwCookie <= nMaxSize)
  5398. return m_arr[dwCookie-1]; // cookie minus one is an index into the array
  5399. else
  5400. return NULL;
  5401. }
  5402. IUnknown** begin()
  5403. {
  5404. return &m_arr[0];
  5405. }
  5406. IUnknown** end()
  5407. {
  5408. return &m_arr[nMaxSize];
  5409. }
  5410. protected:
  5411. IUnknown* m_arr[nMaxSize];
  5412. };
  5413.  
  5414. template <unsigned int nMaxSize>
  5415. inline DWORD CComUnkArray<nMaxSize>::Add(IUnknown* pUnk)
  5416. {
  5417. DWORD dwCookie = 1;
  5418. for (IUnknown** pp = begin(); pp < end(); pp++)
  5419. {
  5420. if (*pp == NULL)
  5421. {
  5422. *pp = pUnk;
  5423. return dwCookie;
  5424. }
  5425. dwCookie++;
  5426. }
  5427. // If this fires then you need a larger array
  5428. ATLASSERT(0);
  5429. return 0;
  5430. }
  5431.  
  5432. template <unsigned int nMaxSize>
  5433. inline BOOL CComUnkArray<nMaxSize>::Remove(DWORD dwCookie)
  5434. {
  5435. ATLASSERT(dwCookie != 0 && dwCookie <= nMaxSize);
  5436. if (dwCookie != 0 && dwCookie <= nMaxSize && m_arr[dwCookie-1] != NULL)
  5437. {
  5438. m_arr[dwCookie-1] = NULL;
  5439. return TRUE;
  5440. }
  5441. else
  5442. return FALSE;
  5443. }
  5444.  
  5445. template<>
  5446. class CComUnkArray<1>
  5447. {
  5448. public:
  5449. CComUnkArray()
  5450. {
  5451. m_arr[0] = NULL;
  5452. }
  5453. DWORD Add(IUnknown* pUnk)
  5454. {
  5455. if (m_arr[0] != NULL)
  5456. {
  5457. // If this fires then you need a larger array
  5458. ATLASSERT(0);
  5459. return 0;
  5460. }
  5461. m_arr[0] = pUnk;
  5462. return 1;
  5463. }
  5464. BOOL Remove(DWORD dwCookie)
  5465. {
  5466. ATLASSERT(dwCookie == 1);
  5467. if (dwCookie == 1 && m_arr[0] != NULL)
  5468. {
  5469. m_arr[0] = NULL;
  5470. return TRUE;
  5471. }
  5472. else
  5473. return FALSE;
  5474. }
  5475. DWORD WINAPI GetCookie(IUnknown** /* pp */)
  5476. {
  5477. return 1;
  5478. }
  5479. IUnknown* WINAPI GetUnknown(DWORD dwCookie)
  5480. {
  5481. ATLASSERT(dwCookie == 1);
  5482. if (dwCookie == 1)
  5483. return m_arr[0];
  5484. else
  5485. return NULL;
  5486. }
  5487. IUnknown** begin()
  5488. {
  5489. return &m_arr[0];
  5490. }
  5491. IUnknown** end()
  5492. {
  5493. return (&m_arr[0])+1;
  5494. }
  5495. protected:
  5496. IUnknown* m_arr[1];
  5497. };
  5498.  
  5499. class CComDynamicUnkArray
  5500. {
  5501. public:
  5502. CComDynamicUnkArray()
  5503. {
  5504. m_nSize = 0;
  5505. m_ppUnk = NULL;
  5506. }
  5507.  
  5508. ~CComDynamicUnkArray()
  5509. {
  5510. if (m_nSize > 0)
  5511. free(m_ppUnk);
  5512. }
  5513. DWORD Add(IUnknown* pUnk);
  5514. BOOL Remove(DWORD dwCookie);
  5515. // If there is more than one instance of the same IUnknown*,
  5516. // this function returns the cookie for the first one.
  5517. DWORD WINAPI GetCookie(IUnknown** ppFind)
  5518. {
  5519. ATLASSERT(ppFind && *ppFind);
  5520. if (ppFind && *ppFind)
  5521. {
  5522. IUnknown** ppUnk = NULL;
  5523. DWORD dwCookie = 1;
  5524. // find IUnknown* in array
  5525. for (ppUnk = begin(); ppUnk < end(); ppUnk++)
  5526. {
  5527. if (*ppUnk == *ppFind)
  5528. return dwCookie; // cookie minus one is an index into the array
  5529. dwCookie++;
  5530. }
  5531. }
  5532. return 0;
  5533. }
  5534. IUnknown* WINAPI GetUnknown(DWORD dwCookie)
  5535. {
  5536. #ifndef _ATL_OLEDB_CONFORMANCE_TESTS
  5537. ATLASSERT(dwCookie != 0 && dwCookie <= (DWORD)m_nSize);
  5538. #endif
  5539. if (dwCookie != 0 && dwCookie <= (DWORD)m_nSize)
  5540. return GetAt(dwCookie-1); // cookie minus one is an index into the array
  5541. else
  5542. return NULL;
  5543. }
  5544. IUnknown** begin()
  5545. {
  5546. return m_ppUnk;
  5547. }
  5548. IUnknown** end()
  5549. {
  5550. return &m_ppUnk[m_nSize];
  5551. }
  5552.  
  5553. IUnknown* GetAt(int nIndex)
  5554. {
  5555. ATLASSERT(nIndex >= 0 && nIndex < m_nSize);
  5556. if (nIndex >= 0 && nIndex < m_nSize)
  5557. return m_ppUnk[nIndex];
  5558. else
  5559. return NULL;
  5560.  
  5561. }
  5562. int GetSize() const
  5563. {
  5564. return m_nSize;
  5565. }
  5566. void clear()
  5567. {
  5568. if (m_nSize > 0)
  5569. {
  5570. free(m_ppUnk);
  5571. m_ppUnk = 0;
  5572. }
  5573. m_nSize = 0;
  5574. }
  5575. protected:
  5576. IUnknown** m_ppUnk;
  5577. int m_nSize;
  5578. };
  5579.  
  5580. inline DWORD CComDynamicUnkArray::Add(IUnknown* pUnk)
  5581. {
  5582. IUnknown** pp = NULL;
  5583. if (m_nSize == 0)
  5584. {
  5585. // Create array with _DEFAULT_VECTORLENGTH number of items.
  5586. ATLTRY(pp = (IUnknown**)calloc(sizeof(IUnknown*),_DEFAULT_VECTORLENGTH));
  5587. if (pp == NULL)
  5588. return 0;
  5589. memset(pp, 0, sizeof(IUnknown*)*_DEFAULT_VECTORLENGTH);
  5590. m_ppUnk = pp;
  5591. m_nSize = _DEFAULT_VECTORLENGTH;
  5592. }
  5593. // Walk array and use empty slots if any.
  5594. DWORD dwCookie = 1;
  5595. for (pp = begin(); pp < end(); pp++)
  5596. {
  5597. if (*pp == NULL)
  5598. {
  5599. *pp = pUnk;
  5600. return dwCookie; // cookie mi nus one is index into array
  5601. }
  5602. dwCookie++;
  5603. }
  5604. // No empty slots so resize array.
  5605. // # of new slots is double of current size.
  5606. int nAlloc = m_nSize*2;
  5607. pp = (IUnknown**)_recalloc(m_ppUnk, sizeof(IUnknown*),nAlloc);
  5608. if (pp == NULL)
  5609. return 0;
  5610. m_ppUnk = pp;
  5611. memset(&m_ppUnk[m_nSize], 0, sizeof(IUnknown*)*m_nSize);
  5612. m_ppUnk[m_nSize] = pUnk;
  5613. dwCookie = m_nSize+1;
  5614. m_nSize = nAlloc;
  5615. return dwCookie; // cookie minus one is index into array
  5616. }
  5617.  
  5618. inline BOOL CComDynamicUnkArray::Remove(DWORD dwCookie)
  5619. {
  5620. DWORD idx = dwCookie -1;
  5621. #ifndef _ATL_OLEDB_CONFORMANCE_TESTS
  5622. ATLASSERT(idx < dwCookie && idx < (DWORD)m_nSize);
  5623. #endif
  5624. if (idx < dwCookie && idx < (DWORD)m_nSize)
  5625. {
  5626. // cookie minus one is index into array
  5627. if (m_ppUnk[idx] == NULL)
  5628. return FALSE;
  5629. m_ppUnk[idx] = NULL;
  5630. return TRUE;
  5631. }
  5632. else
  5633. return FALSE;
  5634. }
  5635.  
  5636. template <const IID* piid>
  5637. class ATL_NO_VTABLE _ICPLocator
  5638. {
  5639. public:
  5640. //this method needs a different name than QueryInterface
  5641. STDMETHOD(_LocCPQueryInterface)(REFIID riid, void ** ppvObject) = 0;
  5642. virtual ULONG STDMETHODCALLTYPE AddRef(void) = 0;
  5643. virtual ULONG STDMETHODCALLTYPE Release(void) = 0;
  5644. };
  5645.  
  5646. template <class T, const IID* piid, class CDV = CComDynamicUnkArray >
  5647. class ATL_NO_VTABLE IConnectionPointImpl : public _ICPLocator<piid>
  5648. {
  5649. typedef CComEnum<IEnumConnections, &__uuidof(IEnumConnections), CONNECTDATA,
  5650. _Copy<CONNECTDATA> > CComEnumConnections;
  5651. typedef CDV _CDV;
  5652. public:
  5653. ~IConnectionPointImpl();
  5654. STDMETHOD(_LocCPQueryInterface)(REFIID riid, void ** ppvObject)
  5655. {
  5656. #ifndef _ATL_OLEDB_CONFORMANCE_TESTS
  5657. ATLASSERT(ppvObject != NULL);
  5658. #endif
  5659. if (ppvObject == NULL)
  5660. return E_POINTER;
  5661. *ppvObject = NULL;
  5662.  
  5663. if (InlineIsEqualGUID(riid, __uuidof(IConnectionPoint)) || InlineIsEqualUnknown(riid))
  5664. {
  5665. *ppvObject = this;
  5666. AddRef();
  5667. #ifdef _ATL_DEBUG_INTERFACES
  5668. _AtlDebugInterfacesModule.AddThunk((IUnknown**)ppvObject, _T("IConnectionPointImpl"), riid);
  5669. #endif // _ATL_DEBUG_INTERFACES
  5670. return S_OK;
  5671. }
  5672. else
  5673. return E_NOINTERFACE;
  5674. }
  5675.  
  5676. STDMETHOD(GetConnectionInterface)(IID* piid2)
  5677. {
  5678. if (piid2 == NULL)
  5679. return E_POINTER;
  5680. *piid2 = *piid;
  5681. return S_OK;
  5682. }
  5683. STDMETHOD(GetConnectionPointContainer)(IConnectionPointContainer** ppCPC)
  5684. {
  5685. T* pT = static_cast<T*>(this);
  5686. // No need to check ppCPC for NULL since QI will do that for us
  5687. return pT->QueryInterface(__uuidof(IConnectionPointContainer), (void**)ppCPC);
  5688. }
  5689. STDMETHOD(Advise)(IUnknown* pUnkSink, DWORD* pdwCookie);
  5690. STDMETHOD(Unadvise)(DWORD dwCookie);
  5691. STDMETHOD(EnumConnections)(IEnumConnections** ppEnum);
  5692. CDV m_vec;
  5693. };
  5694.  
  5695. template <class T, const IID* piid, class CDV>
  5696. IConnectionPointImpl<T, piid, CDV>::~IConnectionPointImpl()
  5697. {
  5698. IUnknown** pp = m_vec.begin();
  5699. while (pp < m_vec.end())
  5700. {
  5701. if (*pp != NULL)
  5702. (*pp)->Release();
  5703. pp++;
  5704. }
  5705. }
  5706.  
  5707. template <class T, const IID* piid, class CDV>
  5708. STDMETHODIMP IConnectionPointImpl<T, piid, CDV>::Advise(IUnknown* pUnkSink,
  5709. DWORD* pdwCookie)
  5710. {
  5711. T* pT = static_cast<T*>(this);
  5712. IUnknown* p;
  5713. HRESULT hRes = S_OK;
  5714. if (pdwCookie != NULL)
  5715. *pdwCookie = 0;
  5716. if (pUnkSink == NULL || pdwCookie == NULL)
  5717. return E_POINTER;
  5718. IID iid;
  5719. GetConnectionInterface(&iid);
  5720. hRes = pUnkSink->QueryInterface(iid, (void**)&p);
  5721. if (SUCCEEDED(hRes))
  5722. {
  5723. pT->Lock();
  5724. *pdwCookie = m_vec.Add(p);
  5725. hRes = (*pdwCookie != NULL) ? S_OK : CONNECT_E_ADVISELIMIT;
  5726. pT->Unlock();
  5727. if (hRes != S_OK)
  5728. p->Release();
  5729. }
  5730. else if (hRes == E_NOINTERFACE)
  5731. hRes = CONNECT_E_CANNOTCONNECT;
  5732. if (FAILED(hRes))
  5733. *pdwCookie = 0;
  5734. return hRes;
  5735. }
  5736.  
  5737. template <class T, const IID* piid, class CDV>
  5738. STDMETHODIMP IConnectionPointImpl<T, piid, CDV>::Unadvise(DWORD dwCookie)
  5739. {
  5740. T* pT = static_cast<T*>(this);
  5741. pT->Lock();
  5742. IUnknown* p = m_vec.GetUnknown(dwCookie);
  5743. HRESULT hRes = m_vec.Remove(dwCookie) ? S_OK : CONNECT_E_NOCONNECTION;
  5744. pT->Unlock();
  5745. if (hRes == S_OK && p != NULL)
  5746. p->Release();
  5747. return hRes;
  5748. }
  5749.  
  5750. #pragma warning(push)
  5751. #pragma warning(disable: 6014 6211)
  5752. template <class T, const IID* piid, class CDV>
  5753. STDMETHODIMP IConnectionPointImpl<T, piid, CDV>::EnumConnections(
  5754. IEnumConnections** ppEnum)
  5755. {
  5756. if (ppEnum == NULL)
  5757. return E_POINTER;
  5758. *ppEnum = NULL;
  5759. CComObject<CComEnumConnections>* pEnum = NULL;
  5760. ATLTRY(pEnum = new CComObject<CComEnumConnections>)
  5761. if (pEnum == NULL)
  5762. return E_OUTOFMEMORY;
  5763. T* pT = static_cast<T*>(this);
  5764. pT->Lock();
  5765. CONNECTDATA* pcd = NULL;
  5766. ATLTRY(pcd = new CONNECTDATA[m_vec.end()-m_vec.begin()])
  5767. if (pcd == NULL)
  5768. {
  5769. delete pEnum;
  5770. pT->Unlock();
  5771. return E_OUTOFMEMORY;
  5772. }
  5773. CONNECTDATA* pend = pcd;
  5774. // Copy the valid CONNECTDATA's
  5775. for (IUnknown** pp = m_vec.begin();pp<m_vec.end();pp++)
  5776. {
  5777. if (*pp != NULL)
  5778. {
  5779. (*pp)->AddRef();
  5780. pend->pUnk = *pp;
  5781. pend->dwCookie = m_vec.GetCookie(pp);
  5782. pend++;
  5783. }
  5784. }
  5785. // don't copy the data, but transfer ownership to it
  5786. pEnum->Init(pcd, pend, NULL, AtlFlagTakeOwnership);
  5787. pT->Unlock();
  5788. HRESULT hRes = pEnum->_InternalQueryInterface(__uuidof(IEnumConnections), (void**)ppEnum);
  5789. if (FAILED(hRes))
  5790. delete pEnum;
  5791. return hRes;
  5792. }
  5793. #pragma warning(pop)
  5794.  
  5795. /////////////////////////////////////////////////////////////////////////////
  5796. // IConnectionPointContainerImpl
  5797.  
  5798. template <class T>
  5799. class ATL_NO_VTABLE IConnectionPointContainerImpl : public IConnectionPointContainer
  5800. {
  5801. typedef CComEnum<IEnumConnectionPoints,
  5802. &__uuidof(IEnumConnectionPoints), IConnectionPoint*,
  5803. _CopyInterface<IConnectionPoint> >
  5804. CComEnumConnectionPoints;
  5805. public:
  5806. #pragma warning(push)
  5807. #pragma warning(disable: 6014 6211)
  5808. STDMETHOD(EnumConnectionPoints)(IEnumConnectionPoints** ppEnum)
  5809. {
  5810. if (ppEnum == NULL)
  5811. return E_POINTER;
  5812. *ppEnum = NULL;
  5813. CComEnumConnectionPoints* pEnum = NULL;
  5814. ATLTRY(pEnum = new CComObject<CComEnumConnectionPoints>)
  5815. if (pEnum == NULL)
  5816. return E_OUTOFMEMORY;
  5817.  
  5818. int nCPCount;
  5819. const _ATL_CONNMAP_ENTRY* pEntry = T::GetConnMap(&nCPCount);
  5820.  
  5821. // allocate an initialize a vector of connection point object pointers
  5822. USES_ATL_SAFE_ALLOCA;
  5823. if ((nCPCount < 0) || (nCPCount > (INT_MAX / sizeof(IConnectionPoint*))))
  5824. return E_OUTOFMEMORY;
  5825. size_t nBytes=0;
  5826. HRESULT hr=S_OK;
  5827. if( FAILED(hr=::ATL::AtlMultiply(&nBytes, sizeof(IConnectionPoint*), static_cast<size_t>(nCPCount))))
  5828. {
  5829. return hr;
  5830. }
  5831. IConnectionPoint** ppCP = (IConnectionPoint**)_ATL_SAFE_ALLOCA(nBytes, _ATL_SAFE_ALLOCA_DEF_THRESHOLD);
  5832. if (ppCP == NULL)
  5833. {
  5834. delete pEnum;
  5835. return E_OUTOFMEMORY;
  5836. }
  5837.  
  5838. int i = 0;
  5839. while (pEntry->dwOffset != (DWORD_PTR)-1)
  5840. {
  5841. if (pEntry->dwOffset == (DWORD_PTR)-2)
  5842. {
  5843. pEntry++;
  5844. const _ATL_CONNMAP_ENTRY* (*pFunc)(int*) = (const _ATL_CONNMAP_ENTRY* (*)(int*))(pEntry->dwOffset);
  5845. pEntry = pFunc(NULL);
  5846. continue;
  5847. }
  5848. ppCP[i++] = (IConnectionPoint*)((INT_PTR)this+pEntry->dwOffset);
  5849. pEntry++;
  5850. }
  5851.  
  5852. // copy the pointers: they will AddRef this object
  5853. HRESULT hRes = pEnum->Init((IConnectionPoint**)&ppCP[0],
  5854. (IConnectionPoint**)&ppCP[nCPCount],
  5855. reinterpret_cast<IConnectionPointContainer*>(this), AtlFlagCopy);
  5856. if (FAILED(hRes))
  5857. {
  5858. delete pEnum;
  5859. return hRes;
  5860. }
  5861. hRes = pEnum->QueryInterface(__uuidof(IEnumConnectionPoints), (void**)ppEnum);
  5862. if (FAILED(hRes))
  5863. delete pEnum;
  5864. return hRes;
  5865. }
  5866. #pragma warning(pop)
  5867.  
  5868. STDMETHOD(FindConnectionPoint)(REFIID riid, IConnectionPoint** ppCP)
  5869. {
  5870. if (ppCP == NULL)
  5871. return E_POINTER;
  5872. *ppCP = NULL;
  5873. HRESULT hRes = CONNECT_E_NOCONNECTION;
  5874. const _ATL_CONNMAP_ENTRY* pEntry = T::GetConnMap(NULL);
  5875. IID iid;
  5876. while (pEntry->dwOffset != (DWORD_PTR)-1)
  5877. {
  5878. if (pEntry->dwOffset == (DWORD_PTR)-2)
  5879. {
  5880. pEntry++;
  5881. const _ATL_CONNMAP_ENTRY* (*pFunc)(int*) = (const _ATL_CONNMAP_ENTRY* (*)(int*))(pEntry->dwOffset);
  5882. pEntry = pFunc(NULL);
  5883. continue;
  5884. }
  5885. IConnectionPoint* pCP =
  5886. (IConnectionPoint*)((INT_PTR)this+pEntry->dwOffset);
  5887. if (SUCCEEDED(pCP->GetConnectionInterface(&iid)) &&
  5888. InlineIsEqualGUID(riid, iid))
  5889. {
  5890. *ppCP = pCP;
  5891. pCP->AddRef();
  5892. hRes = S_OK;
  5893. break;
  5894. }
  5895. pEntry++;
  5896. }
  5897. return hRes;
  5898. }
  5899. };
  5900.  
  5901. #endif //!_ATL_NO_CONNECTION_POINTS
  5902.  
  5903. /////////////////////////////////////////////////////////////////////////////
  5904. // IExternalConnectionImpl
  5905.  
  5906. // An object that implements IExternalConnection should explicitly call
  5907. // CoDisconnectObject on itself when its external reference count drops to 0.
  5908. // This call will cause the stub manager to call Release on the object so the
  5909. // object can destroy itself.
  5910.  
  5911. template <class T>
  5912. class IExternalConnectionImpl : public IExternalConnection
  5913. {
  5914. public:
  5915. IExternalConnectionImpl(void) : m_nStrongLocks(0) {}
  5916. STDMETHODIMP_(DWORD) AddConnection(DWORD extconn, DWORD /*dwReserved*/)
  5917. {
  5918. DWORD dw = 0;
  5919. if (extconn & EXTCONN_STRONG)
  5920. {
  5921. dw = T::_ThreadModel::Increment(&m_nStrongLocks);
  5922. static_cast<T*>(this)->OnAddConnection(dw == 1);
  5923. }
  5924. return dw;
  5925. }
  5926. STDMETHODIMP_(DWORD) ReleaseConnection(DWORD extconn, DWORD /*dwReserved*/, BOOL bLastUnlockReleases)
  5927. {
  5928. DWORD dw = 0;
  5929. if (extconn & EXTCONN_STRONG)
  5930. {
  5931. dw = T::_ThreadModel::Decrement(&m_nStrongLocks);
  5932. static_cast<T*>(this)->OnReleaseConnection(dw == 0, !!bLastUnlockReleases);
  5933. }
  5934. return dw;
  5935. }
  5936.  
  5937. // Services provided by this class
  5938. bool DoIHaveAStub() { return m_nStrongLocks != 0; }
  5939. LONG GetStrongConnectionCount() { return m_nStrongLocks; }
  5940. // Extensibility points provided by this class
  5941. void OnAddConnection(bool bThisIsFirstLock) {}
  5942. void OnReleaseConnection(bool bThisIsLastUnlock, bool bLastUnlockReleases)
  5943. {
  5944. if (bThisIsLastUnlock && bLastUnlockReleases)
  5945. CoDisconnectObject(static_cast<T*>(this)->GetUnknown(), 0);
  5946. }
  5947. // Implementation
  5948. LONG m_nStrongLocks;
  5949. };
  5950.  
  5951. #pragma pack(pop)
  5952.  
  5953. // All exports go here
  5954. #ifndef _ATL_DLL
  5955.  
  5956. /////////////////////////////////////////////////////////////////////////////
  5957. // IDispatch Error handling
  5958.  
  5959. ATLINLINE ATLAPI AtlSetErrorInfo(const CLSID& clsid, LPCOLESTR lpszDesc, DWORD dwHelpID,
  5960. LPCOLESTR lpszHelpFile, const IID& iid, HRESULT hRes, HINSTANCE hInst)
  5961. {
  5962. USES_CONVERSION_EX;
  5963. TCHAR szDesc[1024];
  5964. szDesc[0] = NULL;
  5965. // For a valid HRESULT the id should be in the range [0x0200, 0xffff]
  5966. if (IS_INTRESOURCE(lpszDesc)) //id
  5967. {
  5968. UINT nID = LOWORD((DWORD_PTR)lpszDesc);
  5969. ATLASSERT((nID >= 0x0200 && nID <= 0xffff) || hRes != 0);
  5970. if (LoadString(hInst, nID, szDesc, 1024) == 0)
  5971. {
  5972. ATLASSERT(FALSE);
  5973. Checked::tcscpy_s(szDesc, _countof(szDesc), _T("Unknown Error"));
  5974. }
  5975. lpszDesc = T2OLE_EX(szDesc, _ATL_SAFE_ALLOCA_DEF_THRESHOLD);
  5976. #ifndef _UNICODE
  5977. if(lpszDesc == NULL)
  5978. return E_OUTOFMEMORY;
  5979. #endif
  5980. if (hRes == 0)
  5981. hRes = MAKE_HRESULT(3, FACILITY_ITF, nID);
  5982. }
  5983.  
  5984. CComPtr<ICreateErrorInfo> pICEI;
  5985. if (SUCCEEDED(CreateErrorInfo(&pICEI)))
  5986. {
  5987. CComPtr<IErrorInfo> pErrorInfo;
  5988. pICEI->SetGUID(iid);
  5989. LPOLESTR lpsz;
  5990. ProgIDFromCLSID(clsid, &lpsz);
  5991. if (lpsz != NULL)
  5992. pICEI->SetSource(lpsz);
  5993. if (dwHelpID != 0 && lpszHelpFile != NULL)
  5994. {
  5995. pICEI->SetHelpContext(dwHelpID);
  5996. pICEI->SetHelpFile(const_cast<LPOLESTR>(lpszHelpFile));
  5997. }
  5998. CoTaskMemFree(lpsz);
  5999. pICEI->SetDescription((LPOLESTR)lpszDesc);
  6000. if (SUCCEEDED(pICEI->QueryInterface(__uuidof(IErrorInfo), (void**)&pErrorInfo)))
  6001. SetErrorInfo(0, pErrorInfo);
  6002. }
  6003. return (hRes == 0) ? DISP_E_EXCEPTION : hRes;
  6004. }
  6005.  
  6006. /////////////////////////////////////////////////////////////////////////////
  6007. // IPersist* helpers.
  6008.  
  6009. ATLINLINE ATLAPI AtlIPersistStreamInit_Load(LPSTREAM pStm, const ATL_PROPMAP_ENTRY* pMap, void* pThis, IUnknown* pUnk)
  6010. {
  6011. ATLASSERT(pMap != NULL);
  6012. if (pStm == NULL || pMap == NULL || pThis == NULL || pUnk == NULL)
  6013. return E_INVALIDARG;
  6014.  
  6015. HRESULT hr = S_OK;
  6016. DWORD dwVer;
  6017. hr = pStm->Read(&dwVer, sizeof(DWORD), NULL);
  6018. if (FAILED(hr))
  6019. return hr;
  6020. if (dwVer > _ATL_VER)
  6021. return E_FAIL;
  6022.  
  6023. CComPtr<IDispatch> pDispatch;
  6024. const IID* piidOld = NULL;
  6025. for (int i = 0; pMap[i].pclsidPropPage != NULL; i++)
  6026. {
  6027. if (pMap[i].szDesc == NULL)
  6028. continue;
  6029.  
  6030. // check if raw data entry
  6031. if (pMap[i].dwSizeData != 0)
  6032. {
  6033. void* pData = (void*) (pMap[i].dwOffsetData + (DWORD_PTR)pThis);
  6034. // call CComBSTR::ReadFromStream for BSTRs
  6035. if (pMap[i].vt == VT_BSTR)
  6036. {
  6037. CComBSTR bstrRead;
  6038. hr = bstrRead.ReadFromStream(pStm);
  6039. (*(BSTR*)pData) = bstrRead.Detach();
  6040. }
  6041. else
  6042. hr = pStm->Read(pData, pMap[i].dwSizeData, NULL);
  6043. if (FAILED(hr))
  6044. return hr;
  6045. continue;
  6046. }
  6047.  
  6048. CComVariant var;
  6049.  
  6050. #if defined(_ATL_DLL_IMPL)
  6051. hr = var.ReadFromStream(pStm, pMap[i].vt);
  6052. #else
  6053. hr = var.ReadFromStream(pStm, pMap[i].vt, pMap[i].rgclsidAllowed, pMap[i].cclsidAllowed);
  6054. #endif
  6055. if (FAILED(hr))
  6056. break;
  6057.  
  6058. if (pMap[i].piidDispatch != piidOld)
  6059. {
  6060. pDispatch.Release();
  6061. ATLENSURE_RETURN(pMap[i].piidDispatch);
  6062. if (FAILED(pUnk->QueryInterface(*pMap[i].piidDispatch, (void**)&pDispatch)))
  6063. {
  6064. ATLTRACE(atlTraceCOM, 0, _T("Failed to get a dispatch pointer for property #%i\n"), i);
  6065. hr = E_FAIL;
  6066. break;
  6067. }
  6068. piidOld = pMap[i].piidDispatch;
  6069. }
  6070.  
  6071. if (FAILED(pDispatch.PutProperty(pMap[i].dispid, &var)))
  6072. {
  6073. ATLTRACE(atlTraceCOM, 0, _T("Invoked failed on DISPID %x\n"), pMap[i].dispid);
  6074. hr = E_FAIL;
  6075. break;
  6076. }
  6077. }
  6078. return hr;
  6079. }
  6080.  
  6081. ATLINLINE ATLAPI AtlIPersistStreamInit_Save(LPSTREAM pStm,
  6082. BOOL /* fClearDirty */, const ATL_PROPMAP_ENTRY* pMap,
  6083. void* pThis, IUnknown* pUnk)
  6084. {
  6085. ATLASSERT(pMap != NULL);
  6086. if (pStm == NULL || pMap == NULL || pThis == NULL || pUnk == NULL)
  6087. return E_INVALIDARG;
  6088.  
  6089. DWORD dw = _ATL_VER;
  6090. HRESULT hr = pStm->Write(&dw, sizeof(DWORD), NULL);
  6091. if (FAILED(hr))
  6092. return hr;
  6093.  
  6094. CComPtr<IDispatch> pDispatch;
  6095. const IID* piidOld = NULL;
  6096. for (int i = 0; pMap[i].pclsidPropPage != NULL; i++)
  6097. {
  6098. if (pMap[i].szDesc == NULL)
  6099. continue;
  6100.  
  6101. // check if raw data entry
  6102. if (pMap[i].dwSizeData != 0)
  6103. {
  6104. void* pData = (void*) (pMap[i].dwOffsetData + (DWORD_PTR)pThis);
  6105. // call CComBSTR::WriteToStream for BSTRs
  6106. if (pMap[i].vt == VT_BSTR)
  6107. {
  6108. CComBSTR bstrWrite;
  6109. bstrWrite.Attach(*(BSTR*)pData);
  6110. hr = bstrWrite.WriteToStream(pStm);
  6111. bstrWrite.Detach();
  6112. }
  6113. else
  6114. hr = pStm->Write(pData, pMap[i].dwSizeData, NULL);
  6115. if (FAILED(hr))
  6116. return hr;
  6117. continue;
  6118. }
  6119.  
  6120. CComVariant var;
  6121. if (pMap[i].piidDispatch != piidOld)
  6122. {
  6123. pDispatch.Release();
  6124. ATLENSURE_RETURN(pMap[i].piidDispatch);
  6125. if (FAILED(pUnk->QueryInterface(*pMap[i].piidDispatch, (void**)&pDispatch)))
  6126. {
  6127. ATLTRACE(atlTraceCOM, 0, _T("Failed to get a dispatch pointer for property #%i\n"), i);
  6128. hr = E_FAIL;
  6129. break;
  6130. }
  6131. piidOld = pMap[i].piidDispatch;
  6132. }
  6133.  
  6134. if (FAILED(pDispatch.GetProperty(pMap[i].dispid, &var)))
  6135. {
  6136. ATLTRACE(atlTraceCOM, 0, _T("Invoked failed on DISPID %x\n"), pMap[i].dispid);
  6137. hr = E_FAIL;
  6138. break;
  6139. }
  6140.  
  6141. hr = var.WriteToStream(pStm, pMap[i].vt);
  6142. if (FAILED(hr))
  6143. break;
  6144. }
  6145. return hr;
  6146. }
  6147. ATLINLINE ATLAPI AtlIPersistPropertyBag_Load(LPPROPERTYBAG pPropBag, LPERRORLOG pErrorLog, const ATL_PROPMAP_ENTRY* pMap, void* pThis, IUnknown* pUnk)
  6148. {
  6149. if (pPropBag == NULL || pMap == NULL || pThis == NULL || pUnk == NULL)
  6150. return E_INVALIDARG;
  6151.  
  6152. CComPtr<IDispatch> pDispatch;
  6153. const IID* piidOld = NULL;
  6154. for (int i = 0; pMap[i].pclsidPropPage != NULL; i++)
  6155. {
  6156. if (pMap[i].szDesc == NULL)
  6157. continue;
  6158.  
  6159. CComVariant var;
  6160.  
  6161. if (pMap[i].dwSizeData != 0)
  6162. {
  6163. var.ClearToZero();
  6164. var.vt = pMap[i].vt;
  6165. void* pData = (void*) (pMap[i].dwOffsetData + (DWORD_PTR)pThis);
  6166. HRESULT hr = pPropBag->Read(pMap[i].szDesc, &var, pErrorLog);
  6167. if (SUCCEEDED(hr))
  6168. {
  6169. // check the type - we only deal with limited set
  6170. switch (pMap[i].vt)
  6171. {
  6172. case VT_UI1:
  6173. case VT_I1:
  6174. *((BYTE*)pData) = var.bVal;
  6175. break;
  6176. case VT_BOOL:
  6177. *((VARIANT_BOOL*)pData) = var.boolVal;
  6178. break;
  6179. case VT_I2:
  6180. case VT_UI2:
  6181. *((short*)pData) = var.iVal;
  6182. break;
  6183. case VT_I4:
  6184. case VT_UI4:
  6185. case VT_INT:
  6186. case VT_UINT:
  6187. *((long*)pData) = var.lVal;
  6188. break;
  6189. case VT_BSTR:
  6190. *((BSTR*)pData) = ::SysAllocString(var.bstrVal);
  6191. if (*((BSTR*)pData) == NULL && var.bstrVal != NULL)
  6192. return E_OUTOFMEMORY;
  6193. break;
  6194. }
  6195. }
  6196. else
  6197. {
  6198. var.vt = VT_EMPTY;
  6199. }
  6200. continue;
  6201. }
  6202.  
  6203. if (pMap[i].piidDispatch != piidOld)
  6204. {
  6205. pDispatch.Release();
  6206. ATLENSURE_RETURN(pMap[i].piidDispatch);
  6207. if (FAILED(pUnk->QueryInterface(*pMap[i].piidDispatch, (void**)&pDispatch)))
  6208. {
  6209. ATLTRACE(atlTraceCOM, 0, _T("Failed to get a dispatch pointer for property #%i\n"), i);
  6210. return E_FAIL;
  6211. }
  6212. piidOld = pMap[i].piidDispatch;
  6213. }
  6214.  
  6215. VARTYPE vt = pMap[i].vt;
  6216. if (vt == VT_EMPTY)
  6217. {
  6218. if (FAILED(pDispatch.GetProperty(pMap[i].dispid, &var)))
  6219. {
  6220. ATLTRACE(atlTraceCOM, 0, _T("Invoked failed on DISPID %x\n"), pMap[i].dispid);
  6221. return E_FAIL;
  6222. }
  6223. vt = var.vt;
  6224. }
  6225.  
  6226. var.ClearToZero();
  6227. var.vt = vt;
  6228.  
  6229. HRESULT hr = pPropBag->Read(pMap[i].szDesc, &var, pErrorLog);
  6230. if (FAILED(hr))
  6231. {
  6232. #ifdef _DEBUG
  6233. COLE2CT strDesc(pMap[i].szDesc);
  6234. LPCTSTR lp = static_cast<LPCTSTR>(strDesc);
  6235.  
  6236. if (hr == E_INVALIDARG)
  6237. {
  6238. if (lp == NULL)
  6239. ATLTRACE(atlTraceCOM, 0, _T("Property not in Bag\n"));
  6240. else
  6241. ATLTRACE(atlTraceCOM, 0, _T("Property %s not in Bag\n"), lp);
  6242. }
  6243. else
  6244. {
  6245. // Many containers return different ERROR values for Member not found
  6246. if (lp == NULL)
  6247. ATLTRACE(atlTraceCOM, 0, _T("Error attempting to read Property from PropertyBag \n"));
  6248. else
  6249. ATLTRACE(atlTraceCOM, 0, _T("Error attempting to read Property %s from PropertyBag \n"), lp);
  6250. }
  6251. #endif
  6252. var.vt = VT_EMPTY;
  6253. continue;
  6254. }
  6255.  
  6256. if (FAILED(pDispatch.PutProperty(pMap[i].dispid, &var)))
  6257. {
  6258. ATLTRACE(atlTraceCOM, 0, _T("Invoked failed on DISPID %x\n"), pMap[i].dispid);
  6259. return E_FAIL;
  6260. }
  6261. }
  6262. return S_OK;
  6263. }
  6264. ATLINLINE ATLAPI AtlIPersistPropertyBag_Save(LPPROPERTYBAG pPropBag,
  6265. BOOL /* fClearDirty */, BOOL /* fSaveAllProperties */,
  6266. const ATL_PROPMAP_ENTRY* pMap, void* pThis, IUnknown* pUnk)
  6267. {
  6268. if (pPropBag == NULL)
  6269. {
  6270. ATLTRACE(atlTraceCOM, 0, _T("PropBag pointer passed in was invalid\n"));
  6271. return E_INVALIDARG;
  6272. }
  6273. if (pMap == NULL || pThis == NULL || pUnk == NULL)
  6274. return E_INVALIDARG;
  6275.  
  6276. CComPtr<IDispatch> pDispatch;
  6277. const IID* piidOld = NULL;
  6278. for (int i = 0; pMap[i].pclsidPropPage != NULL; i++)
  6279. {
  6280. if (pMap[i].szDesc == NULL)
  6281. continue;
  6282.  
  6283. CComVariant var;
  6284.  
  6285. if (pMap[i].dwSizeData != 0)
  6286. {
  6287. void* pData = (void*) (pMap[i].dwOffsetData + (DWORD_PTR)pThis);
  6288. // check the type - we only deal with limited set
  6289. bool bTypeOK = false;
  6290. switch (pMap[i].vt)
  6291. {
  6292. case VT_UI1:
  6293. case VT_I1:
  6294. var.bVal = *((BYTE*)pData);
  6295. bTypeOK = true;
  6296. break;
  6297. case VT_BOOL:
  6298. var.boolVal = *((VARIANT_BOOL*)pData);
  6299. bTypeOK = true;
  6300. break;
  6301. case VT_UI2:
  6302. var.iVal = *((short*)pData);
  6303. bTypeOK = true;
  6304. break;
  6305. case VT_UI4:
  6306. case VT_INT:
  6307. case VT_UINT:
  6308. var.lVal = *((long*)pData);
  6309. bTypeOK = true;
  6310. break;
  6311. case VT_BSTR:
  6312. var.bstrVal = ::SysAllocString(*((BSTR*)pData));
  6313. if (var.bstrVal == NULL && *((BSTR*)pData) != NULL)
  6314. return E_OUTOFMEMORY;
  6315. bTypeOK = true;
  6316. break;
  6317. }
  6318. if (bTypeOK)
  6319. {
  6320. var.vt = pMap[i].vt;
  6321. HRESULT hr = pPropBag->Write(pMap[i].szDesc, &var);
  6322. if (FAILED(hr))
  6323. return hr;
  6324. }
  6325. continue;
  6326. }
  6327.  
  6328. if (pMap[i].piidDispatch != piidOld)
  6329. {
  6330. pDispatch.Release();
  6331. ATLENSURE_RETURN(pMap[i].piidDispatch);
  6332. if (FAILED(pUnk->QueryInterface(*pMap[i].piidDispatch, (void**)&pDispatch)))
  6333. {
  6334. ATLTRACE(atlTraceCOM, 0, _T("Failed to get a dispatch pointer for property #%i\n"), i);
  6335. return E_FAIL;
  6336. }
  6337. piidOld = pMap[i].piidDispatch;
  6338. }
  6339.  
  6340. if (FAILED(pDispatch.GetProperty(pMap[i].dispid, &var)))
  6341. {
  6342. ATLTRACE(atlTraceCOM, 0, _T("Invoked failed on DISPID %x\n"), pMap[i].dispid);
  6343. return E_FAIL;
  6344. }
  6345.  
  6346. if (pMap[i].vt != VT_EMPTY && pMap[i].vt != var.vt)
  6347. {
  6348. HRESULT hr = var.ChangeType(pMap[i].vt);
  6349. if (FAILED(hr))
  6350. return hr;
  6351. }
  6352.  
  6353. if (var.vt == VT_UNKNOWN || var.vt == VT_DISPATCH)
  6354. {
  6355. if (var.punkVal == NULL)
  6356. {
  6357. ATLTRACE(atlTraceCOM, 2, _T("Warning skipping empty IUnknown in Save\n"));
  6358. continue;
  6359. }
  6360. }
  6361.  
  6362. HRESULT hr = pPropBag->Write(pMap[i].szDesc, &var);
  6363. if (FAILED(hr))
  6364. return hr;
  6365. }
  6366. return S_OK;
  6367. }
  6368.  
  6369. /////////////////////////////////////////////////////////////////////////////
  6370. // Connection Point Sink Helper
  6371.  
  6372. ATLINLINE ATLAPI AtlGetObjectSourceInterface(IUnknown* punkObj, GUID* plibid, IID* piid, unsigned short* pdwMajor, unsigned short* pdwMinor)
  6373. {
  6374. if (plibid == NULL || piid == NULL || pdwMajor == NULL || pdwMinor == NULL)
  6375. return E_POINTER;
  6376.  
  6377. *plibid = GUID_NULL;
  6378. *piid = IID_NULL;
  6379. *pdwMajor = 0;
  6380. *pdwMinor = 0;
  6381.  
  6382.  
  6383. HRESULT hr = E_FAIL;
  6384. if (punkObj != NULL)
  6385. {
  6386. CComPtr<IDispatch> spDispatch;
  6387. hr = punkObj->QueryInterface(__uuidof(IDispatch), (void**)&spDispatch);
  6388. if (SUCCEEDED(hr))
  6389. {
  6390. CComPtr<ITypeInfo> spTypeInfo;
  6391. hr = spDispatch->GetTypeInfo(0, 0, &spTypeInfo);
  6392. if (SUCCEEDED(hr))
  6393. {
  6394. CComPtr<ITypeLib> spTypeLib;
  6395. hr = spTypeInfo->GetContainingTypeLib(&spTypeLib, 0);
  6396. if (SUCCEEDED(hr))
  6397. {
  6398. TLIBATTR* plibAttr;
  6399. hr = spTypeLib->GetLibAttr(&plibAttr);
  6400. if (SUCCEEDED(hr))
  6401. {
  6402. Checked::memcpy_s(plibid, sizeof(GUID), &plibAttr->guid, sizeof(GUID));
  6403. *pdwMajor = plibAttr->wMajorVerNum;
  6404. *pdwMinor = plibAttr->wMinorVerNum;
  6405. spTypeLib->ReleaseTLibAttr(plibAttr);
  6406. // First see if the object is willing to tell us about the
  6407. // default source interface via IProvideClassInfo2
  6408. CComPtr<IProvideClassInfo2> spProvideClassInfo;
  6409. hr = punkObj->QueryInterface(__uuidof(IProvideClassInfo2), (void**)&spProvideClassInfo);
  6410. if (SUCCEEDED(hr) && spProvideClassInfo != NULL)
  6411. hr = spProvideClassInfo->GetGUID(GUIDKIND_DEFAULT_SOURCE_DISP_IID, piid);
  6412. else
  6413. {
  6414. // No, we have to go hunt for it
  6415. CComPtr<ITypeInfo> spInfoCoClass;
  6416. // If we have a clsid, use that
  6417. // Otherwise, try to locate the clsid from IPersist
  6418. CComPtr<IPersist> spPersist;
  6419. CLSID clsid;
  6420. hr = punkObj->QueryInterface(__uuidof(IPersist), (void**)&spPersist);
  6421. if (SUCCEEDED(hr))
  6422. {
  6423. hr = spPersist->GetClassID(&clsid);
  6424. if (SUCCEEDED(hr))
  6425. {
  6426. hr = spTypeLib->GetTypeInfoOfGuid(clsid, &spInfoCoClass);
  6427. if (SUCCEEDED(hr))
  6428. {
  6429. TYPEATTR* pAttr=NULL;
  6430. spInfoCoClass->GetTypeAttr(&pAttr);
  6431. if (pAttr != NULL)
  6432. {
  6433. HREFTYPE hRef;
  6434. for (int i = 0; i < pAttr->cImplTypes; i++)
  6435. {
  6436. int nType;
  6437. hr = spInfoCoClass->GetImplTypeFlags(i, &nType);
  6438. if (SUCCEEDED(hr))
  6439. {
  6440. if (nType == (IMPLTYPEFLAG_FDEFAULT | IMPLTYPEFLAG_FSOURCE))
  6441. {
  6442. // we found it
  6443. hr = spInfoCoClass->GetRefTypeOfImplType(i, &hRef);
  6444. if (SUCCEEDED(hr))
  6445. {
  6446. CComPtr<ITypeInfo> spInfo;
  6447. hr = spInfoCoClass->GetRefTypeInfo(hRef, &spInfo);
  6448. if (SUCCEEDED(hr))
  6449. {
  6450. TYPEATTR* pAttrIF;
  6451. spInfo->GetTypeAttr(&pAttrIF);
  6452. if (pAttrIF != NULL)
  6453. {
  6454. Checked::memcpy_s(piid, sizeof(GUID), &pAttrIF->guid, sizeof(GUID));
  6455. spInfo->ReleaseTypeAttr(pAttrIF);
  6456. }
  6457. }
  6458. }
  6459. break;
  6460. }
  6461. }
  6462. }
  6463. spInfoCoClass->ReleaseTypeAttr(pAttr);
  6464. }
  6465. }
  6466. }
  6467. }
  6468. }
  6469. }
  6470. }
  6471. }
  6472. }
  6473. }
  6474. return hr;
  6475. }
  6476.  
  6477. #endif // !_ATL_DLL
  6478.  
  6479. } // namespace ATL
  6480. #pragma pack(pop)
  6481.  
  6482. #ifdef _ATL_ALL_WARNINGS
  6483. #pragma warning( pop )
  6484. #endif
  6485.  
  6486. #ifndef _ATL_NO_PRAGMA_WARNINGS
  6487. #pragma warning (pop)
  6488. #endif
  6489.  
  6490. #endif // __ATLCOM_H__
  6491.  
  6492. /////////////////////////////////////////////////////////////////////////////
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement