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

226 lines
6.3 KiB

  1. //******************************************************************************
  2. //
  3. // ESSUTILS.CPP
  4. //
  5. // Copyright (C) 1996-1999 Microsoft Corporation
  6. //
  7. //******************************************************************************
  8. #include "precomp.h"
  9. #include <stdio.h>
  10. #include "ess.h"
  11. #include "essutils.h"
  12. #include <tls.h>
  13. CTLS g_tlsContext;
  14. long g_lNumExternalThreadObjects = 0;
  15. INTERNAL CEssThreadObject* GetCurrentEssThreadObject()
  16. {
  17. CEssThreadObject* pObj = (CEssThreadObject*)g_tlsContext.Get();
  18. if ( pObj != NULL )
  19. {
  20. //
  21. // mark the fact that we are handing the thread object to the
  22. // outside world. We use this later on when checking
  23. // thread object leaks.
  24. //
  25. pObj->SetReferencedExternally();
  26. }
  27. return pObj;
  28. }
  29. void SetCurrentEssThreadObject(IWbemContext* pContext)
  30. {
  31. //
  32. // make sure we're not overwriting an existing internal thread object.
  33. // if its externally referenced, we really can't tell if this would
  34. // be a leak or not.
  35. //
  36. CEssThreadObject* pOldObj = (CEssThreadObject*)g_tlsContext.Get();
  37. _DBG_ASSERT( pOldObj == NULL || pOldObj->IsReferencedExternally() );
  38. CEssThreadObject* pObj = new CEssThreadObject(pContext);
  39. g_tlsContext.Set((void*)pObj);
  40. }
  41. void SetConstructedEssThreadObject(CEssThreadObject* pObj)
  42. {
  43. //
  44. // make sure we're not overwriting an existing internal thread object.
  45. // if its externally referenced, we really can't tell if this would
  46. // be a leak or not.
  47. //
  48. CEssThreadObject* pOldObj = (CEssThreadObject*)g_tlsContext.Get();
  49. _DBG_ASSERT( pOldObj == NULL || pOldObj->IsReferencedExternally() );
  50. //
  51. // since this object was passed in from the outside world, then
  52. // mark it as externally referenced.
  53. //
  54. if ( pObj != NULL )
  55. {
  56. pObj->SetReferencedExternally();
  57. }
  58. g_tlsContext.Set((void*)pObj);
  59. }
  60. void ClearCurrentEssThreadObject()
  61. {
  62. //
  63. // make sure we're not overwriting an existing internal thread object.
  64. // if its externally referenced, we really can't tell if this would
  65. // be a leak or not.
  66. //
  67. CEssThreadObject* pObj = (CEssThreadObject*)g_tlsContext.Get();
  68. _DBG_ASSERT( pObj == NULL || pObj->IsReferencedExternally() );
  69. g_tlsContext.Set(NULL);
  70. }
  71. INTERNAL IWbemContext* GetCurrentEssContext()
  72. {
  73. CEssThreadObject* pThreadObj = (CEssThreadObject*)g_tlsContext.Get();
  74. if(pThreadObj)
  75. return pThreadObj->m_pContext;
  76. else
  77. return NULL;
  78. }
  79. INTERNAL CPostponedList* GetCurrentPostponedList()
  80. {
  81. CEssThreadObject* pThreadObj = (CEssThreadObject*)g_tlsContext.Get();
  82. if(pThreadObj)
  83. return &pThreadObj->m_PostponedList;
  84. else
  85. return NULL;
  86. }
  87. INTERNAL CPostponedList* GetCurrentPostponedEventList()
  88. {
  89. CEssThreadObject* pThreadObj = (CEssThreadObject*)g_tlsContext.Get();
  90. if(pThreadObj)
  91. return &pThreadObj->m_PostponedEventList;
  92. else
  93. return NULL;
  94. }
  95. CEssThreadObject::CEssThreadObject( IWbemContext* pContext )
  96. : m_bReferencedExternally( FALSE )
  97. {
  98. m_pContext = pContext;
  99. if( m_pContext == NULL )
  100. {
  101. m_pContext = GetSpecialContext();
  102. }
  103. if ( m_pContext != NULL )
  104. {
  105. m_pContext->AddRef();
  106. }
  107. }
  108. void CEssThreadObject::SetReferencedExternally()
  109. {
  110. if ( !m_bReferencedExternally )
  111. {
  112. g_lNumExternalThreadObjects++;
  113. m_bReferencedExternally = TRUE;
  114. }
  115. }
  116. IWbemContext* CEssThreadObject::mstatic_pSpecialContext = NULL;
  117. INTERNAL IWbemContext* CEssThreadObject::GetSpecialContext()
  118. {
  119. // Create a "special" context object that will make sure that our
  120. // calls back into CIMOM are not blocked
  121. // ==============================================================
  122. if(mstatic_pSpecialContext == NULL)
  123. {
  124. IWbemCausalityAccess* pCause = NULL;
  125. HRESULT hres = CoCreateInstance(CLSID_WbemContext, NULL,
  126. CLSCTX_INPROC_SERVER, IID_IWbemCausalityAccess,
  127. (void**)&pCause);
  128. if(FAILED(hres))
  129. {
  130. ERRORTRACE((LOG_ESS, "Unable to create special context object: "
  131. "0x%X. Danger of deadlock\n", hres));
  132. return NULL;
  133. }
  134. CReleaseMe rm1(pCause);
  135. hres = pCause->MakeSpecial();
  136. if(FAILED(hres))
  137. {
  138. ERRORTRACE((LOG_ESS, "Unable to make the context special: "
  139. "0x%X. Danger of deadlock\n", hres));
  140. return NULL;
  141. }
  142. IWbemContext* pContext = NULL;
  143. hres = pCause->QueryInterface(IID_IWbemContext, (void**)&pContext);
  144. if(FAILED(hres))
  145. {
  146. ERRORTRACE((LOG_ESS, "Internal error: invalid context (0x%X)\n",
  147. hres));
  148. return NULL;
  149. }
  150. if(mstatic_pSpecialContext == NULL) // tiny window for a one-time leak
  151. mstatic_pSpecialContext = pContext;
  152. else
  153. pContext->Release();
  154. }
  155. return mstatic_pSpecialContext;
  156. }
  157. CEssThreadObject::~CEssThreadObject()
  158. {
  159. if ( m_bReferencedExternally )
  160. {
  161. g_lNumExternalThreadObjects--;
  162. //
  163. // since ClearCurrentEssThreadObject() can reference the
  164. // thread object ( for leak checking ) and because we previously
  165. // supported the thread object being deleted before
  166. // CurrentThreadEssThreadObject(), make sure that we perform the
  167. // Clear if the current thread object matches this one. This only
  168. // can happen when the thread object is referenced externally.
  169. //
  170. CEssThreadObject* pObj = (CEssThreadObject*)g_tlsContext.Get();
  171. if ( pObj == this )
  172. {
  173. ClearCurrentEssThreadObject();
  174. }
  175. }
  176. _DBG_ASSERT( m_PostponedList.IsEmpty() );
  177. if ( m_pContext != NULL )
  178. {
  179. m_pContext->Release();
  180. }
  181. }
  182. void /*static*/ CEssThreadObject::ClearSpecialContext()
  183. {
  184. // Call only when no other work can be taking place, e.g. in DllCanUnloadNow
  185. // =========================================================================
  186. if(mstatic_pSpecialContext)
  187. mstatic_pSpecialContext->Release();
  188. mstatic_pSpecialContext = NULL;
  189. }