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.

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