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.

318 lines
7.3 KiB

  1. //***************************************************************************
  2. //
  3. // Copyright (c) 1998-1999 Microsoft Corporation
  4. //
  5. // ERROR.CPP
  6. //
  7. // alanbos 28-Jun-98 Created.
  8. //
  9. // Defines the WBEM error cache implementation
  10. //
  11. //***************************************************************************
  12. #include "precomp.h"
  13. #define NULLBSTR(x) \
  14. SysFreeString (x);\
  15. x = NULL;
  16. #define FREECOAUTH(x) \
  17. if (x)\
  18. {\
  19. WbemFreeAuthIdentity (x);\
  20. x = NULL;\
  21. }
  22. //***************************************************************************
  23. //
  24. // CWbemErrorCache::CWbemErrorCache
  25. //
  26. // DESCRIPTION:
  27. //
  28. // Constructor
  29. //
  30. //***************************************************************************
  31. CWbemErrorCache::CWbemErrorCache ()
  32. {
  33. InitializeCriticalSection (&m_cs);
  34. headPtr = NULL;
  35. }
  36. //***************************************************************************
  37. //
  38. // CWbemErrorCache::~CWbemErrorCache
  39. //
  40. // DESCRIPTION:
  41. //
  42. // Destructor
  43. //
  44. //***************************************************************************
  45. CWbemErrorCache::~CWbemErrorCache ()
  46. {
  47. EnterCriticalSection (&m_cs);
  48. ThreadError *pPtr = headPtr;
  49. while (pPtr)
  50. {
  51. // This is in case we re-enter here on the same thread.
  52. // This can happen when in an STA since the message loop may be invoked by the COM calls below.
  53. headPtr = pPtr->pNext;
  54. if (pPtr->pErrorObject)
  55. {
  56. pPtr->pErrorObject->Release ();
  57. pPtr->pErrorObject = NULL;
  58. }
  59. if (pPtr->pService)
  60. {
  61. pPtr->pService->Release ();
  62. pPtr->pService = NULL;
  63. }
  64. NULLBSTR (pPtr->strNamespacePath);
  65. NULLBSTR (pPtr->strAuthority);
  66. NULLBSTR (pPtr->strPrincipal);
  67. FREECOAUTH (pPtr->pCoAuthIdentity)
  68. ThreadError *pTmp = pPtr;
  69. pPtr = headPtr; // Bug ID 472474
  70. delete pTmp;
  71. }
  72. headPtr = NULL;
  73. LeaveCriticalSection (&m_cs);
  74. DeleteCriticalSection (&m_cs);
  75. }
  76. //***************************************************************************
  77. //
  78. // CWbemErrorCache::GetAndResetCurrentThreadError
  79. //
  80. // DESCRIPTION:
  81. //
  82. // Extract the WBEM error object (if any) from the current thread. This
  83. // is a once-only operation as the entry for that thread is cleared by this
  84. // read.
  85. //
  86. //***************************************************************************
  87. CSWbemObject *CWbemErrorCache::GetAndResetCurrentThreadError ()
  88. {
  89. CSWbemObject *pObject = NULL;
  90. DWORD threadId = GetCurrentThreadId ();
  91. EnterCriticalSection (&m_cs);
  92. ThreadError *pPtr = headPtr;
  93. while (pPtr)
  94. {
  95. if (threadId == pPtr->dwThreadId)
  96. {
  97. if (pPtr->pErrorObject)
  98. {
  99. // Unhook ThreadError prior to cleanup in case this is re-entered on the same thread
  100. // This can happen when in an STA since the message loop may be invoked by the COM calls below.
  101. if (pPtr == headPtr)
  102. headPtr = pPtr->pNext;
  103. if (pPtr->pNext)
  104. pPtr->pNext->pPrev = pPtr->pPrev;
  105. if (pPtr->pPrev)
  106. pPtr->pPrev->pNext = pPtr->pNext;
  107. CSWbemServices *pService = NULL;
  108. // Try and create a services object
  109. if (pPtr->pService)
  110. {
  111. pService = new CSWbemServices (pPtr->pService, pPtr->strNamespacePath,
  112. pPtr->pCoAuthIdentity, pPtr->strPrincipal,
  113. pPtr->strAuthority);
  114. if (pService)
  115. pService->AddRef ();
  116. }
  117. if (pPtr->pService)
  118. {
  119. pPtr->pService->Release ();
  120. pPtr->pService = NULL;
  121. }
  122. NULLBSTR (pPtr->strNamespacePath);
  123. NULLBSTR (pPtr->strAuthority);
  124. NULLBSTR (pPtr->strPrincipal);
  125. FREECOAUTH (pPtr->pCoAuthIdentity)
  126. pObject = new CSWbemObject (pService, pPtr->pErrorObject, NULL, true);
  127. pPtr->pErrorObject->Release ();
  128. pPtr->pErrorObject = NULL;
  129. if (pService)
  130. pService->Release ();
  131. // and finally delete the ThreadError...
  132. delete pPtr;
  133. }
  134. break;
  135. }
  136. pPtr = pPtr->pNext;
  137. }
  138. LeaveCriticalSection (&m_cs);
  139. return pObject;
  140. }
  141. //***************************************************************************
  142. //
  143. // CWbemErrorCache::SetCurrentThreadError
  144. //
  145. // DESCRIPTION:
  146. //
  147. // Set the WBEM error object (if any) for the current thread.
  148. //
  149. //***************************************************************************
  150. void CWbemErrorCache::SetCurrentThreadError (CSWbemServices *pService)
  151. {
  152. IErrorInfo * pInfo = NULL;
  153. if(SUCCEEDED(GetErrorInfo(0, &pInfo)) && pInfo)
  154. {
  155. // Is this a WBEM Error Object?
  156. IWbemClassObject * pObj = NULL;
  157. if(SUCCEEDED(pInfo->QueryInterface(IID_IWbemClassObject, (void **)&pObj)) && pObj)
  158. {
  159. EnterCriticalSection (&m_cs);
  160. //Remove the current one if present...
  161. ResetCurrentThreadError();
  162. DWORD threadId = GetCurrentThreadId ();
  163. // No entry for this thread anymore - create one at the head
  164. ThreadError *pTmp = headPtr;
  165. headPtr = new ThreadError;
  166. if (headPtr)
  167. {
  168. headPtr->pPrev = NULL;
  169. headPtr->pNext = pTmp;
  170. if (pTmp)
  171. pTmp->pPrev = headPtr;
  172. headPtr->dwThreadId = threadId;
  173. headPtr->pErrorObject = pObj;
  174. headPtr->pService = NULL;
  175. headPtr->strAuthority = NULL;
  176. headPtr->strPrincipal = NULL;
  177. headPtr->pCoAuthIdentity = NULL;
  178. headPtr->strNamespacePath = NULL;
  179. if (pService)
  180. {
  181. headPtr->pService = pService->GetIWbemServices ();
  182. CSWbemSecurity *pSecurity = pService->GetSecurityInfo ();
  183. if (pSecurity)
  184. {
  185. headPtr->strAuthority = SysAllocString (pSecurity->GetAuthority ());
  186. headPtr->strPrincipal = SysAllocString (pSecurity->GetPrincipal ());
  187. headPtr->pCoAuthIdentity = pSecurity->GetCoAuthIdentity ();
  188. pSecurity->Release ();
  189. }
  190. headPtr->strNamespacePath = SysAllocString(pService->GetPath ());
  191. }
  192. } else {
  193. headPtr = pTmp; // copy back the pointer to headPtr
  194. }
  195. LeaveCriticalSection (&m_cs);
  196. }
  197. pInfo->Release (); // To balance the GetErrorInfo call
  198. }
  199. }
  200. //***************************************************************************
  201. //
  202. // CWbemErrorCache::ResetCurrentThreadError
  203. //
  204. // DESCRIPTION:
  205. //
  206. // If there is an entry for the current thread then remove it
  207. //
  208. //***************************************************************************
  209. void CWbemErrorCache::ResetCurrentThreadError ()
  210. {
  211. DWORD threadId = GetCurrentThreadId ();
  212. EnterCriticalSection (&m_cs);
  213. ThreadError *pPtr = headPtr;
  214. // Find the current entry (if any)
  215. while (pPtr)
  216. {
  217. if (threadId == pPtr->dwThreadId)
  218. break;
  219. pPtr = pPtr->pNext;
  220. }
  221. if (pPtr)
  222. {
  223. // Unhook ThreadError prior to cleanup in case this is re-entered on the same thread
  224. // This can happen when in an STA since the message loop may be invoked by the COM calls below.
  225. if (pPtr == headPtr)
  226. headPtr = pPtr->pNext;
  227. if (pPtr->pNext)
  228. pPtr->pNext->pPrev = pPtr->pPrev;
  229. if (pPtr->pPrev)
  230. pPtr->pPrev->pNext = pPtr->pNext;
  231. // pPtr addresses the current entry for the thread
  232. if (pPtr->pErrorObject)
  233. {
  234. pPtr->pErrorObject->Release ();
  235. pPtr->pErrorObject = NULL;
  236. }
  237. if (pPtr->pService)
  238. {
  239. pPtr->pService->Release ();
  240. pPtr->pService = NULL;
  241. }
  242. NULLBSTR (pPtr->strNamespacePath);
  243. NULLBSTR (pPtr->strAuthority);
  244. NULLBSTR (pPtr->strPrincipal);
  245. FREECOAUTH (pPtr->pCoAuthIdentity)
  246. // Finally delete the ErrorInfo
  247. delete pPtr;
  248. }
  249. LeaveCriticalSection (&m_cs);
  250. }