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.

329 lines
9.6 KiB

  1. /*++
  2. Copyright (C) 1996-2001 Microsoft Corporation
  3. Module Name:
  4. WBEMQ.CPP
  5. Abstract:
  6. History:
  7. --*/
  8. #include "precomp.h"
  9. #include <stdio.h>
  10. #include <wbemcore.h>
  11. #include <genutils.h>
  12. CWbemRequest::CWbemRequest(IWbemContext* pContext, BOOL bInternallyIssued)
  13. {
  14. m_pContext = NULL;
  15. m_pCA = NULL;
  16. m_pCallSec = NULL;
  17. m_ulForceRun = 0;
  18. m_fOk = false;
  19. if(pContext == NULL)
  20. {
  21. // See if we can discern the context from the thread
  22. CWbemRequest* pPrev = CWbemQueue::GetCurrentRequest();
  23. if(pPrev)
  24. {
  25. pContext = pPrev->m_pContext;
  26. DEBUGTRACE((LOG_WBEMCORE, "Derived context %p from thread. Request was %p\n", pContext, pPrev));
  27. }
  28. }
  29. if(pContext)
  30. {
  31. // Create a derived context
  32. IWbemCausalityAccess* pParentCA;
  33. if (FAILED(pContext->QueryInterface(IID_IWbemCausalityAccess, (void**)&pParentCA))) return;
  34. CReleaseMe rm(pParentCA);
  35. if (FAILED(pParentCA->CreateChild(&m_pCA))) return;
  36. if(FAILED(m_pCA->QueryInterface(IID_IWbemContext, (void**)&m_pContext))) return;
  37. }
  38. else // Create a fresh context
  39. {
  40. m_pContext = ConfigMgr::GetNewContext();
  41. if (NULL == m_pContext) return;
  42. if (FAILED( m_pContext->QueryInterface(IID_IWbemCausalityAccess, (void**)&m_pCA))) return;
  43. m_lPriority = 0;
  44. }
  45. // Clone the call context.
  46. m_pCallSec = CWbemCallSecurity::CreateInst();
  47. if (m_pCallSec == 0)
  48. {
  49. return; // a CWbemRequest cannot be executed without CallSec
  50. }
  51. IServerSecurity *pSec = 0;
  52. HRESULT hRes = m_pCallSec->CloneThreadContext(bInternallyIssued);
  53. if(FAILED(hRes))
  54. {
  55. m_pCallSec->Release();
  56. m_pCallSec = NULL;
  57. return;
  58. }
  59. m_fOk = true;
  60. _DBG_ASSERT(m_pCallSec && m_pContext && m_pCA);
  61. }
  62. CWbemRequest::~CWbemRequest()
  63. {
  64. if (m_pContext) m_pContext->Release();
  65. if (m_pCA) m_pCA->Release();
  66. if (m_pCallSec) m_pCallSec->Release();
  67. }
  68. BOOL CWbemRequest::IsChildOf(CWbemRequest* pOther)
  69. {
  70. GUID guid = GUID_NULL;
  71. pOther->m_pCA->GetRequestId(&guid);
  72. return (m_pCA->IsChildOf(guid) == S_OK);
  73. }
  74. BOOL CWbemRequest::IsSpecial()
  75. {
  76. return (m_pCA->IsSpecial() == S_OK);
  77. }
  78. // Returns TRUE iff this request has otherts that depend on it.
  79. BOOL CWbemRequest::IsDependee()
  80. {
  81. if(m_pCA == NULL) return FALSE;
  82. // Check if the context has any "parents". Note: this test has
  83. // false-positives if the client uses a context object.
  84. // ============================================================
  85. long lNumParents, lNumSiblings;
  86. m_pCA->GetHistoryInfo(&lNumParents, &lNumSiblings);
  87. return (lNumParents > 0);
  88. }
  89. // Returns TRUE iff this request has otherts that depend on it.
  90. BOOL CWbemRequest::IsIssuedByProvider()
  91. {
  92. if (m_pCA == NULL) return FALSE;
  93. // Check if the context has any "parents". Note: this test has
  94. // false-positives if the client uses a context object.
  95. // ============================================================
  96. long lNumParents, lNumSiblings;
  97. m_pCA->GetHistoryInfo(&lNumParents, &lNumSiblings);
  98. return (lNumParents > 1);
  99. }
  100. BOOL CWbemRequest::IsAcceptableByParent()
  101. {
  102. return (!IsLongRunning() || !IsIssuedByProvider());
  103. }
  104. // Returns TRUE iff this request must have a thread created for it if one is
  105. // not available
  106. BOOL CWbemRequest::IsCritical()
  107. {
  108. return (IsDependee() && !IsAcceptableByParent());
  109. }
  110. BOOL CWbemRequest::IsChildOf(IWbemContext* pOther)
  111. {
  112. IWbemCausalityAccess* pOtherCA;
  113. if (FAILED(pOther->QueryInterface(IID_IWbemCausalityAccess, (void**)&pOtherCA)))
  114. return FALSE;
  115. GUID guid = GUID_NULL;
  116. pOtherCA->GetRequestId(&guid);
  117. pOtherCA->Release();
  118. return (m_pCA->IsChildOf(guid) == S_OK);
  119. }
  120. void CWbemRequest::GetHistoryInfo(long* plNumParents, long* plNumSiblings)
  121. {
  122. m_pCA->GetHistoryInfo(plNumParents, plNumSiblings);
  123. }
  124. CWbemQueue::CWbemQueue()
  125. {
  126. SetRequestLimits(2000, 1500, 1950);
  127. SetRequestPenalties(1, 1, 1);
  128. // thread limits are left to derived classes
  129. }
  130. BOOL CWbemQueue::IsSuitableThread(CThreadRecord* pRecord, CCoreExecReq* pReq)
  131. {
  132. CWbemRequest* pParentWbemReq = (CWbemRequest*)pRecord->m_pCurrentRequest;
  133. if(pParentWbemReq == NULL)
  134. {
  135. return TRUE;
  136. }
  137. CWbemRequest* pNewWbemReq = (CWbemRequest*)pReq;
  138. if(pNewWbemReq->IsChildOf(pParentWbemReq))
  139. {
  140. // This request is a child of the one this thread is processing.
  141. // We could use this thread, unless this is a long-running request and
  142. // this thread might be the one consuming the results. In that case,
  143. // we want to create another thread (to avoid the possibility of a
  144. // deadlock) and let this one continue.
  145. // ===================================================================
  146. return pNewWbemReq->IsAcceptableByParent();
  147. }
  148. else
  149. {
  150. return FALSE;
  151. }
  152. }
  153. CWbemRequest* CWbemQueue::GetCurrentRequest()
  154. {
  155. CThreadRecord* pRecord = (CThreadRecord*)TlsGetValue(GetTlsIndex());
  156. if(pRecord)
  157. {
  158. _DBG_ASSERT(0 == wcsncmp(pRecord->m_pQueue->GetType(), L"WBEMQ", 5))
  159. return (CWbemRequest*)pRecord->m_pCurrentRequest;
  160. }
  161. return NULL;
  162. }
  163. void CWbemQueue::AdjustInitialPriority(CCoreExecReq* pReq)
  164. {
  165. CWbemRequest* pRequest = (CWbemRequest*) pReq;
  166. if(pRequest->IsSpecial() || pRequest->IsCritical())
  167. {
  168. pRequest->SetPriority(PriorityCriticalRequests);
  169. }
  170. else
  171. {
  172. // Get information from the context
  173. // ================================
  174. long lNumParents, lNumSiblings; // SEC:REVIEWED 2002-03-22 : Init to zero
  175. pRequest->GetHistoryInfo(&lNumParents, &lNumSiblings);
  176. pRequest->SetPriority(lNumParents * m_lChildPenalty +
  177. lNumSiblings * m_lSiblingPenalty);
  178. }
  179. }
  180. void CWbemQueue::AdjustPriorityForPassing(CCoreExecReq* pReq)
  181. {
  182. pReq->SetPriority(pReq->GetPriority() - m_lPassingPenalty);
  183. }
  184. void CWbemQueue::SetRequestPenalties(long lChildPenalty, long lSiblingPenalty,
  185. long lPassingPenalty)
  186. {
  187. m_lChildPenalty = lChildPenalty;
  188. m_lSiblingPenalty = lSiblingPenalty;
  189. m_lPassingPenalty = lPassingPenalty;
  190. }
  191. //
  192. // exit conditions:
  193. // the CThreadRecord has a NULL request
  194. // the event in the request is set
  195. // the request is deleted
  196. //
  197. /////////////////////////////////////
  198. BOOL CWbemQueue::Execute(CThreadRecord* pRecord)
  199. {
  200. wmilib::auto_ptr<CWbemRequest> pReq( (CWbemRequest *) pRecord->m_pCurrentRequest);
  201. CAutoSignal SetMe(pReq->GetWhenDoneHandle());
  202. NullPointer NullMe((PVOID *)&pRecord->m_pCurrentRequest);
  203. IWbemCallSecurity* pServerSec = pReq->GetCallSecurity();
  204. if(NULL == pServerSec )
  205. {
  206. ERRORTRACE((LOG_WBEMCORE, "Failing request due to an error retrieving security settings\n"));
  207. return FALSE;
  208. }
  209. pServerSec->AddRef();
  210. CReleaseMe rmss( pServerSec );
  211. IUnknown *pOld = 0;
  212. // if the thread has OLE initialized, will NEVER fail
  213. if (FAILED(CoSwitchCallContext( pServerSec, &pOld )))
  214. {
  215. return FALSE;
  216. }
  217. // Save the old impersonation level
  218. BOOL bImpersonating = FALSE;
  219. IServerSecurity* pOldSec = NULL;
  220. if(pOld)
  221. {
  222. if(FAILED(pOld->QueryInterface(IID_IServerSecurity,(void**)&pOldSec))) return FALSE;
  223. bImpersonating = pOldSec->IsImpersonating();
  224. if (FAILED(pOldSec->RevertToSelf()))
  225. {
  226. pOldSec->Release();
  227. return FALSE;
  228. }
  229. }
  230. // dismiss the objects because the method on the base class will do the work
  231. SetMe.dismiss();
  232. pReq.release();
  233. BOOL bRes = CCoreQueue::Execute(pRecord);
  234. IUnknown *pNew = 0;
  235. // if the previous has succeded, this one will succed too
  236. CoSwitchCallContext(pOld, &pNew);
  237. // Restore the old impersonation level
  238. // ===================================
  239. if(pOldSec)
  240. {
  241. if(bImpersonating)
  242. {
  243. if (FAILED(pOldSec->ImpersonateClient()))
  244. {
  245. ERRORTRACE((LOG_WBEMCORE, "CWbemQueue::Execute() failed to reimpersonate client\n"));
  246. bRes = FALSE;
  247. }
  248. }
  249. pOldSec->Release();
  250. }
  251. return bRes;
  252. }
  253. BOOL CWbemQueue::DoesNeedNewThread(CCoreExecReq* pRequest, bool bIgnoreNumRequests )
  254. {
  255. // Check the base class
  256. if(CCoreQueue::DoesNeedNewThread(pRequest, bIgnoreNumRequests))
  257. return TRUE;
  258. if(pRequest)
  259. {
  260. // Check if the request is "special". Special requests are issued by
  261. // the sink proxy of an out-of-proc event provider. Such requests must
  262. // be processed at all costs, because their parent thread is stuck in
  263. // RPC. Additionally, check if this request is marked as "critical",
  264. // which would mean that its parent thread didn't take it.
  265. // ===================================================================
  266. CWbemRequest* pWbemRequest = (CWbemRequest*)pRequest;
  267. return (pWbemRequest->IsSpecial() || pWbemRequest->IsCritical());
  268. }
  269. else
  270. {
  271. return FALSE;
  272. }
  273. }