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.

1058 lines
31 KiB

  1. //***************************************************************************
  2. //
  3. // WMITASK.CPP
  4. //
  5. // raymcc 23-Apr-00 First oversimplified draft for Whistler
  6. // raymcc 18-Mar-02 Security review.
  7. //
  8. //***************************************************************************
  9. #include "precomp.h"
  10. #include <windows.h>
  11. #include <comdef.h>
  12. #include <stdio.h>
  13. #include <wbemcore.h>
  14. #include <wmiarbitrator.h>
  15. #include <wmifinalizer.h>
  16. #include <context.h>
  17. static ULONG g_uNextTaskId = 1;
  18. static LONG g_uTaskCount = 0;
  19. extern ULONG g_ulClientCallbackTimeout ;
  20. //***************************************************************************
  21. //
  22. //***************************************************************************
  23. CStaticCritSec CWmiTask::m_TaskCs;
  24. CWmiTask* CWmiTask::CreateTask ( )
  25. {
  26. try
  27. {
  28. return new CWmiTask(); //throws
  29. }
  30. catch( CX_Exception &)
  31. {
  32. return NULL;
  33. }
  34. }
  35. //***************************************************************************
  36. //
  37. //***************************************************************************
  38. CWmiTask::CWmiTask ( )
  39. {
  40. m_hResult = WBEM_E_CALL_CANCELLED ;
  41. m_uRefCount = 1;
  42. m_uTaskType = 0;
  43. m_uTaskStatus = 0;
  44. m_uStartTime = 0;
  45. m_uTaskId = InterlockedIncrement((LONG *) &g_uNextTaskId);
  46. m_pNs = 0;
  47. m_pAsyncClientSink = 0;
  48. m_pReqSink = 0;
  49. m_uMemoryUsage = 0;
  50. m_uTotalSleepTime = 0;
  51. m_uCancelState = FALSE;
  52. m_uLastSleepTime = 0;
  53. m_hTimer = NULL;
  54. m_pMainCtx = 0;
  55. m_hCompletion = NULL ;
  56. m_bAccountedForThrottling = FALSE ;
  57. m_bCancelledDueToThrottling = FALSE ;
  58. m_pReqDoNotUse = NULL;
  59. m_pReqCancelNotSink = NULL;
  60. m_pStatusSink = new CStatusSink;
  61. if (NULL == m_pStatusSink) throw CX_MemoryException();
  62. InterlockedIncrement((LONG *)&g_uTaskCount);
  63. }
  64. //***************************************************************************
  65. //
  66. // CWmiTask::~CWmiTask
  67. //
  68. //***************************************************************************
  69. //
  70. CWmiTask::~CWmiTask()
  71. {
  72. if (m_pNs) m_pNs->Release ( ) ;
  73. if (m_pAsyncClientSink) m_pAsyncClientSink->Release ( ) ;
  74. if (m_pReqSink) m_pReqSink->Release ( ) ;
  75. if (m_pMainCtx) m_pMainCtx->Release ( ) ;
  76. CCheckedInCritSec _cs ( &m_csTask );
  77. // Release all provider/sink bindings.
  78. for (int i = 0; i < m_aTaskProviders.Size(); i++)
  79. {
  80. STaskProvider *pTP = (STaskProvider *) m_aTaskProviders[i];
  81. delete pTP;
  82. }
  83. // Release all Arbitratees
  84. ReleaseArbitratees ( ) ;
  85. if ( m_hTimer ) CloseHandle ( m_hTimer );
  86. if (m_hCompletion) CloseHandle ( m_hCompletion ) ;
  87. if (m_pStatusSink) m_pStatusSink->Release();
  88. delete m_pReqCancelNotSink;
  89. InterlockedDecrement((LONG *)&g_uTaskCount);
  90. }
  91. /*
  92. * =============================================================================
  93. |
  94. | HRESULT CWmiTask::SignalCancellation ( )
  95. | ----------------------------------------
  96. |
  97. | Signals the task to be cancelled
  98. |
  99. |
  100. * =============================================================================
  101. */
  102. HRESULT CWmiTask::SignalCancellation ( )
  103. {
  104. CInCritSec _cs ( &m_csTask ); // SEC:REVIEWED 2002-03-22 : Assumes entry
  105. if ( ( m_uTaskStatus != WMICORE_TASK_STATUS_CANCELLED ) && ( m_hTimer != NULL ) )
  106. {
  107. SetEvent ( m_hTimer ) ; // SEC:REVIEWED 2002-03-22 : Needs err check
  108. }
  109. return WBEM_S_NO_ERROR;
  110. }
  111. /*
  112. * =============================================================================
  113. |
  114. | HRESULT CWmiTask::SetTaskResult ( HRESULT hRes )
  115. | -------------------------------------------------
  116. |
  117. | Sets the task result
  118. |
  119. |
  120. * =============================================================================
  121. */
  122. HRESULT CWmiTask::SetTaskResult ( HRESULT hResult )
  123. {
  124. m_hResult = hResult ;
  125. return WBEM_S_NO_ERROR;
  126. }
  127. /*
  128. * =============================================================================
  129. |
  130. | HRESULT CWmiTask::UpdateMemoryUsage ( LONG lDelta )
  131. | ---------------------------------------------------
  132. |
  133. | Updates the task memory usage
  134. |
  135. |
  136. * =============================================================================
  137. */
  138. HRESULT CWmiTask::UpdateMemoryUsage ( LONG lDelta )
  139. {
  140. CInCritSec _cs ( &m_csTask ); // SEC:REVIEWED 2002-03-22 : Assumes entry
  141. m_uMemoryUsage += lDelta ;
  142. return WBEM_S_NO_ERROR;
  143. }
  144. /*
  145. * =============================================================================
  146. |
  147. | HRESULT CWmiTask::UpdateTotalSleepTime ( ULONG uSleepTime )
  148. | -----------------------------------------------------------
  149. |
  150. | Updates the tasks sleep time
  151. |
  152. |
  153. * =============================================================================
  154. */
  155. HRESULT CWmiTask::UpdateTotalSleepTime ( ULONG uSleepTime )
  156. {
  157. CInCritSec _cs ( &m_csTask ); // SEC:REVIEWED 2002-03-22 : Assumes entry
  158. m_uTotalSleepTime += uSleepTime ;
  159. return WBEM_S_NO_ERROR;
  160. }
  161. /*
  162. * =============================================================================
  163. |
  164. | HRESULT CWmiTask::ReleaseArbitratees ( )
  165. | ----------------------------------------
  166. |
  167. | Releases all the arbitratees (Finalizer, Merger currently)
  168. |
  169. |
  170. |
  171. |
  172. |
  173. * =============================================================================
  174. */
  175. HRESULT CWmiTask::ReleaseArbitratees ( BOOL bIsShutdown)
  176. {
  177. HRESULT hRes = WBEM_S_NO_ERROR ;
  178. CInCritSec _cs ( &m_csTask ); // SEC:REVIEWED 2002-03-22 : Assumes entry
  179. for (ULONG i = 0; i < m_aArbitratees.Size(); i++)
  180. {
  181. BOOL bLastNeeded = TRUE;
  182. _IWmiArbitratee *pArbee = NULL ;
  183. pArbee = (_IWmiArbitratee*) m_aArbitratees[i];
  184. if ( pArbee )
  185. {
  186. if (bIsShutdown)
  187. {
  188. IWbemShutdown * pShutdown = NULL;
  189. if (SUCCEEDED(pArbee->QueryInterface(IID_IWbemShutdown,(void **)&pShutdown)))
  190. {
  191. pShutdown->Shutdown(0,0,NULL);
  192. long lRet = pShutdown->Release();
  193. //
  194. // Please understand the code in CWmiFinalizer::ShutDown for this trick
  195. //
  196. if (0 == lRet) bLastNeeded = FALSE;
  197. }
  198. }
  199. if (bLastNeeded)
  200. pArbee->Release();
  201. }
  202. }
  203. m_aArbitratees.Empty();
  204. return hRes ;
  205. }
  206. //***************************************************************************
  207. //
  208. //***************************************************************************
  209. HRESULT CWmiTask::SetRequestSink(CStdSink *pReqSink)
  210. {
  211. if (pReqSink == 0)
  212. return WBEM_E_INVALID_PARAMETER;
  213. if (m_pReqSink != 0)
  214. return WBEM_E_INVALID_OPERATION;
  215. CInCritSec _cs ( &m_csTask ); // SEC:REVIEWED 2002-03-22 : Assumes entry
  216. pReqSink->AddRef ( ) ;
  217. m_pReqSink = pReqSink;
  218. return WBEM_S_NO_ERROR;
  219. }
  220. //***************************************************************************
  221. //
  222. //***************************************************************************
  223. // *
  224. ULONG CWmiTask::AddRef()
  225. {
  226. InterlockedIncrement((LONG *) &m_uRefCount);
  227. return m_uRefCount;
  228. }
  229. //***************************************************************************
  230. //
  231. //***************************************************************************
  232. // *
  233. ULONG CWmiTask::Release()
  234. {
  235. ULONG uNewCount = InterlockedDecrement((LONG *) &m_uRefCount);
  236. if (0 != uNewCount)
  237. return uNewCount;
  238. delete this;
  239. return 0;
  240. }
  241. //***************************************************************************
  242. //
  243. //***************************************************************************
  244. // *
  245. HRESULT CWmiTask::QueryInterface(
  246. IN REFIID riid,
  247. OUT LPVOID *ppvObj
  248. )
  249. {
  250. if (NULL == ppvObj) return E_POINTER;
  251. if (IID_IUnknown==riid || IID__IWmiCoreHandle==riid)
  252. {
  253. *ppvObj = (_IWmiCoreHandle *)this;
  254. AddRef();
  255. return S_OK;
  256. }
  257. else
  258. {
  259. *ppvObj = 0;
  260. return E_NOINTERFACE;
  261. }
  262. }
  263. //***************************************************************************
  264. //
  265. //***************************************************************************
  266. // *
  267. HRESULT CWmiTask::GetHandleType(
  268. ULONG *puType
  269. )
  270. {
  271. *puType = WMI_HANDLE_TASK;
  272. return WBEM_S_NO_ERROR;
  273. }
  274. //***************************************************************************
  275. //
  276. //***************************************************************************
  277. // *
  278. HRESULT CWmiTask::Initialize(
  279. IN CWbemNamespace *pNs,
  280. IN ULONG uTaskType,
  281. IN IWbemContext *pCtx,
  282. IN IWbemObjectSink *pAsyncClientSinkCopy,
  283. IN CAsyncReq *pReq
  284. )
  285. {
  286. HRESULT hRes;
  287. if (pNs == 0 || pCtx == 0)
  288. return WBEM_E_INVALID_PARAMETER;
  289. m_hCompletion = CreateEvent(NULL,TRUE,FALSE,NULL);
  290. if (NULL == m_hCompletion) return WBEM_E_OUT_OF_MEMORY;
  291. //
  292. // this is just a pointer copy for the debugger
  293. // it MAY point to the request that originated us, or it MAY not
  294. // the lifetime of the request is generally less than the lifetime of the CWmiTask
  295. //
  296. m_pReqDoNotUse = pReq;
  297. m_pNs = pNs;
  298. m_pNs->AddRef();
  299. m_uTaskType = uTaskType;
  300. if (CORE_TASK_TYPE(m_uTaskType) == WMICORE_TASK_EXEC_NOTIFICATION_QUERY)
  301. {
  302. wmilib::auto_ptr<CAsyncReq_RemoveNotifySink> pReq( new CAsyncReq_RemoveNotifySink(m_pReqSink, NULL));
  303. if (NULL == pReq.get() || NULL == pReq->GetContext())
  304. {
  305. return WBEM_E_OUT_OF_MEMORY;
  306. }
  307. m_pReqCancelNotSink = pReq.release();
  308. }
  309. m_uStartTime = GetCurrentTime();
  310. // See if the task is primary or not.
  311. // ==================================
  312. if (pCtx)
  313. {
  314. CWbemContext *pContext = (CWbemContext *) pCtx;
  315. GUID ParentId = GUID_NULL;
  316. pContext->GetParentId(&ParentId);
  317. if (ParentId != GUID_NULL)
  318. {
  319. m_uTaskType |= WMICORE_TASK_TYPE_DEPENDENT;
  320. }
  321. else
  322. m_uTaskType |= WMICORE_TASK_TYPE_PRIMARY;
  323. m_pMainCtx = (CWbemContext *) pCtx;
  324. m_pMainCtx->AddRef();
  325. }
  326. else
  327. {
  328. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  329. // If we dont have a context check to see if the namespace is an ESS or Provider
  330. // initialized namespace, if so, set the task type to dependent.
  331. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  332. if ( pNs->GetIsESS ( ) || pNs->GetIsProvider ( ) )
  333. {
  334. m_uTaskType |= WMICORE_TASK_TYPE_DEPENDENT;
  335. }
  336. else
  337. {
  338. m_uTaskType |= WMICORE_TASK_TYPE_PRIMARY;
  339. }
  340. }
  341. if ((uTaskType & WMICORE_TASK_TYPE_ASYNC) && pAsyncClientSinkCopy)
  342. {
  343. m_pAsyncClientSink = pAsyncClientSinkCopy;
  344. m_pAsyncClientSink->AddRef();
  345. }
  346. else
  347. m_pAsyncClientSink = 0;
  348. // Register this task with Arbitrator.
  349. // ====================================
  350. _IWmiArbitrator *pArb = CWmiArbitrator::GetUnrefedArbitrator();
  351. if (!pArb)
  352. return WBEM_E_CRITICAL_ERROR;
  353. hRes = pArb->RegisterTask(this);
  354. if (FAILED(hRes))
  355. return hRes;
  356. return WBEM_S_NO_ERROR;
  357. }
  358. //***************************************************************************
  359. //
  360. //***************************************************************************
  361. //
  362. /*
  363. HRESULT CWmiTask::SetFinalizer(_IWmiFinalizer *pFnz)
  364. {
  365. if (pFnz == 0)
  366. return WBEM_E_INVALID_PARAMETER;
  367. if (m_pWorkingFnz)
  368. return WBEM_E_INVALID_OPERATION;
  369. m_pWorkingFnz = pFnz;
  370. m_pWorkingFnz->AddRef();
  371. return WBEM_S_NO_ERROR;
  372. }
  373. */
  374. //***************************************************************************
  375. //
  376. //***************************************************************************
  377. //
  378. HRESULT CWmiTask::GetFinalizer(_IWmiFinalizer **ppFnz)
  379. {
  380. CInCritSec ics( &m_csTask ); // SEC:REVIEWED 2002-03-22 : Assumes entry
  381. for ( int x = 0; x < m_aArbitratees.Size(); x++ )
  382. {
  383. _IWmiArbitratee* pArbitratee = (_IWmiArbitratee*) m_aArbitratees[x];
  384. if (pArbitratee && SUCCEEDED( pArbitratee->QueryInterface( IID__IWmiFinalizer, (void**) ppFnz ) ) )
  385. {
  386. break;
  387. }
  388. }
  389. return ( x < m_aArbitratees.Size() ? WBEM_S_NO_ERROR : WBEM_E_NOT_FOUND );
  390. }
  391. //***************************************************************************
  392. //
  393. //***************************************************************************
  394. //
  395. HRESULT CWmiTask::AddArbitratee( ULONG uFlags, _IWmiArbitratee* pArbitratee )
  396. {
  397. HRESULT hRes = WBEM_S_NO_ERROR;
  398. if (pArbitratee == 0)
  399. return WBEM_E_INVALID_PARAMETER;
  400. CInCritSec _cs ( &m_csTask );
  401. if (m_uTaskStatus == WMICORE_TASK_STATUS_CANCELLED) return WBEM_S_NO_ERROR;
  402. if (CFlexArray::no_error != m_aArbitrateesStorage.InsertAt(m_aArbitratees.Size(),NULL)) return WBEM_E_OUT_OF_MEMORY;
  403. if (CFlexArray::no_error != m_aArbitratees.Add (pArbitratee)) return WBEM_E_OUT_OF_MEMORY;
  404. pArbitratee->AddRef();
  405. return hRes;
  406. }
  407. //***************************************************************************
  408. //
  409. //***************************************************************************
  410. //
  411. HRESULT CWmiTask::RemoveArbitratee( ULONG uFlags, _IWmiArbitratee* pArbitratee )
  412. {
  413. HRESULT hRes = WBEM_E_FAILED;
  414. if (pArbitratee == 0)
  415. return WBEM_E_INVALID_PARAMETER;
  416. CInCritSec _cs ( &m_csTask ); // SEC:REVIEWED 2002-03-22 : assumes entry
  417. for (int i = 0; i < m_aArbitratees.Size(); i++)
  418. {
  419. _IWmiArbitratee *pArbee = (_IWmiArbitratee*) m_aArbitratees[i];
  420. if (pArbee == pArbitratee)
  421. {
  422. m_aArbitratees[i] = 0;
  423. pArbee->Release();
  424. hRes = WBEM_S_NO_ERROR;
  425. break;
  426. }
  427. }
  428. return hRes;
  429. }
  430. //***************************************************************************
  431. //
  432. //***************************************************************************
  433. //
  434. HRESULT CWmiTask::GetArbitratedQuery( ULONG uFlags, _IWmiArbitratedQuery** ppArbitratedQuery )
  435. {
  436. HRESULT hRes = E_NOINTERFACE;
  437. if (ppArbitratedQuery == 0)
  438. return WBEM_E_INVALID_PARAMETER;
  439. {
  440. CInCritSec _cs ( &m_csTask ); //#SEC:Assumes entry
  441. for ( int x = 0; FAILED( hRes ) && x < m_aArbitratees.Size(); x++ )
  442. {
  443. _IWmiArbitratee* pArb = (_IWmiArbitratee*) m_aArbitratees[x];
  444. if (pArb)
  445. {
  446. hRes = pArb->QueryInterface( IID__IWmiArbitratedQuery, (void**) ppArbitratedQuery );
  447. }
  448. }
  449. }
  450. return hRes;
  451. }
  452. //***************************************************************************
  453. //
  454. //***************************************************************************
  455. HRESULT CWmiTask::GetPrimaryTask ( _IWmiCoreHandle** pPTask )
  456. {
  457. if ( pPTask == NULL ) return WBEM_E_INVALID_PARAMETER;
  458. *pPTask = (_IWmiCoreHandle*) this;
  459. return WBEM_S_NO_ERROR;
  460. }
  461. //***************************************************************************
  462. //
  463. //***************************************************************************
  464. //
  465. HRESULT CWmiTask::Cancel( HRESULT hResParam )
  466. {
  467. {
  468. CCheckedInCritSec _cs(&m_csTask);
  469. if (m_uTaskStatus == WMICORE_TASK_STATUS_CANCELLED)
  470. {
  471. return WBEM_S_NO_ERROR; // Prevent reentrancy
  472. }
  473. m_uTaskStatus = WMICORE_TASK_STATUS_CANCELLED;
  474. }
  475. BOOL bCancelledViaEss = FALSE ;
  476. OnDeleteObj<BOOL,
  477. CWmiTask,
  478. HRESULT(CWmiTask::*)(BOOL),
  479. &CWmiTask::ReleaseArbitratees> RelArbitratees(this,WBEM_E_SHUTTING_DOWN == hResParam);
  480. // We'll want one of these in order to track statuses from all plausible locations if
  481. // we are performing a client originated cancel
  482. CStatusSink* pStatusSink = NULL;
  483. if (hResParam == WMIARB_CALL_CANCELLED_CLIENT)
  484. {
  485. //
  486. // transfer ownership of the StatusSink to the stack
  487. // initial refcount is 1, so we are OK
  488. //
  489. pStatusSink = m_pStatusSink;
  490. m_pStatusSink = NULL;
  491. }
  492. // Auto Release
  493. CReleaseMe rmStatusSink( pStatusSink );
  494. // Change this to an async scheduled request
  495. // ==========================================
  496. if (CORE_TASK_TYPE(m_uTaskType) == WMICORE_TASK_EXEC_NOTIFICATION_QUERY)
  497. {
  498. wmilib::auto_ptr<CAsyncReq_RemoveNotifySink> pReq(m_pReqCancelNotSink);
  499. m_pReqCancelNotSink = NULL; // transfer ownership
  500. pReq->SetSink(m_pReqSink);
  501. pReq->SetStatusSink(pStatusSink);
  502. // If we have a status sink, then we should wait until the operation
  503. // completes before continuing so we can get the proper status from the
  504. // sink.
  505. HRESULT hResInner;
  506. if (pStatusSink) // cancelled by the originating client
  507. {
  508. hResInner = ConfigMgr::EnqueueRequestAndWait(pReq.get());
  509. }
  510. else
  511. {
  512. hResInner = ConfigMgr::EnqueueRequest(pReq.get());
  513. }
  514. if (FAILED(hResInner)) return hResInner;
  515. pReq.release();
  516. bCancelledViaEss = TRUE ;
  517. }
  518. // If here, a normal task. Loop through any providers and stop them.
  519. // ==================================================================
  520. int SizeIter = 0;
  521. // This could change while we're accessing, so do this in a critsec
  522. {
  523. CInCritSec ics( &m_csTask );
  524. _DBG_ASSERT(m_aTaskProvStorage.Size() >= m_aTaskProviders.Size());
  525. SizeIter = m_aTaskProviders.Size();
  526. for (int i = 0; i < SizeIter; i++)
  527. m_aTaskProvStorage[i] = m_aTaskProviders[i];
  528. }
  529. // Cancel what we've got
  530. // there cannot be 2 threads using m_aTaskProvStorage in the cancel call
  531. // m_uTaskStatus guards this code and the Add code
  532. for (int i = 0; i < SizeIter; i++)
  533. {
  534. STaskProvider *pTP = (STaskProvider *) m_aTaskProvStorage[i];
  535. if (pTP) pTP->Cancel(pStatusSink);
  536. }
  537. CStdSink* pTempSink = NULL;
  538. {
  539. CInCritSec _cs ( &m_csTask );
  540. if (m_pReqSink)
  541. {
  542. pTempSink = m_pReqSink;
  543. m_pReqSink = 0;
  544. }
  545. }
  546. if ( pTempSink )
  547. {
  548. pTempSink->Cancel();
  549. pTempSink->Release();
  550. }
  551. _DBG_ASSERT(m_hCompletion);
  552. //
  553. // Loop through all arbitratees and set the operation result to cancelled
  554. //
  555. HRESULT hRes = WBEM_S_NO_ERROR;
  556. if (!bCancelledViaEss)
  557. {
  558. _IWmiFinalizer* pFinalizer = NULL ;
  559. if ( hResParam == WMIARB_CALL_CANCELLED_CLIENT )
  560. {
  561. //
  562. // We need the finalizer to set the client wakeup event
  563. //
  564. hRes = GetFinalizer ( &pFinalizer ) ;
  565. if ( FAILED (hRes) )
  566. {
  567. hRes = WBEM_E_FAILED ;
  568. }
  569. else
  570. {
  571. ((CWmiFinalizer*)pFinalizer)->SetClientCancellationHandle ( m_hCompletion ) ;
  572. }
  573. }
  574. CReleaseMe FinalizerRelease(pFinalizer);
  575. //
  576. // only enter wait state if we successfully created and set the client wait event
  577. //
  578. if (SUCCEEDED(hRes))
  579. {
  580. if ( hResParam == WMIARB_CALL_CANCELLED_CLIENT ||
  581. hResParam == WMIARB_CALL_CANCELLED_THROTTLING )
  582. {
  583. SetArbitrateesOperationResult(0,WBEM_E_CALL_CANCELLED_CLIENT);
  584. }
  585. else
  586. {
  587. SetArbitrateesOperationResult(0,m_hResult);
  588. }
  589. if (hResParam == WMIARB_CALL_CANCELLED_CLIENT )
  590. {
  591. if (((CWmiFinalizer*)pFinalizer)->IsValidDestinationSink())
  592. {
  593. DWORD dwRet = CCoreQueue::QueueWaitForSingleObject(m_hCompletion,g_ulClientCallbackTimeout);
  594. if (dwRet == WAIT_TIMEOUT)
  595. {
  596. hRes = WBEM_S_TIMEDOUT;
  597. }
  598. }
  599. ((CWmiFinalizer*)pFinalizer)->CancelWaitHandle();
  600. if (m_hCompletion)
  601. {
  602. CloseHandle(m_hCompletion);
  603. m_hCompletion = NULL ;
  604. }
  605. }
  606. }
  607. }
  608. //
  609. // We're done, get the final status from the status sink if we have one.
  610. //
  611. if ( NULL != pStatusSink )
  612. {
  613. hRes = pStatusSink->GetLastStatus();
  614. }
  615. return hRes ;
  616. }
  617. //***************************************************************************
  618. //
  619. //***************************************************************************
  620. //
  621. BOOL CWmiTask::IsESSNamespace ( )
  622. {
  623. if (m_pNs)
  624. return m_pNs->GetIsESS ( );
  625. return false;
  626. }
  627. //***************************************************************************
  628. //
  629. //***************************************************************************
  630. //
  631. BOOL CWmiTask::IsProviderNamespace ( )
  632. {
  633. BOOL bRet = FALSE;
  634. if ( m_pNs )
  635. {
  636. bRet = m_pNs->GetIsProvider ( );
  637. }
  638. return bRet;
  639. }
  640. //***************************************************************************
  641. //
  642. //***************************************************************************
  643. //
  644. HRESULT CWmiTask::AddTaskProv(STaskProvider *p)
  645. {
  646. CInCritSec ics( &m_csTask ); // SEC:REVIEWED 2002-03-22 : assumes entry
  647. // There is a race condition in which the task could get cancelled just as we
  648. // are executing. In this case, the task status will indicate that it has been
  649. // cancelled, so we should not add it to the task providers list.
  650. if (m_uTaskStatus == WMICORE_TASK_STATUS_CANCELLED)
  651. return WBEM_E_CALL_CANCELLED; // Prevent reentrancy
  652. if (CFlexArray::no_error != m_aTaskProvStorage.InsertAt(m_aTaskProviders.Size()+1,NULL)) return WBEM_E_OUT_OF_MEMORY;
  653. if (CFlexArray::no_error != m_aTaskProviders.Add(p)) return WBEM_E_OUT_OF_MEMORY;
  654. return WBEM_S_NO_ERROR;
  655. }
  656. //***************************************************************************
  657. //
  658. //***************************************************************************
  659. //
  660. HRESULT CWmiTask::HasMatchingSink(void *Test, IN REFIID riid)
  661. {
  662. if (LPVOID(m_pAsyncClientSink) == LPVOID(Test))
  663. return WBEM_S_NO_ERROR;
  664. return WBEM_E_NOT_FOUND;
  665. }
  666. //***************************************************************************
  667. //
  668. //***************************************************************************
  669. //
  670. HRESULT CWmiTask::CreateTimerEvent ( )
  671. {
  672. HRESULT hRes = WBEM_S_NO_ERROR;
  673. CCheckedInCritSec _cs ( &m_csTask ); // SEC:REVIEWED 2002-03-22 : assumes entry
  674. if ( !m_hTimer )
  675. {
  676. m_hTimer = CreateEvent ( NULL, TRUE, FALSE, NULL ); // SEC:REVIEWED 2002-03-22 : ok, unnamed
  677. if ( !m_hTimer )
  678. {
  679. hRes = WBEM_E_OUT_OF_MEMORY;
  680. }
  681. }
  682. return hRes;
  683. }
  684. //***************************************************************************
  685. //
  686. //***************************************************************************
  687. HRESULT CWmiTask::SetArbitrateesOperationResult ( ULONG lFlags, HRESULT hResult )
  688. {
  689. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  690. // Set the operation result of all Arbitratees
  691. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  692. int Index = 0;
  693. //
  694. // this function is only called by the Cancel call
  695. // We knwon that the Cance call is called only ONCE
  696. // and the code for adding to the array uses the same guard of the Cancel() method
  697. //
  698. {
  699. CInCritSec _cs ( &m_csTask );
  700. _DBG_ASSERT(m_aArbitrateesStorage.Size() >= m_aArbitratees.Size());
  701. for (int i = 0; i < m_aArbitratees.Size(); i++)
  702. {
  703. _IWmiArbitratee *pArbee = (_IWmiArbitratee*) m_aArbitratees[i];
  704. if ( pArbee )
  705. {
  706. m_aArbitrateesStorage[Index++] = pArbee;
  707. pArbee->AddRef();
  708. }
  709. }
  710. }
  711. for (int i = 0; i < Index; i++)
  712. {
  713. _IWmiArbitratee *pArbee = (_IWmiArbitratee*) m_aArbitrateesStorage[i];
  714. pArbee->SetOperationResult(lFlags, hResult );
  715. pArbee->Release();
  716. m_aArbitrateesStorage[i] = NULL;
  717. }
  718. return WBEM_S_NO_ERROR;
  719. }
  720. //***************************************************************************
  721. //
  722. //***************************************************************************
  723. //
  724. HRESULT CWmiTask::Dump(FILE* f)
  725. {
  726. fprintf(f, "---Task = 0x%p----------------------------\n", this); // SEC:REVIEWED 2002-03-22 : OK
  727. fprintf(f, " Refcount = %d\n", m_uRefCount); // SEC:REVIEWED 2002-03-22 : OK
  728. fprintf(f, " TaskStatus = %u\n ", m_uTaskStatus); // SEC:REVIEWED 2002-03-22 : OK
  729. fprintf(f, " Task ID = %u\n", m_uTaskId); // SEC:REVIEWED 2002-03-22 : OK
  730. // Task status
  731. char *p = "<none>";
  732. switch(m_uTaskStatus)
  733. {
  734. case WMICORE_TASK_STATUS_NEW: p = "WMICORE_TASK_STATUS_NEW"; break;
  735. case WMICORE_TASK_STATUS_CANCELLED: p = "WMICORE_TASK_STATUS_CANCELLED"; break;
  736. };
  737. fprintf(f, " %s\n", p); // SEC:REVIEWED 2002-03-22 : OK
  738. // Task type
  739. p = "<none>";
  740. switch(m_uTaskType & 0xFF)
  741. {
  742. case WMICORE_TASK_NULL: p = "WMICORE_TASK_NULL"; break;
  743. case WMICORE_TASK_GET_OBJECT: p = "WMICORE_TASK_GET_OBJECT"; break;
  744. case WMICORE_TASK_GET_INSTANCE: p = "WMICORE_TASK_GET_INSTANCE"; break;
  745. case WMICORE_TASK_PUT_INSTANCE: p = "WMICORE_TASK_PUT_INSTANCE"; break;
  746. case WMICORE_TASK_DELETE_INSTANCE: p = "WMICORE_TASK_DELETE_INSTANCE"; break;
  747. case WMICORE_TASK_ENUM_INSTANCES: p = "WMICORE_TASK_ENUM_INSTANCES"; break;
  748. case WMICORE_TASK_GET_CLASS: p = "WMICORE_TASK_GET_CLASS"; break;
  749. case WMICORE_TASK_PUT_CLASS: p = "WMICORE_TASK_PUT_CLASS"; break;
  750. case WMICORE_TASK_DELETE_CLASS: p = "WMICORE_TASK_DELETE_CLASS"; break;
  751. case WMICORE_TASK_ENUM_CLASSES: p = "WMICORE_TASK_ENUM_CLASSES"; break;
  752. case WMICORE_TASK_EXEC_QUERY: p = "WMICORE_TASK_EXEC_QUERY"; break;
  753. case WMICORE_TASK_EXEC_METHOD: p = "WMICORE_TASK_EXEC_METHOD"; break;
  754. case WMICORE_TASK_OPEN: p = "WMICORE_TASK_OPEN"; break;
  755. case WMICORE_TASK_OPEN_SCOPE: p = "WMICORE_TASK_OPEN_SCOPE"; break;
  756. case WMICORE_TASK_OPEN_NAMESPACE: p = "WMICORE_TASK_OPEN_NAMESPACE"; break;
  757. case WMICORE_TASK_EXEC_NOTIFICATION_QUERY: p = "WMICORE_TASK_EXEC_NOTIFICATION_QUERY"; break;
  758. }
  759. fprintf(f, " TaskType = [0x%X] %s ", m_uTaskType, p); // SEC:REVIEWED 2002-03-22 : OK
  760. if (m_uTaskType & WMICORE_TASK_TYPE_SYNC)
  761. fprintf(f, " WMICORE_TASK_TYPE_SYNC"); // SEC:REVIEWED 2002-03-22 : OK
  762. if (m_uTaskType & WMICORE_TASK_TYPE_SEMISYNC)
  763. fprintf(f, " WMICORE_TASK_TYPE_SEMISYNC"); // SEC:REVIEWED 2002-03-22 : OK
  764. if (m_uTaskType & WMICORE_TASK_TYPE_ASYNC)
  765. fprintf(f, " WMICORE_TASK_TYPE_ASYNC"); // SEC:REVIEWED 2002-03-22 : OK
  766. if (m_uTaskType & WMICORE_TASK_TYPE_PRIMARY)
  767. fprintf(f, " WMICORE_TASK_TYPE_PRIMARY"); // SEC:REVIEWED 2002-03-22 : OK
  768. if (m_uTaskType & WMICORE_TASK_TYPE_DEPENDENT)
  769. fprintf(f, " WMICORE_TASK_TYPE_DEPENDENT"); // SEC:REVIEWED 2002-03-22 : OK
  770. fprintf(f, "\n"); // SEC:REVIEWED 2002-03-22 : OK
  771. fprintf(f, " AsyncClientSink = 0x%p\n", m_pAsyncClientSink); // SEC:REVIEWED 2002-03-22 : OK
  772. CCheckedInCritSec ics( &m_csTask ); // SEC:REVIEWED 2002-03-22 : Assumes entry
  773. for (int i = 0; i < m_aTaskProviders.Size(); i++)
  774. {
  775. STaskProvider *pTP = (STaskProvider *) m_aTaskProviders[i];
  776. fprintf(f, " Task Provider [0x%p] Prov=0x%p Sink=0x%p\n", this, pTP->m_pProv, pTP->m_pProvSink); // SEC:REVIEWED 2002-03-22 : OK
  777. }
  778. ics.Leave();
  779. DWORD dwAge = GetCurrentTime() - m_uStartTime;
  780. fprintf(f, " CWbemNamespace = 0x%p\n", m_pNs); // SEC:REVIEWED 2002-03-22 : OK
  781. fprintf(f, " Task age = %d milliseconds\n", dwAge); // SEC:REVIEWED 2002-03-22 : OK
  782. fprintf(f, " Task last sleep time = %d ms\n", m_uLastSleepTime ); // SEC:REVIEWED 2002-03-22 : OK
  783. fprintf(f, "\n"); // SEC:REVIEWED 2002-03-22 : OK
  784. return 0;
  785. }
  786. //***************************************************************************
  787. //
  788. //***************************************************************************
  789. //
  790. STaskProvider::~STaskProvider()
  791. {
  792. if (m_pProvSink)
  793. m_pProvSink->LocalRelease();
  794. ReleaseIfNotNULL(m_pProv);
  795. }
  796. //***************************************************************************
  797. //
  798. //***************************************************************************
  799. //
  800. HRESULT STaskProvider::Cancel( CStatusSink* pStatusSink )
  801. {
  802. HRESULT hRes = WBEM_S_NO_ERROR ;
  803. IWbemServices *pTmpProv = 0;
  804. CProviderSink *pTmpProvSink = 0;
  805. {
  806. CInCritSec ics(&CWmiTask::m_TaskCs);
  807. if (m_pProv != 0)
  808. {
  809. pTmpProv = m_pProv;
  810. m_pProv = 0;
  811. }
  812. if (m_pProvSink != 0)
  813. {
  814. pTmpProvSink = m_pProvSink;
  815. m_pProvSink = 0;
  816. }
  817. }
  818. if (pTmpProvSink)
  819. {
  820. pTmpProvSink->Cancel();
  821. }
  822. if (pTmpProv)
  823. {
  824. hRes = ExecCancelOnNewRequest ( pTmpProv, pTmpProvSink, pStatusSink ) ;
  825. }
  826. ReleaseIfNotNULL(pTmpProv);
  827. ReleaseIfNotNULL(pTmpProvSink);
  828. return hRes ;
  829. }
  830. // //////////////////////////////////////////////////////////////////////////////////////////
  831. //
  832. // Used when issuing CancelAsyncCall to providers associtated with the task.
  833. // Rather than calling CancelAsynCall directly on the provider, we create a brand
  834. // new request and execute it on a different thread. We do this to avoid hangs, since
  835. // PSS is waiting the Indicate/SetStatus call to return before servicing the CancelCallAsync.
  836. //
  837. // //////////////////////////////////////////////////////////////////////////////////////////
  838. HRESULT STaskProvider::ExecCancelOnNewRequest ( IWbemServices* pProv, CProviderSink* pSink, CStatusSink* pStatusSink )
  839. {
  840. // Sanity check on params
  841. if ( pSink == NULL ) return WBEM_E_INVALID_PARAMETER ;
  842. // Create new request
  843. wmilib::auto_ptr<CAsyncReq_CancelProvAsyncCall>
  844. pReq(new CAsyncReq_CancelProvAsyncCall ( pProv, pSink, pStatusSink ));
  845. if ( NULL == pReq.get() || NULL == pReq->GetContext())
  846. {
  847. return WBEM_E_OUT_OF_MEMORY ;
  848. }
  849. // Enqueue the request
  850. // If we have a status sink, then we should wait until the operation
  851. // completes before continuing so we can get the proper status from the
  852. // sink.
  853. HRESULT hRes;
  854. if ( NULL != pStatusSink )
  855. {
  856. hRes = ConfigMgr::EnqueueRequestAndWait(pReq.get());
  857. }
  858. else
  859. {
  860. hRes = ConfigMgr::EnqueueRequest(pReq.get());
  861. }
  862. if (FAILED(hRes)) return hRes;
  863. pReq.release();
  864. return WBEM_S_NO_ERROR;
  865. }