//*************************************************************************** // // WMITASK.CPP // // raymcc 23-Apr-00 First oversimplified draft for Whistler // raymcc 18-Mar-02 Security review. // //*************************************************************************** #include "precomp.h" #include #include #include #include #include #include #include static ULONG g_uNextTaskId = 1; static LONG g_uTaskCount = 0; extern ULONG g_ulClientCallbackTimeout ; //*************************************************************************** // //*************************************************************************** CStaticCritSec CWmiTask::m_TaskCs; CWmiTask* CWmiTask::CreateTask ( ) { try { return new CWmiTask(); //throws } catch( CX_Exception &) { return NULL; } } //*************************************************************************** // //*************************************************************************** CWmiTask::CWmiTask ( ) { m_hResult = WBEM_E_CALL_CANCELLED ; m_uRefCount = 1; m_uTaskType = 0; m_uTaskStatus = 0; m_uStartTime = 0; m_uTaskId = InterlockedIncrement((LONG *) &g_uNextTaskId); m_pNs = 0; m_pAsyncClientSink = 0; m_pReqSink = 0; m_uMemoryUsage = 0; m_uTotalSleepTime = 0; m_uCancelState = FALSE; m_uLastSleepTime = 0; m_hTimer = NULL; m_pMainCtx = 0; m_hCompletion = NULL ; m_bAccountedForThrottling = FALSE ; m_bCancelledDueToThrottling = FALSE ; m_pReqDoNotUse = NULL; m_pReqCancelNotSink = NULL; m_pStatusSink = new CStatusSink; if (NULL == m_pStatusSink) throw CX_MemoryException(); InterlockedIncrement((LONG *)&g_uTaskCount); } //*************************************************************************** // // CWmiTask::~CWmiTask // //*************************************************************************** // CWmiTask::~CWmiTask() { if (m_pNs) m_pNs->Release ( ) ; if (m_pAsyncClientSink) m_pAsyncClientSink->Release ( ) ; if (m_pReqSink) m_pReqSink->Release ( ) ; if (m_pMainCtx) m_pMainCtx->Release ( ) ; CCheckedInCritSec _cs ( &m_csTask ); // Release all provider/sink bindings. for (int i = 0; i < m_aTaskProviders.Size(); i++) { STaskProvider *pTP = (STaskProvider *) m_aTaskProviders[i]; delete pTP; } // Release all Arbitratees ReleaseArbitratees ( ) ; if ( m_hTimer ) CloseHandle ( m_hTimer ); if (m_hCompletion) CloseHandle ( m_hCompletion ) ; if (m_pStatusSink) m_pStatusSink->Release(); delete m_pReqCancelNotSink; InterlockedDecrement((LONG *)&g_uTaskCount); } /* * ============================================================================= | | HRESULT CWmiTask::SignalCancellation ( ) | ---------------------------------------- | | Signals the task to be cancelled | | * ============================================================================= */ HRESULT CWmiTask::SignalCancellation ( ) { CInCritSec _cs ( &m_csTask ); // SEC:REVIEWED 2002-03-22 : Assumes entry if ( ( m_uTaskStatus != WMICORE_TASK_STATUS_CANCELLED ) && ( m_hTimer != NULL ) ) { SetEvent ( m_hTimer ) ; // SEC:REVIEWED 2002-03-22 : Needs err check } return WBEM_S_NO_ERROR; } /* * ============================================================================= | | HRESULT CWmiTask::SetTaskResult ( HRESULT hRes ) | ------------------------------------------------- | | Sets the task result | | * ============================================================================= */ HRESULT CWmiTask::SetTaskResult ( HRESULT hResult ) { m_hResult = hResult ; return WBEM_S_NO_ERROR; } /* * ============================================================================= | | HRESULT CWmiTask::UpdateMemoryUsage ( LONG lDelta ) | --------------------------------------------------- | | Updates the task memory usage | | * ============================================================================= */ HRESULT CWmiTask::UpdateMemoryUsage ( LONG lDelta ) { CInCritSec _cs ( &m_csTask ); // SEC:REVIEWED 2002-03-22 : Assumes entry m_uMemoryUsage += lDelta ; return WBEM_S_NO_ERROR; } /* * ============================================================================= | | HRESULT CWmiTask::UpdateTotalSleepTime ( ULONG uSleepTime ) | ----------------------------------------------------------- | | Updates the tasks sleep time | | * ============================================================================= */ HRESULT CWmiTask::UpdateTotalSleepTime ( ULONG uSleepTime ) { CInCritSec _cs ( &m_csTask ); // SEC:REVIEWED 2002-03-22 : Assumes entry m_uTotalSleepTime += uSleepTime ; return WBEM_S_NO_ERROR; } /* * ============================================================================= | | HRESULT CWmiTask::ReleaseArbitratees ( ) | ---------------------------------------- | | Releases all the arbitratees (Finalizer, Merger currently) | | | | | * ============================================================================= */ HRESULT CWmiTask::ReleaseArbitratees ( BOOL bIsShutdown) { HRESULT hRes = WBEM_S_NO_ERROR ; CInCritSec _cs ( &m_csTask ); // SEC:REVIEWED 2002-03-22 : Assumes entry for (ULONG i = 0; i < m_aArbitratees.Size(); i++) { BOOL bLastNeeded = TRUE; _IWmiArbitratee *pArbee = NULL ; pArbee = (_IWmiArbitratee*) m_aArbitratees[i]; if ( pArbee ) { if (bIsShutdown) { IWbemShutdown * pShutdown = NULL; if (SUCCEEDED(pArbee->QueryInterface(IID_IWbemShutdown,(void **)&pShutdown))) { pShutdown->Shutdown(0,0,NULL); long lRet = pShutdown->Release(); // // Please understand the code in CWmiFinalizer::ShutDown for this trick // if (0 == lRet) bLastNeeded = FALSE; } } if (bLastNeeded) pArbee->Release(); } } m_aArbitratees.Empty(); return hRes ; } //*************************************************************************** // //*************************************************************************** HRESULT CWmiTask::SetRequestSink(CStdSink *pReqSink) { if (pReqSink == 0) return WBEM_E_INVALID_PARAMETER; if (m_pReqSink != 0) return WBEM_E_INVALID_OPERATION; CInCritSec _cs ( &m_csTask ); // SEC:REVIEWED 2002-03-22 : Assumes entry pReqSink->AddRef ( ) ; m_pReqSink = pReqSink; return WBEM_S_NO_ERROR; } //*************************************************************************** // //*************************************************************************** // * ULONG CWmiTask::AddRef() { InterlockedIncrement((LONG *) &m_uRefCount); return m_uRefCount; } //*************************************************************************** // //*************************************************************************** // * ULONG CWmiTask::Release() { ULONG uNewCount = InterlockedDecrement((LONG *) &m_uRefCount); if (0 != uNewCount) return uNewCount; delete this; return 0; } //*************************************************************************** // //*************************************************************************** // * HRESULT CWmiTask::QueryInterface( IN REFIID riid, OUT LPVOID *ppvObj ) { if (NULL == ppvObj) return E_POINTER; if (IID_IUnknown==riid || IID__IWmiCoreHandle==riid) { *ppvObj = (_IWmiCoreHandle *)this; AddRef(); return S_OK; } else { *ppvObj = 0; return E_NOINTERFACE; } } //*************************************************************************** // //*************************************************************************** // * HRESULT CWmiTask::GetHandleType( ULONG *puType ) { *puType = WMI_HANDLE_TASK; return WBEM_S_NO_ERROR; } //*************************************************************************** // //*************************************************************************** // * HRESULT CWmiTask::Initialize( IN CWbemNamespace *pNs, IN ULONG uTaskType, IN IWbemContext *pCtx, IN IWbemObjectSink *pAsyncClientSinkCopy, IN CAsyncReq *pReq ) { HRESULT hRes; if (pNs == 0 || pCtx == 0) return WBEM_E_INVALID_PARAMETER; m_hCompletion = CreateEvent(NULL,TRUE,FALSE,NULL); if (NULL == m_hCompletion) return WBEM_E_OUT_OF_MEMORY; // // this is just a pointer copy for the debugger // it MAY point to the request that originated us, or it MAY not // the lifetime of the request is generally less than the lifetime of the CWmiTask // m_pReqDoNotUse = pReq; m_pNs = pNs; m_pNs->AddRef(); m_uTaskType = uTaskType; if (CORE_TASK_TYPE(m_uTaskType) == WMICORE_TASK_EXEC_NOTIFICATION_QUERY) { wmilib::auto_ptr pReq( new CAsyncReq_RemoveNotifySink(m_pReqSink, NULL)); if (NULL == pReq.get() || NULL == pReq->GetContext()) { return WBEM_E_OUT_OF_MEMORY; } m_pReqCancelNotSink = pReq.release(); } m_uStartTime = GetCurrentTime(); // See if the task is primary or not. // ================================== if (pCtx) { CWbemContext *pContext = (CWbemContext *) pCtx; GUID ParentId = GUID_NULL; pContext->GetParentId(&ParentId); if (ParentId != GUID_NULL) { m_uTaskType |= WMICORE_TASK_TYPE_DEPENDENT; } else m_uTaskType |= WMICORE_TASK_TYPE_PRIMARY; m_pMainCtx = (CWbemContext *) pCtx; m_pMainCtx->AddRef(); } else { // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // If we dont have a context check to see if the namespace is an ESS or Provider // initialized namespace, if so, set the task type to dependent. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if ( pNs->GetIsESS ( ) || pNs->GetIsProvider ( ) ) { m_uTaskType |= WMICORE_TASK_TYPE_DEPENDENT; } else { m_uTaskType |= WMICORE_TASK_TYPE_PRIMARY; } } if ((uTaskType & WMICORE_TASK_TYPE_ASYNC) && pAsyncClientSinkCopy) { m_pAsyncClientSink = pAsyncClientSinkCopy; m_pAsyncClientSink->AddRef(); } else m_pAsyncClientSink = 0; // Register this task with Arbitrator. // ==================================== _IWmiArbitrator *pArb = CWmiArbitrator::GetUnrefedArbitrator(); if (!pArb) return WBEM_E_CRITICAL_ERROR; hRes = pArb->RegisterTask(this); if (FAILED(hRes)) return hRes; return WBEM_S_NO_ERROR; } //*************************************************************************** // //*************************************************************************** // /* HRESULT CWmiTask::SetFinalizer(_IWmiFinalizer *pFnz) { if (pFnz == 0) return WBEM_E_INVALID_PARAMETER; if (m_pWorkingFnz) return WBEM_E_INVALID_OPERATION; m_pWorkingFnz = pFnz; m_pWorkingFnz->AddRef(); return WBEM_S_NO_ERROR; } */ //*************************************************************************** // //*************************************************************************** // HRESULT CWmiTask::GetFinalizer(_IWmiFinalizer **ppFnz) { CInCritSec ics( &m_csTask ); // SEC:REVIEWED 2002-03-22 : Assumes entry for ( int x = 0; x < m_aArbitratees.Size(); x++ ) { _IWmiArbitratee* pArbitratee = (_IWmiArbitratee*) m_aArbitratees[x]; if (pArbitratee && SUCCEEDED( pArbitratee->QueryInterface( IID__IWmiFinalizer, (void**) ppFnz ) ) ) { break; } } return ( x < m_aArbitratees.Size() ? WBEM_S_NO_ERROR : WBEM_E_NOT_FOUND ); } //*************************************************************************** // //*************************************************************************** // HRESULT CWmiTask::AddArbitratee( ULONG uFlags, _IWmiArbitratee* pArbitratee ) { HRESULT hRes = WBEM_S_NO_ERROR; if (pArbitratee == 0) return WBEM_E_INVALID_PARAMETER; CInCritSec _cs ( &m_csTask ); if (m_uTaskStatus == WMICORE_TASK_STATUS_CANCELLED) return WBEM_S_NO_ERROR; if (CFlexArray::no_error != m_aArbitrateesStorage.InsertAt(m_aArbitratees.Size(),NULL)) return WBEM_E_OUT_OF_MEMORY; if (CFlexArray::no_error != m_aArbitratees.Add (pArbitratee)) return WBEM_E_OUT_OF_MEMORY; pArbitratee->AddRef(); return hRes; } //*************************************************************************** // //*************************************************************************** // HRESULT CWmiTask::RemoveArbitratee( ULONG uFlags, _IWmiArbitratee* pArbitratee ) { HRESULT hRes = WBEM_E_FAILED; if (pArbitratee == 0) return WBEM_E_INVALID_PARAMETER; CInCritSec _cs ( &m_csTask ); // SEC:REVIEWED 2002-03-22 : assumes entry for (int i = 0; i < m_aArbitratees.Size(); i++) { _IWmiArbitratee *pArbee = (_IWmiArbitratee*) m_aArbitratees[i]; if (pArbee == pArbitratee) { m_aArbitratees[i] = 0; pArbee->Release(); hRes = WBEM_S_NO_ERROR; break; } } return hRes; } //*************************************************************************** // //*************************************************************************** // HRESULT CWmiTask::GetArbitratedQuery( ULONG uFlags, _IWmiArbitratedQuery** ppArbitratedQuery ) { HRESULT hRes = E_NOINTERFACE; if (ppArbitratedQuery == 0) return WBEM_E_INVALID_PARAMETER; { CInCritSec _cs ( &m_csTask ); //#SEC:Assumes entry for ( int x = 0; FAILED( hRes ) && x < m_aArbitratees.Size(); x++ ) { _IWmiArbitratee* pArb = (_IWmiArbitratee*) m_aArbitratees[x]; if (pArb) { hRes = pArb->QueryInterface( IID__IWmiArbitratedQuery, (void**) ppArbitratedQuery ); } } } return hRes; } //*************************************************************************** // //*************************************************************************** HRESULT CWmiTask::GetPrimaryTask ( _IWmiCoreHandle** pPTask ) { if ( pPTask == NULL ) return WBEM_E_INVALID_PARAMETER; *pPTask = (_IWmiCoreHandle*) this; return WBEM_S_NO_ERROR; } //*************************************************************************** // //*************************************************************************** // HRESULT CWmiTask::Cancel( HRESULT hResParam ) { { CCheckedInCritSec _cs(&m_csTask); if (m_uTaskStatus == WMICORE_TASK_STATUS_CANCELLED) { return WBEM_S_NO_ERROR; // Prevent reentrancy } m_uTaskStatus = WMICORE_TASK_STATUS_CANCELLED; } BOOL bCancelledViaEss = FALSE ; OnDeleteObj RelArbitratees(this,WBEM_E_SHUTTING_DOWN == hResParam); // We'll want one of these in order to track statuses from all plausible locations if // we are performing a client originated cancel CStatusSink* pStatusSink = NULL; if (hResParam == WMIARB_CALL_CANCELLED_CLIENT) { // // transfer ownership of the StatusSink to the stack // initial refcount is 1, so we are OK // pStatusSink = m_pStatusSink; m_pStatusSink = NULL; } // Auto Release CReleaseMe rmStatusSink( pStatusSink ); // Change this to an async scheduled request // ========================================== if (CORE_TASK_TYPE(m_uTaskType) == WMICORE_TASK_EXEC_NOTIFICATION_QUERY) { wmilib::auto_ptr pReq(m_pReqCancelNotSink); m_pReqCancelNotSink = NULL; // transfer ownership pReq->SetSink(m_pReqSink); pReq->SetStatusSink(pStatusSink); // If we have a status sink, then we should wait until the operation // completes before continuing so we can get the proper status from the // sink. HRESULT hResInner; if (pStatusSink) // cancelled by the originating client { hResInner = ConfigMgr::EnqueueRequestAndWait(pReq.get()); } else { hResInner = ConfigMgr::EnqueueRequest(pReq.get()); } if (FAILED(hResInner)) return hResInner; pReq.release(); bCancelledViaEss = TRUE ; } // If here, a normal task. Loop through any providers and stop them. // ================================================================== int SizeIter = 0; // This could change while we're accessing, so do this in a critsec { CInCritSec ics( &m_csTask ); _DBG_ASSERT(m_aTaskProvStorage.Size() >= m_aTaskProviders.Size()); SizeIter = m_aTaskProviders.Size(); for (int i = 0; i < SizeIter; i++) m_aTaskProvStorage[i] = m_aTaskProviders[i]; } // Cancel what we've got // there cannot be 2 threads using m_aTaskProvStorage in the cancel call // m_uTaskStatus guards this code and the Add code for (int i = 0; i < SizeIter; i++) { STaskProvider *pTP = (STaskProvider *) m_aTaskProvStorage[i]; if (pTP) pTP->Cancel(pStatusSink); } CStdSink* pTempSink = NULL; { CInCritSec _cs ( &m_csTask ); if (m_pReqSink) { pTempSink = m_pReqSink; m_pReqSink = 0; } } if ( pTempSink ) { pTempSink->Cancel(); pTempSink->Release(); } _DBG_ASSERT(m_hCompletion); // // Loop through all arbitratees and set the operation result to cancelled // HRESULT hRes = WBEM_S_NO_ERROR; if (!bCancelledViaEss) { _IWmiFinalizer* pFinalizer = NULL ; if ( hResParam == WMIARB_CALL_CANCELLED_CLIENT ) { // // We need the finalizer to set the client wakeup event // hRes = GetFinalizer ( &pFinalizer ) ; if ( FAILED (hRes) ) { hRes = WBEM_E_FAILED ; } else { ((CWmiFinalizer*)pFinalizer)->SetClientCancellationHandle ( m_hCompletion ) ; } } CReleaseMe FinalizerRelease(pFinalizer); // // only enter wait state if we successfully created and set the client wait event // if (SUCCEEDED(hRes)) { if ( hResParam == WMIARB_CALL_CANCELLED_CLIENT || hResParam == WMIARB_CALL_CANCELLED_THROTTLING ) { SetArbitrateesOperationResult(0,WBEM_E_CALL_CANCELLED_CLIENT); } else { SetArbitrateesOperationResult(0,m_hResult); } if (hResParam == WMIARB_CALL_CANCELLED_CLIENT ) { if (((CWmiFinalizer*)pFinalizer)->IsValidDestinationSink()) { DWORD dwRet = CCoreQueue::QueueWaitForSingleObject(m_hCompletion,g_ulClientCallbackTimeout); if (dwRet == WAIT_TIMEOUT) { hRes = WBEM_S_TIMEDOUT; } } ((CWmiFinalizer*)pFinalizer)->CancelWaitHandle(); if (m_hCompletion) { CloseHandle(m_hCompletion); m_hCompletion = NULL ; } } } } // // We're done, get the final status from the status sink if we have one. // if ( NULL != pStatusSink ) { hRes = pStatusSink->GetLastStatus(); } return hRes ; } //*************************************************************************** // //*************************************************************************** // BOOL CWmiTask::IsESSNamespace ( ) { if (m_pNs) return m_pNs->GetIsESS ( ); return false; } //*************************************************************************** // //*************************************************************************** // BOOL CWmiTask::IsProviderNamespace ( ) { BOOL bRet = FALSE; if ( m_pNs ) { bRet = m_pNs->GetIsProvider ( ); } return bRet; } //*************************************************************************** // //*************************************************************************** // HRESULT CWmiTask::AddTaskProv(STaskProvider *p) { CInCritSec ics( &m_csTask ); // SEC:REVIEWED 2002-03-22 : assumes entry // There is a race condition in which the task could get cancelled just as we // are executing. In this case, the task status will indicate that it has been // cancelled, so we should not add it to the task providers list. if (m_uTaskStatus == WMICORE_TASK_STATUS_CANCELLED) return WBEM_E_CALL_CANCELLED; // Prevent reentrancy if (CFlexArray::no_error != m_aTaskProvStorage.InsertAt(m_aTaskProviders.Size()+1,NULL)) return WBEM_E_OUT_OF_MEMORY; if (CFlexArray::no_error != m_aTaskProviders.Add(p)) return WBEM_E_OUT_OF_MEMORY; return WBEM_S_NO_ERROR; } //*************************************************************************** // //*************************************************************************** // HRESULT CWmiTask::HasMatchingSink(void *Test, IN REFIID riid) { if (LPVOID(m_pAsyncClientSink) == LPVOID(Test)) return WBEM_S_NO_ERROR; return WBEM_E_NOT_FOUND; } //*************************************************************************** // //*************************************************************************** // HRESULT CWmiTask::CreateTimerEvent ( ) { HRESULT hRes = WBEM_S_NO_ERROR; CCheckedInCritSec _cs ( &m_csTask ); // SEC:REVIEWED 2002-03-22 : assumes entry if ( !m_hTimer ) { m_hTimer = CreateEvent ( NULL, TRUE, FALSE, NULL ); // SEC:REVIEWED 2002-03-22 : ok, unnamed if ( !m_hTimer ) { hRes = WBEM_E_OUT_OF_MEMORY; } } return hRes; } //*************************************************************************** // //*************************************************************************** HRESULT CWmiTask::SetArbitrateesOperationResult ( ULONG lFlags, HRESULT hResult ) { // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Set the operation result of all Arbitratees // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int Index = 0; // // this function is only called by the Cancel call // We knwon that the Cance call is called only ONCE // and the code for adding to the array uses the same guard of the Cancel() method // { CInCritSec _cs ( &m_csTask ); _DBG_ASSERT(m_aArbitrateesStorage.Size() >= m_aArbitratees.Size()); for (int i = 0; i < m_aArbitratees.Size(); i++) { _IWmiArbitratee *pArbee = (_IWmiArbitratee*) m_aArbitratees[i]; if ( pArbee ) { m_aArbitrateesStorage[Index++] = pArbee; pArbee->AddRef(); } } } for (int i = 0; i < Index; i++) { _IWmiArbitratee *pArbee = (_IWmiArbitratee*) m_aArbitrateesStorage[i]; pArbee->SetOperationResult(lFlags, hResult ); pArbee->Release(); m_aArbitrateesStorage[i] = NULL; } return WBEM_S_NO_ERROR; } //*************************************************************************** // //*************************************************************************** // HRESULT CWmiTask::Dump(FILE* f) { fprintf(f, "---Task = 0x%p----------------------------\n", this); // SEC:REVIEWED 2002-03-22 : OK fprintf(f, " Refcount = %d\n", m_uRefCount); // SEC:REVIEWED 2002-03-22 : OK fprintf(f, " TaskStatus = %u\n ", m_uTaskStatus); // SEC:REVIEWED 2002-03-22 : OK fprintf(f, " Task ID = %u\n", m_uTaskId); // SEC:REVIEWED 2002-03-22 : OK // Task status char *p = ""; switch(m_uTaskStatus) { case WMICORE_TASK_STATUS_NEW: p = "WMICORE_TASK_STATUS_NEW"; break; case WMICORE_TASK_STATUS_CANCELLED: p = "WMICORE_TASK_STATUS_CANCELLED"; break; }; fprintf(f, " %s\n", p); // SEC:REVIEWED 2002-03-22 : OK // Task type p = ""; switch(m_uTaskType & 0xFF) { case WMICORE_TASK_NULL: p = "WMICORE_TASK_NULL"; break; case WMICORE_TASK_GET_OBJECT: p = "WMICORE_TASK_GET_OBJECT"; break; case WMICORE_TASK_GET_INSTANCE: p = "WMICORE_TASK_GET_INSTANCE"; break; case WMICORE_TASK_PUT_INSTANCE: p = "WMICORE_TASK_PUT_INSTANCE"; break; case WMICORE_TASK_DELETE_INSTANCE: p = "WMICORE_TASK_DELETE_INSTANCE"; break; case WMICORE_TASK_ENUM_INSTANCES: p = "WMICORE_TASK_ENUM_INSTANCES"; break; case WMICORE_TASK_GET_CLASS: p = "WMICORE_TASK_GET_CLASS"; break; case WMICORE_TASK_PUT_CLASS: p = "WMICORE_TASK_PUT_CLASS"; break; case WMICORE_TASK_DELETE_CLASS: p = "WMICORE_TASK_DELETE_CLASS"; break; case WMICORE_TASK_ENUM_CLASSES: p = "WMICORE_TASK_ENUM_CLASSES"; break; case WMICORE_TASK_EXEC_QUERY: p = "WMICORE_TASK_EXEC_QUERY"; break; case WMICORE_TASK_EXEC_METHOD: p = "WMICORE_TASK_EXEC_METHOD"; break; case WMICORE_TASK_OPEN: p = "WMICORE_TASK_OPEN"; break; case WMICORE_TASK_OPEN_SCOPE: p = "WMICORE_TASK_OPEN_SCOPE"; break; case WMICORE_TASK_OPEN_NAMESPACE: p = "WMICORE_TASK_OPEN_NAMESPACE"; break; case WMICORE_TASK_EXEC_NOTIFICATION_QUERY: p = "WMICORE_TASK_EXEC_NOTIFICATION_QUERY"; break; } fprintf(f, " TaskType = [0x%X] %s ", m_uTaskType, p); // SEC:REVIEWED 2002-03-22 : OK if (m_uTaskType & WMICORE_TASK_TYPE_SYNC) fprintf(f, " WMICORE_TASK_TYPE_SYNC"); // SEC:REVIEWED 2002-03-22 : OK if (m_uTaskType & WMICORE_TASK_TYPE_SEMISYNC) fprintf(f, " WMICORE_TASK_TYPE_SEMISYNC"); // SEC:REVIEWED 2002-03-22 : OK if (m_uTaskType & WMICORE_TASK_TYPE_ASYNC) fprintf(f, " WMICORE_TASK_TYPE_ASYNC"); // SEC:REVIEWED 2002-03-22 : OK if (m_uTaskType & WMICORE_TASK_TYPE_PRIMARY) fprintf(f, " WMICORE_TASK_TYPE_PRIMARY"); // SEC:REVIEWED 2002-03-22 : OK if (m_uTaskType & WMICORE_TASK_TYPE_DEPENDENT) fprintf(f, " WMICORE_TASK_TYPE_DEPENDENT"); // SEC:REVIEWED 2002-03-22 : OK fprintf(f, "\n"); // SEC:REVIEWED 2002-03-22 : OK fprintf(f, " AsyncClientSink = 0x%p\n", m_pAsyncClientSink); // SEC:REVIEWED 2002-03-22 : OK CCheckedInCritSec ics( &m_csTask ); // SEC:REVIEWED 2002-03-22 : Assumes entry for (int i = 0; i < m_aTaskProviders.Size(); i++) { STaskProvider *pTP = (STaskProvider *) m_aTaskProviders[i]; 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 } ics.Leave(); DWORD dwAge = GetCurrentTime() - m_uStartTime; fprintf(f, " CWbemNamespace = 0x%p\n", m_pNs); // SEC:REVIEWED 2002-03-22 : OK fprintf(f, " Task age = %d milliseconds\n", dwAge); // SEC:REVIEWED 2002-03-22 : OK fprintf(f, " Task last sleep time = %d ms\n", m_uLastSleepTime ); // SEC:REVIEWED 2002-03-22 : OK fprintf(f, "\n"); // SEC:REVIEWED 2002-03-22 : OK return 0; } //*************************************************************************** // //*************************************************************************** // STaskProvider::~STaskProvider() { if (m_pProvSink) m_pProvSink->LocalRelease(); ReleaseIfNotNULL(m_pProv); } //*************************************************************************** // //*************************************************************************** // HRESULT STaskProvider::Cancel( CStatusSink* pStatusSink ) { HRESULT hRes = WBEM_S_NO_ERROR ; IWbemServices *pTmpProv = 0; CProviderSink *pTmpProvSink = 0; { CInCritSec ics(&CWmiTask::m_TaskCs); if (m_pProv != 0) { pTmpProv = m_pProv; m_pProv = 0; } if (m_pProvSink != 0) { pTmpProvSink = m_pProvSink; m_pProvSink = 0; } } if (pTmpProvSink) { pTmpProvSink->Cancel(); } if (pTmpProv) { hRes = ExecCancelOnNewRequest ( pTmpProv, pTmpProvSink, pStatusSink ) ; } ReleaseIfNotNULL(pTmpProv); ReleaseIfNotNULL(pTmpProvSink); return hRes ; } // ////////////////////////////////////////////////////////////////////////////////////////// // // Used when issuing CancelAsyncCall to providers associtated with the task. // Rather than calling CancelAsynCall directly on the provider, we create a brand // new request and execute it on a different thread. We do this to avoid hangs, since // PSS is waiting the Indicate/SetStatus call to return before servicing the CancelCallAsync. // // ////////////////////////////////////////////////////////////////////////////////////////// HRESULT STaskProvider::ExecCancelOnNewRequest ( IWbemServices* pProv, CProviderSink* pSink, CStatusSink* pStatusSink ) { // Sanity check on params if ( pSink == NULL ) return WBEM_E_INVALID_PARAMETER ; // Create new request wmilib::auto_ptr pReq(new CAsyncReq_CancelProvAsyncCall ( pProv, pSink, pStatusSink )); if ( NULL == pReq.get() || NULL == pReq->GetContext()) { return WBEM_E_OUT_OF_MEMORY ; } // Enqueue the request // If we have a status sink, then we should wait until the operation // completes before continuing so we can get the proper status from the // sink. HRESULT hRes; if ( NULL != pStatusSink ) { hRes = ConfigMgr::EnqueueRequestAndWait(pReq.get()); } else { hRes = ConfigMgr::EnqueueRequest(pReq.get()); } if (FAILED(hRes)) return hRes; pReq.release(); return WBEM_S_NO_ERROR; }