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.

389 lines
8.7 KiB

  1. //******************************************************************************
  2. //
  3. // EVTOOLS.CPP
  4. //
  5. // Copyright (C) 1996-1999 Microsoft Corporation
  6. //
  7. //******************************************************************************
  8. #include "precomp.h"
  9. #include <stdio.h>
  10. #include <wbemcomn.h>
  11. #include <evtools.h>
  12. #include <cominit.h>
  13. //*****************************************************************************
  14. //
  15. // Implementation:
  16. //
  17. // This class contains a queue of event handles. The top() one is always
  18. // signalled --- it corresponds to the turn that is currently allowed to
  19. // execute. Handles are added to the queue in GetInLine. Handles are removed
  20. // from the queue in EndTurn, at which time the next handle in line is
  21. // signalled.
  22. //
  23. // m_pCurrentTurn contains the pointer to the turn that has returned from from
  24. // WaitForTurn, but not from EndTurn. Note, that m_pCurrentTurn may be empty
  25. // even if a turn is scheduled to execute --- there is a gap between the time
  26. // when a turn's handle is signalled, and its WaitForTurn succeeds.
  27. //
  28. // However, it is guranteed that by the time a legitimate call to EndTurn is
  29. // made, m_pCurrentTurn contains the pointer to the turn in question, at which
  30. // time it is reset to NULL.
  31. //
  32. // An additional optimization is that if the same thread calls GetInLine
  33. // multiple times concurrently, we simply
  34. //
  35. //*****************************************************************************
  36. CExecLine::CExecLine() : m_pCurrentTurn(NULL), m_pLastIssuedTurn(NULL),
  37. m_dwLastIssuedTurnThreadId(0)
  38. {
  39. }
  40. CExecLine::~CExecLine()
  41. {
  42. // No need to do anything --- handles are closed by tokens
  43. // =======================================================
  44. }
  45. CExecLine::CTurn* CExecLine::GetInLine()
  46. {
  47. CInCritSec ics(&m_cs);
  48. //
  49. // First, check if this thread was the guy who got the last turn
  50. //
  51. if(m_pLastIssuedTurn && m_dwLastIssuedTurnThreadId == GetCurrentThreadId())
  52. {
  53. //
  54. // It is us --- just reuse that turn and be done with it
  55. //
  56. m_pLastIssuedTurn->AddRef();
  57. return m_pLastIssuedTurn;
  58. }
  59. //
  60. // Allocate a new turn
  61. //
  62. CTurn* pTurn = new CTurn;
  63. if(pTurn == NULL)
  64. return NULL;
  65. if(!pTurn->Init())
  66. {
  67. ERRORTRACE((LOG_ESS, "Unable to initialize turn: %d\n",
  68. GetLastError()));
  69. delete pTurn;
  70. return NULL;
  71. }
  72. //
  73. // Add its event to the queue
  74. //
  75. try
  76. {
  77. m_qTurns.push_back(pTurn);
  78. }
  79. catch( CX_MemoryException )
  80. {
  81. return NULL;
  82. }
  83. //
  84. // Check if we are currently executing
  85. //
  86. if(m_qTurns.size() == 1)
  87. {
  88. //
  89. // Release first in line
  90. //
  91. if(!ReleaseFirst())
  92. {
  93. //
  94. // Something went horribly wrong
  95. //
  96. ERRORTRACE((LOG_ESS, "Unable to release first turn: %d\n",
  97. GetLastError()));
  98. m_qTurns.pop_front();
  99. delete pTurn;
  100. return NULL;
  101. }
  102. }
  103. //
  104. // Mark ourselves as the last issued turn
  105. //
  106. m_pLastIssuedTurn = pTurn;
  107. m_dwLastIssuedTurnThreadId = GetCurrentThreadId();
  108. return pTurn;
  109. }
  110. // assumes in m_cs and m_qTurns is not empty
  111. BOOL CExecLine::ReleaseFirst()
  112. {
  113. return SetEvent(m_qTurns.front()->GetEvent());
  114. }
  115. DWORD CExecLine::WaitForTurn(CTurn* pTurn, DWORD dwTimeout)
  116. {
  117. // Wait for the turn event to be signaled
  118. // ======================================
  119. DWORD dwRes = WbemWaitForSingleObject(pTurn->GetEvent(), dwTimeout);
  120. {
  121. CInCritSec ics(&m_cs);
  122. if(dwRes == WAIT_OBJECT_0)
  123. {
  124. // Got it --- record this turn as executing
  125. // ========================================
  126. m_pCurrentTurn = pTurn;
  127. }
  128. }
  129. return dwRes;
  130. }
  131. BOOL CExecLine::EndTurn(CTurn* pTurn)
  132. {
  133. CInCritSec ics(&m_cs);
  134. // Check that this is the running turn
  135. // ===================================
  136. if(pTurn != m_pCurrentTurn)
  137. return FALSE;
  138. m_pCurrentTurn = NULL;
  139. // Delete the turn object
  140. // ======================
  141. if(pTurn->Release() > 0)
  142. {
  143. //
  144. // This is not the last incarnation of this turn. No further action is
  145. // required, as the same thread will call Wait and End again
  146. //
  147. return TRUE;
  148. }
  149. //
  150. // Remove the last issued turn if this is it
  151. //
  152. if(m_pLastIssuedTurn == pTurn)
  153. {
  154. m_pLastIssuedTurn = NULL;
  155. m_dwLastIssuedTurnThreadId = 0;
  156. }
  157. //
  158. // Pop its handle off the queue
  159. //
  160. m_qTurns.pop_front();
  161. //
  162. // Signal the next one
  163. //
  164. if(!m_qTurns.empty())
  165. return ReleaseFirst();
  166. else
  167. return TRUE;
  168. }
  169. BOOL CExecLine::DiscardTurn(ACQUIRE CTurn* pTurn)
  170. {
  171. CInCritSec ics(&m_cs);
  172. if(pTurn->Release() > 0)
  173. {
  174. //
  175. // This is not the last incarnation of this turn. No further action is
  176. // required
  177. //
  178. return TRUE;
  179. }
  180. else
  181. {
  182. // if pTurn is going away, we'd better make sure that we don't try to reuse it...
  183. // HMH 4/12/99, RAID 48420
  184. if (pTurn == m_pLastIssuedTurn)
  185. m_pLastIssuedTurn = NULL;
  186. }
  187. //
  188. // Search for it in the queue
  189. //
  190. BOOL bFound = FALSE;
  191. for(TTurnIterator it = m_qTurns.begin(); it != m_qTurns.end();)
  192. {
  193. if((*it) == pTurn)
  194. {
  195. //
  196. // erase it and continue
  197. //
  198. it = m_qTurns.erase(it);
  199. bFound = TRUE;
  200. break;
  201. }
  202. else
  203. it++;
  204. }
  205. if(!bFound)
  206. return FALSE;
  207. if(it == m_qTurns.begin() && it != m_qTurns.end())
  208. {
  209. //
  210. // Discarded turn was actually active --- signal the next one
  211. //
  212. ReleaseFirst();
  213. }
  214. return TRUE;
  215. }
  216. CExecLine::CTurn::CTurn() : m_hEvent(NULL), m_lRef(1)
  217. {
  218. }
  219. BOOL CExecLine::CTurn::Init()
  220. {
  221. m_dwOwningThreadId = GetCurrentThreadId();
  222. m_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  223. return (m_hEvent != NULL);
  224. }
  225. long CExecLine::CTurn::AddRef()
  226. {
  227. return InterlockedIncrement(&m_lRef);
  228. }
  229. long CExecLine::CTurn::Release()
  230. {
  231. long l = InterlockedDecrement(&m_lRef);
  232. if(l == 0)
  233. delete this;
  234. return l;
  235. }
  236. CExecLine::CTurn::~CTurn()
  237. {
  238. if(m_hEvent)
  239. CloseHandle(m_hEvent);
  240. }
  241. void* CExecLine::CTurn::operator new(size_t nSize)
  242. {
  243. return CTemporaryHeap::Alloc(nSize);
  244. }
  245. void CExecLine::CTurn::operator delete(void* p)
  246. {
  247. CTemporaryHeap::Free(p, sizeof(CExecLine::CTurn));
  248. }
  249. INTERNAL const SECURITY_DESCRIPTOR* GetSD( IWbemEvent* pEvent,ULONG* pcEvent )
  250. {
  251. static long mstatic_lSdHandle = -1;
  252. HRESULT hres;
  253. //
  254. // Get the SD from the event
  255. //
  256. _IWmiObject* pEventEx = NULL;
  257. pEvent->QueryInterface(IID__IWmiObject, (void**)&pEventEx);
  258. CReleaseMe rm1(pEventEx);
  259. if(mstatic_lSdHandle == -1)
  260. {
  261. pEventEx->GetPropertyHandleEx(SECURITY_DESCRIPTOR_PROPNAME, 0, NULL,
  262. &mstatic_lSdHandle);
  263. }
  264. const SECURITY_DESCRIPTOR* pSD = NULL;
  265. hres = pEventEx->GetArrayPropAddrByHandle(mstatic_lSdHandle, 0, pcEvent,
  266. (void**)&pSD);
  267. if(FAILED(hres) || pSD == NULL)
  268. return NULL;
  269. else
  270. return pSD;
  271. }
  272. HRESULT SetSD(IWbemEvent* pEvent, const SECURITY_DESCRIPTOR* pSD)
  273. {
  274. HRESULT hres;
  275. VARIANT vSd;
  276. VariantInit(&vSd);
  277. CClearMe cm1(&vSd);
  278. long lLength = GetSecurityDescriptorLength((SECURITY_DESCRIPTOR*)pSD);
  279. V_VT(&vSd) = VT_ARRAY | VT_UI1;
  280. SAFEARRAYBOUND sab;
  281. sab.cElements = lLength;
  282. sab.lLbound = 0;
  283. V_ARRAY(&vSd) = SafeArrayCreate(VT_UI1, 1, &sab);
  284. if(V_ARRAY(&vSd) == NULL)
  285. return WBEM_E_OUT_OF_MEMORY;
  286. BYTE* abSd = NULL;
  287. hres = SafeArrayAccessData(V_ARRAY(&vSd), (void**)&abSd);
  288. if(FAILED(hres))
  289. return WBEM_E_OUT_OF_MEMORY;
  290. CUnaccessMe uam(V_ARRAY(&vSd));
  291. memcpy(abSd, pSD, lLength);
  292. // Put it into the consumer
  293. // ========================
  294. hres = pEvent->Put(SECURITY_DESCRIPTOR_PROPNAME, 0, &vSd, 0);
  295. return hres;
  296. }
  297. CTempMemoryManager CTemporaryHeap::mstatic_Manager;
  298. /*
  299. CTemporaryHeap::CHeapHandle CTemporaryHeap::mstatic_HeapHandle;
  300. CTemporaryHeap::CHeapHandle::CHeapHandle()
  301. {
  302. m_hHeap = HeapCreate(0, 0, 0);
  303. }
  304. CTemporaryHeap::CHeapHandle::~CHeapHandle()
  305. {
  306. HeapDestroy(m_hHeap);
  307. }
  308. */