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
1058 lines
31 KiB
//***************************************************************************
|
|
//
|
|
// WMITASK.CPP
|
|
//
|
|
// raymcc 23-Apr-00 First oversimplified draft for Whistler
|
|
// raymcc 18-Mar-02 Security review.
|
|
//
|
|
//***************************************************************************
|
|
#include "precomp.h"
|
|
|
|
#include <windows.h>
|
|
#include <comdef.h>
|
|
#include <stdio.h>
|
|
#include <wbemcore.h>
|
|
#include <wmiarbitrator.h>
|
|
#include <wmifinalizer.h>
|
|
#include <context.h>
|
|
|
|
|
|
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<CAsyncReq_RemoveNotifySink> 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<BOOL,
|
|
CWmiTask,
|
|
HRESULT(CWmiTask::*)(BOOL),
|
|
&CWmiTask::ReleaseArbitratees> 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<CAsyncReq_RemoveNotifySink> 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 = "<none>";
|
|
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 = "<none>";
|
|
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<CAsyncReq_CancelProvAsyncCall>
|
|
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;
|
|
}
|
|
|
|
|