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.

285 lines
7.6 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997.
  5. //
  6. // File: N C A T L . H
  7. //
  8. // Contents: Common code for use with ATL.
  9. //
  10. // Notes: Pollute this under penalty of death.
  11. //
  12. // Author: shaunco 22 Sep 1997
  13. //
  14. //----------------------------------------------------------------------------
  15. #pragma once
  16. #ifndef _NCATL_H_
  17. #define _NCATL_H_
  18. #include "ncbase.h"
  19. #include "ncstring.h"
  20. //
  21. // This file should be included *after* your standard ATL include sequence.
  22. //
  23. // #include <atlbase.h>
  24. // extern CComModule _Module;
  25. // #include <atlcom.h>
  26. // #include "ncatl.h" <------
  27. //
  28. // We cannot directly include that sequence here because _Module may be
  29. // derived from CComModule as opposed to an instance of it.
  30. //
  31. class CExceptionSafeComObjectLock
  32. {
  33. public:
  34. CExceptionSafeComObjectLock (CComObjectRootEx <CComMultiThreadModel>* pObj)
  35. {
  36. AssertH (pObj);
  37. m_pObj = pObj;
  38. TraceTag (ttidEsLock,
  39. "Entered critical section object of COM object 0x%08x",
  40. &m_pObj);
  41. pObj->Lock ();
  42. }
  43. ~CExceptionSafeComObjectLock ()
  44. {
  45. TraceTag (ttidEsLock,
  46. "Leaving critical section object of COM object 0x%08x",
  47. &m_pObj);
  48. m_pObj->Unlock ();
  49. }
  50. protected:
  51. CComObjectRootEx <CComMultiThreadModel>* m_pObj;
  52. };
  53. //+---------------------------------------------------------------------------
  54. //
  55. // Function: HrCopyIUnknownArrayWhileLocked
  56. //
  57. // Purpose: Allocate and copy an array of IUnknown pointers from an ATL
  58. // CComDynamicUnkArray while holding the object which controls
  59. // the CComDynamicUnkArray locked. This is needed by objects
  60. // which dispatch calls on a connection point's advise sink
  61. // to prevent the CComDynamicUnkArray from being modified (via
  62. // calls to Advise/Unadvise on other threads) while they are
  63. // dispatching. An atomic copy is made so the dispatcher can
  64. // then make the lengthy callbacks without the need to hold
  65. // the owner object locked.
  66. //
  67. // Arguments:
  68. // pObj [in] Pointer to object which has Lock/Unlock methods.
  69. // pVec [in] ATL array of IUnknown's to copy.
  70. // pcUnk [out] Address of returned count of IUnknown pointerss
  71. // in *paUnk.
  72. // paUnk [out] Address of allocated pointer to the array of IUnknown
  73. // pointers.
  74. //
  75. // Returns: S_OK or E_OUTOFMEMORY
  76. //
  77. // Author: shaunco 3 Dec 1998
  78. //
  79. // Notes: The returned count and array may be NULL when no IUnknowns
  80. // existed in the input array. S_OK will be returned for this
  81. // case too, so be sure to check *pcUnk and *paUnk too.
  82. //
  83. inline
  84. HRESULT
  85. HrCopyIUnknownArrayWhileLocked (
  86. IN CComObjectRootEx <CComMultiThreadModel>* pObj,
  87. IN CComDynamicUnkArray* pVec,
  88. OUT ULONG* pcpUnk,
  89. OUT IUnknown*** papUnk)
  90. {
  91. HRESULT hr = S_OK;
  92. IUnknown** ppUnkSrc;
  93. IUnknown** ppUnkDst;
  94. // Initialize the output parameters.
  95. //
  96. *pcpUnk = 0;
  97. *papUnk = NULL;
  98. pObj->Lock();
  99. // First, count the number of IUnknown's we need to copy.
  100. //
  101. ULONG cpUnk = 0;
  102. for (ppUnkSrc = pVec->begin(); ppUnkSrc < pVec->end(); ppUnkSrc++)
  103. {
  104. if (ppUnkSrc && *ppUnkSrc)
  105. {
  106. cpUnk++;
  107. }
  108. }
  109. // Allocate space and copy the IUnknown's. (Be sure to AddRef them.)
  110. //
  111. if (cpUnk)
  112. {
  113. hr = E_OUTOFMEMORY;
  114. ppUnkDst = (IUnknown**)MemAlloc (cpUnk * sizeof(IUnknown*));
  115. if (ppUnkDst)
  116. {
  117. hr = S_OK;
  118. *pcpUnk = cpUnk;
  119. *papUnk = ppUnkDst;
  120. for (ppUnkSrc = pVec->begin(); ppUnkSrc < pVec->end(); ppUnkSrc++)
  121. {
  122. if (ppUnkSrc && *ppUnkSrc)
  123. {
  124. *ppUnkDst = *ppUnkSrc;
  125. AddRefObj(*ppUnkDst);
  126. ppUnkDst++;
  127. cpUnk--;
  128. }
  129. }
  130. // We should have copied what we counted.
  131. //
  132. AssertH(0 == cpUnk);
  133. }
  134. }
  135. pObj->Unlock();
  136. TraceHr (ttidError, FAL, hr, FALSE, "HrCopyIUnknownArrayWhileLocked");
  137. return hr;
  138. }
  139. #define DECLARE_CLASSFACTORY_DEFERRED_SINGLETON(obj) DECLARE_CLASSFACTORY_EX(CComClassFactoryDeferredSingleton<obj>)
  140. //+---------------------------------------------------------------------------
  141. // Deferred Singleton Class Factory
  142. //
  143. template <class T>
  144. class CComClassFactoryDeferredSingleton : public CComClassFactory
  145. {
  146. public:
  147. CComClassFactoryDeferredSingleton () : m_pObj(NULL) {}
  148. ~CComClassFactoryDeferredSingleton() { delete m_pObj; }
  149. // IClassFactory
  150. STDMETHOD(CreateInstance)(LPUNKNOWN pUnkOuter, REFIID riid, void** ppvObj)
  151. {
  152. HRESULT hr = E_POINTER;
  153. if (ppvObj != NULL)
  154. {
  155. // can't ask for anything other than IUnknown when aggregating
  156. //
  157. AssertH(!pUnkOuter || InlineIsEqualUnknown(riid));
  158. if (pUnkOuter && !InlineIsEqualUnknown(riid))
  159. {
  160. hr = CLASS_E_NOAGGREGATION;
  161. }
  162. else
  163. {
  164. // Need to protect m_pObj from being created more than once
  165. // by multiple threads calling this method simultaneously.
  166. // (I've seen this happen on multi-proc machines.)
  167. //
  168. Lock ();
  169. if (m_pObj)
  170. {
  171. hr = S_OK;
  172. }
  173. else
  174. {
  175. hr = E_OUTOFMEMORY;
  176. m_pObj = new CComObjectGlobal<T>;
  177. if (m_pObj)
  178. {
  179. hr = m_pObj->m_hResFinalConstruct;
  180. }
  181. }
  182. Unlock ();
  183. if (SUCCEEDED(hr))
  184. {
  185. hr = m_pObj->QueryInterface(riid, ppvObj);
  186. }
  187. }
  188. }
  189. return hr;
  190. }
  191. CComObjectGlobal<T>* m_pObj;
  192. };
  193. // We have our own version of AtlModuleRegisterServer coded here
  194. // because the former brings in oleaut32.dll so it can register
  195. // type libraries. We don't care to have a type library registered
  196. // so we can avoid the whole the mess associated with oleaut32.dll.
  197. //
  198. inline
  199. HRESULT
  200. NcAtlModuleRegisterServer(
  201. _ATL_MODULE* pM
  202. )
  203. {
  204. AssertH (pM);
  205. AssertH(pM->m_hInst);
  206. AssertH(pM->m_pObjMap);
  207. HRESULT hr = S_OK;
  208. for (_ATL_OBJMAP_ENTRY* pEntry = pM->m_pObjMap;
  209. pEntry->pclsid;
  210. pEntry++)
  211. {
  212. if (pEntry->pfnGetObjectDescription() != NULL)
  213. {
  214. continue;
  215. }
  216. hr = pEntry->pfnUpdateRegistry(TRUE);
  217. if (FAILED(hr))
  218. {
  219. break;
  220. }
  221. }
  222. TraceError ("NcAtlModuleRegisterServer", hr);
  223. return hr;
  224. }
  225. #ifdef __ATLCOM_H__
  226. //+---------------------------------------------------------------------------
  227. //
  228. // Function: WszLoadIds
  229. //
  230. // Purpose: Loads the given string ID from the resource file.
  231. //
  232. // Arguments:
  233. // unId [in] ID of string resource to load.
  234. //
  235. // Returns: Read-only version of resource string.
  236. //
  237. // Author: shaunco 24 Mar 1997
  238. //
  239. // Notes: 1) You must be compiling with ATL support to use this function.
  240. // 2) The returned string CANNOT be modified.
  241. // 3) You must compile your RC file with the -N option for this
  242. // to work properly.
  243. //
  244. inline
  245. PCWSTR
  246. WszLoadIds (
  247. UINT unId)
  248. {
  249. return WszLoadString (_Module.GetResourceInstance(), unId);
  250. }
  251. #endif //!__ATLCOM_H__
  252. #endif // _NCATL_H_