Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

320 lines
9.0 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1999 - 1999
  6. //
  7. // File: tiedobj.h
  8. //
  9. // History: 08/28/1999 VivekJ Created
  10. //--------------------------------------------------------------------------
  11. #ifndef TIEDOBJ_H
  12. #define TIEDOBJ_H
  13. #pragma once
  14. #include "conuistr.h" // for MMC_E_OBJECT_IS_GONE
  15. /************************************************************************
  16. * This file provides base and template class support to encapsulate the
  17. * relationship between an object and a COM tearoff object that holds a pointer
  18. * to that object.
  19. * The object is referred to as the Tied object, since the COM object is
  20. * "tied" to it, and cannot do anything useful apart from it.
  21. * The COM object disables itself when the tied object is deleted. This
  22. * allows for automatic detection of dead states. An object can also "orphan"
  23. * all COM objects tied to it by calling the UnadviseAll method.
  24. *
  25. * An example of a tied object relationship is that of CAMCDoc and CMMCDocument.
  26. * CMMCDocument is derived from CTiedComObject<CAMCDoc>, and CAMCDoc derives
  27. * from CTiedObject. CAMCDoc thus keeps a list of all COM object that are tied
  28. * to it, and notifies them when it is destroyed. Similarly, the COM objects notify
  29. * the tied object when they are destroyed, so that they are removed from the list.
  30. *
  31. * NOTE: the tied object does NOT addref the COM objects, it just keeps a list of them.
  32. * If it was to addref them, there would be all sorts of circular lifetime problems.
  33. * By ensuring that the tied object and the COM objects notify each other of their
  34. * own destruction, lifetime management is correctly handled.
  35. *
  36. * Use CTiedComObjectCreator::ScCreateAndConnect to create an instance of the
  37. * COM object and tie it to the tied object.
  38. *
  39. ************************************************************************/
  40. class CTiedObject;
  41. class CTiedComObjectRoot;
  42. /*+-------------------------------------------------------------------------*
  43. * class CTiedComObjectRoot
  44. *
  45. *
  46. * PURPOSE: Base class for CTiedComObject
  47. *
  48. *+-------------------------------------------------------------------------*/
  49. class CTiedComObjectRoot
  50. {
  51. public:
  52. virtual void Unadvise() = 0; // so that the tied object can inform that it is being deleted.
  53. };
  54. /*+-------------------------------------------------------------------------*
  55. * class CTiedObject
  56. *
  57. *
  58. * PURPOSE: The base class that any object which has COM objects tied to
  59. * it should derive from. Provides methods to add a new COM object
  60. * to its list of tied objects, to remove a COM object from its
  61. * list, and to
  62. *
  63. *+-------------------------------------------------------------------------*/
  64. class CTiedObject
  65. {
  66. typedef CTiedComObjectRoot * PTIEDCOMOBJECTROOT;
  67. typedef std::list<PTIEDCOMOBJECTROOT> CTiedComObjects;
  68. CTiedComObjects m_TiedComObjects;
  69. public:
  70. SC ScAddToList(CTiedComObjectRoot *p);
  71. void RemoveFromList(CTiedComObjectRoot *p);
  72. virtual ~CTiedObject();
  73. protected:
  74. void UnadviseAll();
  75. };
  76. /*+-------------------------------------------------------------------------*
  77. *
  78. * CTiedObject::ScAddToList
  79. *
  80. * PURPOSE: Adds the COM object to the list of objects. Usually called soon
  81. * after constructing the COM object.
  82. *
  83. * PARAMETERS:
  84. * CTiedComObjectRoot * p :
  85. *
  86. * RETURNS:
  87. * inline SC
  88. *
  89. *+-------------------------------------------------------------------------*/
  90. inline
  91. SC CTiedObject::ScAddToList(CTiedComObjectRoot *p)
  92. {
  93. DECLARE_SC (sc, _T("CTiedObject::ScAddToList"));
  94. if(!p)
  95. return (sc = E_INVALIDARG);
  96. m_TiedComObjects.push_back(p);
  97. return sc;
  98. }
  99. /*+-------------------------------------------------------------------------*
  100. *
  101. * CTiedObject::RemoveFromList
  102. *
  103. * PURPOSE: Removes the specfied COM object from the list of COM objects.
  104. * Usually called from the destructor of the COM object.
  105. *
  106. * PARAMETERS:
  107. * CTiedComObjectRoot * p : The COM object.
  108. *
  109. * RETURNS:
  110. * inline void
  111. *
  112. *+-------------------------------------------------------------------------*/
  113. inline
  114. void CTiedObject::RemoveFromList(CTiedComObjectRoot *p)
  115. {
  116. CTiedComObjects::iterator iter;
  117. iter = std::find (m_TiedComObjects.begin(), m_TiedComObjects.end(), p);
  118. ASSERT(iter != m_TiedComObjects.end());
  119. if(iter != m_TiedComObjects.end())
  120. m_TiedComObjects.erase(iter);
  121. }
  122. inline
  123. void CTiedObject::UnadviseAll()
  124. {
  125. CTiedComObjects::iterator iter;
  126. for(iter = m_TiedComObjects.begin(); iter != m_TiedComObjects.end(); iter++)
  127. {
  128. (*iter)->Unadvise();
  129. }
  130. }
  131. inline
  132. CTiedObject::~CTiedObject()
  133. {
  134. UnadviseAll();
  135. }
  136. /*+-------------------------------------------------------------------------*
  137. * template class CTiedComObject
  138. *
  139. *
  140. * PURPOSE: The base class for COM objects that are tied to non-COM objects
  141. * for instance, CMMCDocument is tied to CAMCDoc - it delegates
  142. * all its methods to the tied object.
  143. *
  144. *+-------------------------------------------------------------------------*/
  145. template <class TiedObjectClass>
  146. class CTiedComObject : public CTiedComObjectRoot
  147. {
  148. friend class TiedObjectClass;
  149. public:
  150. CTiedComObject() : m_pT(NULL) {}
  151. virtual ~CTiedComObject();
  152. void SetTiedObject(TiedObjectClass *pT);
  153. protected:
  154. // called by the COM methods to make sure that the tied object exists.
  155. SC ScGetTiedObject(TiedObjectClass*&pT);
  156. bool IsTied() { return m_pT != NULL; }
  157. void Unadvise();
  158. private:
  159. TiedObjectClass *m_pT;
  160. };
  161. /*+-------------------------------------------------------------------------*
  162. *
  163. * ~CTiedComObject
  164. *
  165. * PURPOSE: Destructor. Tells the tied object to remove this one from
  166. * its list of tied COM objects.
  167. *
  168. *+-------------------------------------------------------------------------*/
  169. template<class TiedObjectClass>
  170. CTiedComObject<TiedObjectClass>::~CTiedComObject()
  171. {
  172. if(m_pT != NULL)
  173. {
  174. m_pT->RemoveFromList(this);
  175. }
  176. }
  177. template<class TiedObjectClass>
  178. void
  179. CTiedComObject<TiedObjectClass>::SetTiedObject(TiedObjectClass *pT)
  180. {
  181. ASSERT(pT != NULL);
  182. m_pT = pT;
  183. }
  184. template<class TiedObjectClass>
  185. inline void
  186. CTiedComObject<TiedObjectClass>::Unadvise()
  187. {
  188. m_pT = NULL;
  189. }
  190. /*+-------------------------------------------------------------------------*
  191. *
  192. * CTiedComObject::ScGetTiedObject
  193. *
  194. * PURPOSE: Checks that a valid tied object pointer exists, and returns it.
  195. *
  196. * PARAMETERS:
  197. * TiedObjectClass** ppT : [OUT]: The object pointer
  198. *
  199. * RETURNS:
  200. * SC: MMC_E_OBJECT_IS_GONE if no valid pointer exists.
  201. *+-------------------------------------------------------------------------*/
  202. template<class TiedObjectClass>
  203. inline SC
  204. CTiedComObject<TiedObjectClass>::ScGetTiedObject(TiedObjectClass*&pT)
  205. {
  206. DECLARE_SC (sc, _T("CTiedComObject::ScGetTiedObject"));
  207. pT = m_pT;
  208. if(NULL == m_pT)
  209. return (sc = ScFromMMC(MMC_E_OBJECT_IS_GONE));
  210. return (sc);
  211. }
  212. /*+-------------------------------------------------------------------------*
  213. *
  214. * ScCreateConnection
  215. *
  216. * PURPOSE: Creates a two-way connection between a COM object and its tied
  217. * object.
  218. *
  219. * PARAMETERS:
  220. * TiedComObjClass comObj :
  221. * TiedObjClass obj :
  222. *
  223. * RETURNS:
  224. * SC
  225. *
  226. *+-------------------------------------------------------------------------*/
  227. template<class TiedComObjClass, class TiedObjClass>
  228. SC ScCreateConnection(TiedComObjClass &comObj, TiedObjClass &obj)
  229. {
  230. DECLARE_SC (sc, _T("ScCreateConnection"));
  231. sc = obj.ScAddToList(&comObj);
  232. if(sc)
  233. return (sc);
  234. comObj.SetTiedObject(&obj);
  235. return (sc);
  236. }
  237. /*+-------------------------------------------------------------------------*
  238. * CTiedComObjectCreator
  239. *
  240. *
  241. * PURPOSE: has a single static function, ScCreateAndConnect, which creates
  242. * an instance of the COM object (if the smart pointer supplied is
  243. * NULL) and connects it to the Tied object supplied.
  244. *
  245. *+-------------------------------------------------------------------------*/
  246. template <class TiedComObjectClass>
  247. class CTiedComObjectCreator
  248. {
  249. public:
  250. template<class TiedObjClass, class SmartPointerClass>
  251. static SC ScCreateAndConnect(TiedObjClass &obj, SmartPointerClass &smartPointer)
  252. {
  253. DECLARE_SC(sc, TEXT("CTiedComObjectCreator::ScCreateAndConnect") );
  254. // if the object has not yet been created, create it.
  255. if(smartPointer == NULL)
  256. {
  257. CComObject<TiedComObjectClass> *pTiedComObject = NULL;
  258. sc = CComObject<TiedComObjectClass>::CreateInstance(&pTiedComObject);
  259. if (sc)
  260. return (sc);
  261. if(!pTiedComObject)
  262. return (sc = E_UNEXPECTED);
  263. sc = ScCreateConnection(*pTiedComObject, obj); // create a link between the tied obj and tied com obj.
  264. if(sc)
  265. return sc;
  266. smartPointer = pTiedComObject; // This AddRef's it once. need to addref it for the client as well.
  267. }
  268. return sc;
  269. }
  270. };
  271. #endif // TIEDOBJ_H