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

//***************************************************************************
//
// 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;
}