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.
1585 lines
46 KiB
1585 lines
46 KiB
/*++
|
|
|
|
Copyright (C) 2000-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
Abstract:
|
|
|
|
History:
|
|
|
|
--*/
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Cache.cpp
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "precomp.h"
|
|
#include <winperf.h>
|
|
#include <comdef.h>
|
|
#include <algorithm>
|
|
#include <wbemint.h>
|
|
#include <sync.h> // for CInCritSec
|
|
#include <autoptr.h>
|
|
|
|
#include "Cache.h"
|
|
#include "WMIObjCooker.h"
|
|
#include "CookerUtils.h"
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CProperty
|
|
// =========
|
|
//
|
|
// The base property - used for raw properties and the base
|
|
// class for the CookedProperty.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
CProperty::CProperty(LPWSTR wszName,
|
|
long lHandle, CIMTYPE ct ) :
|
|
#ifdef _VERBOSE
|
|
m_wszName( NULL ),
|
|
#endif
|
|
m_lPropHandle( lHandle ),
|
|
m_ct( ct )
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
//
|
|
//
|
|
// Parameters:
|
|
//
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
{
|
|
#ifdef _VERBOSE
|
|
size_t length = wcslen( wszName ) + 1;
|
|
m_wszName = new WCHAR[ length ];
|
|
if (m_wszName)
|
|
StringCchCopyW( m_wszName, length , wszName);
|
|
#endif
|
|
}
|
|
|
|
CProperty::~CProperty()
|
|
{
|
|
#ifdef _VERBOSE
|
|
delete [] m_wszName;
|
|
#endif
|
|
}
|
|
|
|
#ifdef _VERBOSE
|
|
LPWSTR CProperty::GetName()
|
|
{
|
|
return m_wszName?m_wszName:L"";
|
|
}
|
|
#endif
|
|
|
|
CIMTYPE CProperty::GetType()
|
|
{
|
|
return m_ct;
|
|
}
|
|
|
|
long CProperty::GetHandle()
|
|
{
|
|
return m_lPropHandle;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CCookingProperty
|
|
// ================
|
|
//
|
|
// The cooked property - used to model the data required to
|
|
// cook a property of a cooked class
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
CCookingProperty::CCookingProperty( LPWSTR wszName,
|
|
DWORD dwCounterType,
|
|
long lPropHandle,
|
|
CIMTYPE ct,
|
|
DWORD dwReqProp,
|
|
BOOL bUseWellKnownIfNeeded) :
|
|
CProperty( wszName, lPropHandle, ct ),
|
|
m_dwCounterType( dwCounterType ),
|
|
m_dwReqProp(dwReqProp),
|
|
m_nTimeFreq( 0 ),
|
|
m_lScale(0), // 10^0 = 1
|
|
m_pRawCounterProp( NULL ),
|
|
m_pTimeProp( NULL ),
|
|
m_pFrequencyProp( NULL ),
|
|
m_pBaseProp( NULL ),
|
|
m_nSampleWindow( 0 ),
|
|
m_nTimeWindow( 0 ),
|
|
m_bUseWellKnownIfNeeded(bUseWellKnownIfNeeded)
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Constructor
|
|
//
|
|
// Parameters:
|
|
// wszName - The property name
|
|
// dwCounterType - The property's counter type
|
|
// lPropHandle - The cooking property's WMI Access handle
|
|
// ct - The CIM type of the property
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
{}
|
|
|
|
CCookingProperty::~CCookingProperty()
|
|
{
|
|
delete m_pRawCounterProp;
|
|
delete m_pTimeProp;
|
|
delete m_pFrequencyProp;
|
|
delete m_pBaseProp;
|
|
}
|
|
|
|
|
|
//
|
|
//
|
|
//
|
|
// Parameters:
|
|
// pCookingClassAccess - The class definition for the cooking class
|
|
//
|
|
// Description:
|
|
// For each property of the class to be cooked
|
|
// we need to find the property of the Raw class needed in the formula
|
|
// The 'Counter' qualifier is always needed,
|
|
// but thereafter we might need the timestap, the base, the frequency, ecc, ecc
|
|
// SOme of these are in the PropertyQualifierSet, but other can be defaulted in the
|
|
// ClassQualifierSet
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
WMISTATUS CCookingProperty::Initialize( IWbemQualifierSet* pCookingPropQualifierSet,
|
|
IWbemObjectAccess* pRawAccess,
|
|
IWbemQualifierSet* pCookingClassQSet)
|
|
{
|
|
WMISTATUS dwStatus = WBEM_NO_ERROR;
|
|
|
|
_variant_t vVal;
|
|
|
|
// Initialize the raw counter property ("Counter")
|
|
// ===============================================
|
|
dwStatus = pCookingPropQualifierSet->Get( WMI_COOKER_RAW_COUNTER, 0, &vVal, NULL );
|
|
|
|
if ( SUCCEEDED( dwStatus ) && ( vVal.vt != VT_BSTR ) )
|
|
{
|
|
dwStatus = E_FAIL;
|
|
}
|
|
|
|
if ( SUCCEEDED( dwStatus ) )
|
|
{
|
|
// Get the raw data properties
|
|
// ===========================
|
|
|
|
CIMTYPE ct;
|
|
|
|
long lHandle = 0;
|
|
WCHAR* wszRawCounterName = vVal.bstrVal;
|
|
|
|
// Get the raw counter property
|
|
// ============================
|
|
|
|
dwStatus = pRawAccess->GetPropertyHandle( wszRawCounterName, &ct, &lHandle );
|
|
|
|
if ( SUCCEEDED( dwStatus ) )
|
|
{
|
|
m_pRawCounterProp = new CProperty( wszRawCounterName, lHandle, ct );
|
|
|
|
if ( NULL == m_pRawCounterProp )
|
|
{
|
|
dwStatus = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
|
|
// Get the raw base property
|
|
// =========================
|
|
|
|
if ( SUCCEEDED( dwStatus ) )
|
|
{
|
|
_variant_t vProp;
|
|
dwStatus = pCookingPropQualifierSet->Get( WMI_COOKER_RAW_BASE, 0, &vProp, NULL );
|
|
|
|
if ( SUCCEEDED( dwStatus ) )
|
|
{
|
|
if ( vProp.vt == VT_BSTR )
|
|
{
|
|
dwStatus = pRawAccess->GetPropertyHandle( vProp.bstrVal, &ct, &lHandle );
|
|
|
|
if ( SUCCEEDED( dwStatus ) )
|
|
{
|
|
m_pBaseProp = new CProperty( vProp.bstrVal, lHandle, ct );
|
|
|
|
if ( NULL == m_pBaseProp )
|
|
{
|
|
dwStatus = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwStatus = WBEM_E_TYPE_MISMATCH;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// the property qualifier set failed, try the class one
|
|
_variant_t varProp; // does not throw, simple container
|
|
dwStatus = pCookingClassQSet->Get( WMI_COOKER_RAW_BASE, 0, &varProp, NULL );
|
|
|
|
if ( SUCCEEDED( dwStatus ) )
|
|
{
|
|
if ( varProp.vt == VT_BSTR )
|
|
{
|
|
dwStatus = pRawAccess->GetPropertyHandle( varProp.bstrVal, &ct, &lHandle );
|
|
|
|
if ( SUCCEEDED( dwStatus ) )
|
|
{
|
|
m_pBaseProp = new CProperty( varProp.bstrVal, lHandle, ct );
|
|
|
|
if ( NULL == m_pBaseProp )
|
|
{
|
|
dwStatus = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwStatus = WBEM_E_TYPE_MISMATCH;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwStatus = WBEM_NO_ERROR;
|
|
}
|
|
}
|
|
//
|
|
// no error so far, the BASE qulifier is REQUIRED, but none is found
|
|
//
|
|
if ( SUCCEEDED( dwStatus ) &&
|
|
IsReq(REQ_BASE) &&
|
|
(NULL == m_pBaseProp))
|
|
{
|
|
dwStatus = WBEM_E_INVALID_CLASS;
|
|
}
|
|
}
|
|
|
|
// Get the raw timestamp property record
|
|
// =====================================
|
|
|
|
if ( SUCCEEDED( dwStatus ) )
|
|
{
|
|
_variant_t vProp2;
|
|
dwStatus = pCookingPropQualifierSet->Get( WMI_COOKER_RAW_TIME, 0, &vProp2, NULL );
|
|
|
|
if ( SUCCEEDED( dwStatus ) )
|
|
{
|
|
if ( vProp2.vt == VT_BSTR )
|
|
{
|
|
dwStatus = pRawAccess->GetPropertyHandle( vProp2.bstrVal, &ct, &lHandle );
|
|
|
|
if ( SUCCEEDED( dwStatus ) )
|
|
{
|
|
m_pTimeProp = new CProperty( vProp2.bstrVal, lHandle, ct );
|
|
|
|
if ( NULL == m_pTimeProp )
|
|
{
|
|
dwStatus = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwStatus = WBEM_E_TYPE_MISMATCH;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
// the property qualifier set failed, try the class one
|
|
|
|
//PERF_TIMER_TICK
|
|
//PERF_TIMER_100NS
|
|
//PERF_OBJECT_TIMER
|
|
|
|
_variant_t varProp; // does not throw, simple container
|
|
if (m_dwCounterType & PERF_OBJECT_TIMER)
|
|
{
|
|
dwStatus = pCookingClassQSet->Get( WMI_COOKER_RAW_TIME_OBJ, 0, &varProp, NULL );
|
|
if (FAILED(dwStatus) && m_bUseWellKnownIfNeeded)
|
|
{
|
|
dwStatus = WBEM_NO_ERROR;
|
|
varProp = WMI_COOKER_REQ_TIMESTAMP_PERFTIME;
|
|
}
|
|
}
|
|
else if (m_dwCounterType & PERF_TIMER_100NS)
|
|
{
|
|
dwStatus = pCookingClassQSet->Get( WMI_COOKER_RAW_TIME_100NS, 0, &varProp, NULL );
|
|
if (FAILED(dwStatus) && m_bUseWellKnownIfNeeded)
|
|
{
|
|
dwStatus = WBEM_NO_ERROR;
|
|
varProp = WMI_COOKER_REQ_TIMESTAMP_SYS100NS;
|
|
}
|
|
} else
|
|
{
|
|
dwStatus = pCookingClassQSet->Get( WMI_COOKER_RAW_TIME_SYS, 0, &varProp, NULL );
|
|
if (FAILED(dwStatus) && m_bUseWellKnownIfNeeded)
|
|
{
|
|
dwStatus = WBEM_NO_ERROR;
|
|
varProp = WMI_COOKER_REQ_TIMESTAMP_OBJECT;
|
|
}
|
|
}
|
|
|
|
if ( SUCCEEDED( dwStatus ) )
|
|
{
|
|
if ( varProp.vt == VT_BSTR )
|
|
{
|
|
dwStatus = pRawAccess->GetPropertyHandle( varProp.bstrVal, &ct, &lHandle );
|
|
|
|
if ( SUCCEEDED( dwStatus ) )
|
|
{
|
|
m_pTimeProp = new CProperty( varProp.bstrVal, lHandle, ct );
|
|
|
|
if ( NULL == m_pTimeProp )
|
|
{
|
|
dwStatus = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwStatus = WBEM_E_TYPE_MISMATCH;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwStatus = WBEM_NO_ERROR;
|
|
}
|
|
}
|
|
|
|
// get in cascade the frequency property
|
|
if (SUCCEEDED(dwStatus))
|
|
{
|
|
_variant_t VarFreqName; // simple container, does not throw
|
|
dwStatus = pCookingPropQualifierSet->Get( WMI_COOKER_RAW_FREQUENCY, 0, &VarFreqName, NULL );
|
|
|
|
if (SUCCEEDED(dwStatus))
|
|
{
|
|
if (VarFreqName.vt == VT_BSTR)
|
|
{
|
|
dwStatus = pRawAccess->GetPropertyHandle( VarFreqName.bstrVal, &ct, &lHandle );
|
|
|
|
if (SUCCEEDED(dwStatus))
|
|
{
|
|
m_pFrequencyProp = new CProperty( VarFreqName.bstrVal, lHandle, ct );
|
|
|
|
if ( NULL == m_pFrequencyProp )
|
|
{
|
|
dwStatus = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
|
|
} else {
|
|
dwStatus = WBEM_E_TYPE_MISMATCH;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (m_dwCounterType & PERF_OBJECT_TIMER)
|
|
{
|
|
dwStatus = pCookingClassQSet->Get( WMI_COOKER_RAW_FREQ_OBJ, 0, &VarFreqName, NULL );
|
|
if (FAILED(dwStatus) && m_bUseWellKnownIfNeeded)
|
|
{
|
|
dwStatus = WBEM_NO_ERROR;
|
|
VarFreqName = WMI_COOKER_REQ_FREQUENCY_PERFTIME;
|
|
}
|
|
}
|
|
else if (m_dwCounterType & PERF_TIMER_100NS)
|
|
{
|
|
dwStatus = pCookingClassQSet->Get( WMI_COOKER_RAW_FREQ_100NS, 0, &VarFreqName, NULL );
|
|
if (FAILED(dwStatus) && m_bUseWellKnownIfNeeded)
|
|
{
|
|
dwStatus = WBEM_NO_ERROR;
|
|
VarFreqName = WMI_COOKER_REQ_FREQUENCY_SYS100NS;
|
|
}
|
|
} else
|
|
{
|
|
dwStatus = pCookingClassQSet->Get( WMI_COOKER_RAW_FREQ_SYS, 0, &VarFreqName, NULL );
|
|
if (FAILED(dwStatus) && m_bUseWellKnownIfNeeded)
|
|
{
|
|
dwStatus = WBEM_NO_ERROR;
|
|
VarFreqName = WMI_COOKER_REQ_FREQUENCY_OBJECT;
|
|
}
|
|
}
|
|
|
|
|
|
if (SUCCEEDED(dwStatus))
|
|
{
|
|
if (VarFreqName.vt == VT_BSTR)
|
|
{
|
|
dwStatus = pRawAccess->GetPropertyHandle( VarFreqName.bstrVal, &ct, &lHandle );
|
|
|
|
if (SUCCEEDED(dwStatus))
|
|
{
|
|
m_pFrequencyProp = new CProperty( VarFreqName.bstrVal, lHandle, ct );
|
|
|
|
if ( NULL == m_pFrequencyProp )
|
|
{
|
|
dwStatus = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
|
|
} else {
|
|
dwStatus = WBEM_E_TYPE_MISMATCH;
|
|
}
|
|
} else {
|
|
dwStatus = WBEM_S_NO_ERROR;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Get the Scale factor from ONLY the property Qualifier
|
|
//
|
|
if ( SUCCEEDED( dwStatus ) )
|
|
{
|
|
_variant_t VarScale; // does not throw, simple container
|
|
dwStatus = pCookingPropQualifierSet->Get( WMI_COOKER_SCALE_FACT, 0, &VarScale, NULL );
|
|
|
|
if ( SUCCEEDED( dwStatus ) && (V_VT(&VarScale) == VT_I4))
|
|
{
|
|
m_lScale = VarScale.intVal;
|
|
}
|
|
else
|
|
{
|
|
dwStatus = WBEM_S_NO_ERROR;
|
|
}
|
|
}
|
|
|
|
|
|
// Get the Sample and Time windows value
|
|
// =====================================
|
|
|
|
if ( SUCCEEDED( dwStatus ) )
|
|
{
|
|
DWORD dwSampleStatus = WBEM_NO_ERROR,
|
|
dwTimeStatus = WBEM_NO_ERROR;
|
|
|
|
_variant_t vSampleProp; // does not throw, simple container
|
|
_variant_t vTimeProp; // does not throw, simple container
|
|
|
|
dwSampleStatus = pCookingPropQualifierSet->Get( WMI_COOKER_SAMPLE_WINDOW, 0, &vSampleProp, NULL );
|
|
dwTimeStatus = pCookingPropQualifierSet->Get( WMI_COOKER_TIME_WINDOW, 0, &vTimeProp, NULL );
|
|
|
|
|
|
if ( SUCCEEDED( dwSampleStatus ) && SUCCEEDED( dwTimeStatus ) )
|
|
{
|
|
dwStatus = WBEM_E_INVALID_PROPERTY;
|
|
}
|
|
else if ( SUCCEEDED( dwSampleStatus ) )
|
|
{
|
|
if ( vSampleProp.vt != VT_I4 )
|
|
{
|
|
dwStatus = E_FAIL;
|
|
}
|
|
else
|
|
{
|
|
m_nSampleWindow = vSampleProp.intVal;
|
|
}
|
|
}
|
|
else if ( SUCCEEDED( dwTimeStatus ) )
|
|
{
|
|
if ( vTimeProp.vt != VT_I4 )
|
|
dwStatus = E_FAIL;
|
|
else
|
|
m_nTimeWindow = vTimeProp.intVal;
|
|
}
|
|
else
|
|
{
|
|
m_nSampleWindow = WMI_DEFAULT_SAMPLE_WINDOW;
|
|
}
|
|
}
|
|
}
|
|
|
|
return dwStatus;
|
|
}
|
|
|
|
//
|
|
// Description: the RawCooker could easily be a Singleton shared among
|
|
// all the cooking properties, since it does not mantain state on behaf of the
|
|
// Cooking property
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
WMISTATUS CCookingProperty::Cook( DWORD dwNumSamples, __int64* aRawCounter, __int64* aBaseCounter, __int64* aTimeStamp, __int64* pnResult )
|
|
{
|
|
WMISTATUS dwStatus = WBEM_NO_ERROR;
|
|
|
|
dwStatus = m_Cooker.CookRawValues( m_dwCounterType,
|
|
dwNumSamples,
|
|
aTimeStamp,
|
|
aRawCounter,
|
|
aBaseCounter,
|
|
m_nTimeFreq,
|
|
m_lScale,
|
|
pnResult );
|
|
|
|
return dwStatus;
|
|
}
|
|
|
|
CProperty* CCookingProperty::GetRawCounterProperty()
|
|
{
|
|
return m_pRawCounterProp;
|
|
}
|
|
|
|
CProperty* CCookingProperty::GetBaseProperty()
|
|
{
|
|
return m_pBaseProp;
|
|
}
|
|
|
|
CProperty* CCookingProperty::GetTimeProperty()
|
|
{
|
|
return m_pTimeProp;
|
|
}
|
|
|
|
HRESULT
|
|
CCookingProperty::SetFrequency(IWbemObjectAccess * pObjAcc)
|
|
{
|
|
if (m_nTimeFreq == 0)
|
|
{
|
|
// get the Frequency from the Raw Object
|
|
if (m_pFrequencyProp)
|
|
{
|
|
__int64 lTmp;
|
|
HRESULT hRes = GetPropValue(m_pFrequencyProp,pObjAcc,lTmp);
|
|
if (SUCCEEDED(hRes)) m_nTimeFreq = lTmp;
|
|
return hRes;
|
|
}
|
|
else if (!(m_dwReqProp & REQ_FREQ))
|
|
{
|
|
return WBEM_NO_ERROR;
|
|
}
|
|
else
|
|
{
|
|
LARGE_INTEGER li;
|
|
if (QueryPerformanceFrequency(&li))
|
|
{
|
|
m_nTimeFreq = li.QuadPart;
|
|
return WBEM_NO_ERROR;
|
|
}
|
|
else
|
|
{
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return WBEM_NO_ERROR;
|
|
}
|
|
|
|
}
|
|
|
|
unsigned __int64 CCookingProperty::GetFrequency(void)
|
|
{
|
|
return m_nTimeFreq;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CPropertySampleCache
|
|
// ====================
|
|
//
|
|
// This class caches the sample data for a single property for a single
|
|
// instance
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
CPropertySampleCache::CPropertySampleCache():
|
|
m_aRawCounterVals(NULL),
|
|
m_aBaseCounterVals(NULL),
|
|
m_aTimeStampVals(NULL),
|
|
m_dwRefreshID(0)
|
|
{
|
|
}
|
|
|
|
CPropertySampleCache::~CPropertySampleCache()
|
|
{
|
|
delete [] m_aRawCounterVals;
|
|
delete [] m_aBaseCounterVals;
|
|
delete [] m_aTimeStampVals;
|
|
}
|
|
|
|
WMISTATUS CPropertySampleCache::SetSampleInfo( DWORD dwNumActiveSamples, DWORD dwMinReqSamples )
|
|
{
|
|
WMISTATUS dwStatus = WBEM_NO_ERROR;
|
|
|
|
m_dwNumSamples = 0;
|
|
m_dwTotSamples = dwNumActiveSamples;
|
|
|
|
m_aRawCounterVals = new __int64[dwNumActiveSamples];
|
|
if (!m_aRawCounterVals)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
memset( m_aRawCounterVals, 0, sizeof(__int64) * dwNumActiveSamples );
|
|
|
|
m_aBaseCounterVals = new __int64[dwNumActiveSamples];
|
|
if (!m_aBaseCounterVals)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
memset( m_aBaseCounterVals, 0, sizeof(__int64) * dwNumActiveSamples );
|
|
|
|
m_aTimeStampVals = new __int64[dwNumActiveSamples];
|
|
if (!m_aTimeStampVals)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
memset( m_aBaseCounterVals, 0, sizeof(__int64) * dwNumActiveSamples );
|
|
|
|
return dwStatus;
|
|
}
|
|
|
|
|
|
WMISTATUS CPropertySampleCache::SetSampleData( DWORD dwRefreshID, __int64 nRawCounter, __int64 nRawBase, __int64 nTimeStamp )
|
|
{
|
|
WMISTATUS dwStatus = WBEM_NO_ERROR;
|
|
|
|
if (dwRefreshID <= m_dwRefreshID)
|
|
{
|
|
return dwStatus;
|
|
}
|
|
else
|
|
{
|
|
m_dwRefreshID = dwRefreshID;
|
|
}
|
|
|
|
if ( m_dwNumSamples < m_dwTotSamples )
|
|
{
|
|
m_dwNumSamples++;
|
|
}
|
|
|
|
if ( m_dwTotSamples >= 2 )
|
|
{
|
|
for (LONG i = (LONG)(m_dwTotSamples-2); i>=0; i--)
|
|
{
|
|
m_aRawCounterVals[i+1] = m_aRawCounterVals[i];
|
|
m_aBaseCounterVals[i+1] = m_aBaseCounterVals[i];
|
|
m_aTimeStampVals[i+1] = m_aTimeStampVals[i];
|
|
}
|
|
}
|
|
|
|
m_aRawCounterVals[0] = nRawCounter;
|
|
m_aBaseCounterVals[0] = nRawBase;
|
|
m_aTimeStampVals[0] = nTimeStamp;
|
|
|
|
return dwStatus;
|
|
}
|
|
|
|
WMISTATUS CPropertySampleCache::GetData( DWORD* pdwNumSamples, __int64** paRawCounter, __int64** paBaseCounter, __int64** paTimeStamp )
|
|
{
|
|
WMISTATUS dwStatus = WBEM_NO_ERROR;
|
|
|
|
*pdwNumSamples = m_dwNumSamples;
|
|
*paRawCounter = m_aRawCounterVals;
|
|
*paBaseCounter = m_aBaseCounterVals;
|
|
*paTimeStamp = m_aTimeStampVals;
|
|
|
|
return dwStatus;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CCookingInstance
|
|
// ================
|
|
//
|
|
// The cooking instance - used to model an instance of a cooked object. Each
|
|
// property maintains a cache of values that will be used to compute the
|
|
// final cooked value.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
CCookingInstance::CCookingInstance( IWbemObjectAccess *pCookingInstance, DWORD dwNumProps ) :
|
|
m_wszKey( NULL ),
|
|
m_aPropertySamples( NULL ),
|
|
m_pCookingInstance( pCookingInstance ),
|
|
m_pRawInstance( NULL ),
|
|
m_dwNumProps( dwNumProps )
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
//
|
|
//
|
|
// Parameters:
|
|
//
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
{
|
|
if ( m_pCookingInstance )
|
|
{
|
|
m_pCookingInstance->AddRef();
|
|
m_wszKey = ::GetKey( m_pCookingInstance );
|
|
}
|
|
|
|
if (dwNumProps)
|
|
{
|
|
// allocation checked in IsValid
|
|
m_aPropertySamples = new CPropertySampleCache[dwNumProps];
|
|
};
|
|
}
|
|
|
|
|
|
CCookingInstance::~CCookingInstance()
|
|
{
|
|
|
|
delete [] m_wszKey;
|
|
|
|
if ( NULL != m_pCookingInstance )
|
|
{
|
|
m_pCookingInstance->Release();
|
|
}
|
|
|
|
delete [] m_aPropertySamples;
|
|
|
|
if ( NULL != m_pRawInstance )
|
|
{
|
|
m_pRawInstance->Release();
|
|
}
|
|
}
|
|
|
|
WMISTATUS CCookingInstance::InitProperty( DWORD dwProp, DWORD dwNumActiveSamples, DWORD dwMinReqSamples )
|
|
{
|
|
return m_aPropertySamples[dwProp].SetSampleInfo( dwNumActiveSamples, dwMinReqSamples );
|
|
}
|
|
|
|
WMISTATUS CCookingInstance::SetRawSourceInstance( IWbemObjectAccess* pRawSampleSource )
|
|
{
|
|
WMISTATUS dwStatus = WBEM_NO_ERROR;
|
|
|
|
if ( NULL != m_pRawInstance )
|
|
{
|
|
m_pRawInstance->Release();
|
|
}
|
|
|
|
m_pRawInstance = pRawSampleSource;
|
|
|
|
if ( NULL != m_pRawInstance )
|
|
{
|
|
m_pRawInstance->AddRef();
|
|
}
|
|
|
|
return dwStatus;
|
|
}
|
|
|
|
WMISTATUS CCookingInstance::GetRawSourceInstance( IWbemObjectAccess** ppRawSampleSource )
|
|
{
|
|
WMISTATUS dwStatus = WBEM_NO_ERROR;
|
|
|
|
*ppRawSampleSource = m_pRawInstance;
|
|
|
|
if ( NULL != m_pRawInstance )
|
|
{
|
|
m_pRawInstance->AddRef();
|
|
}
|
|
|
|
return dwStatus;
|
|
}
|
|
|
|
IWbemObjectAccess* CCookingInstance::GetInstance()
|
|
{
|
|
if ( NULL != m_pCookingInstance )
|
|
m_pCookingInstance->AddRef();
|
|
|
|
return m_pCookingInstance;
|
|
}
|
|
|
|
WMISTATUS CCookingInstance::AddSample( DWORD dwRefreshStamp, DWORD dwProp, __int64 nRawCounter, __int64 nRawBase, __int64 nTimeStamp )
|
|
{
|
|
return m_aPropertySamples[dwProp].SetSampleData( dwRefreshStamp, nRawCounter, nRawBase, nTimeStamp );
|
|
}
|
|
|
|
WMISTATUS CCookingInstance::Refresh( IWbemObjectAccess* pRawData, IWbemObjectAccess** ppCookedData )
|
|
{
|
|
WMISTATUS dwStatus = WBEM_NO_ERROR;
|
|
|
|
return dwStatus;
|
|
}
|
|
|
|
WMISTATUS CCookingInstance::UpdateSamples()
|
|
{
|
|
WMISTATUS dwStatus = WBEM_NO_ERROR;
|
|
|
|
return dwStatus;
|
|
}
|
|
|
|
WMISTATUS CCookingInstance::CookProperty( DWORD dwProp, CCookingProperty* pProperty )
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
//
|
|
//
|
|
// Parameters:
|
|
//
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
{
|
|
WMISTATUS dwStatus = WBEM_NO_ERROR;
|
|
|
|
DWORD dwNumSamples = 0;
|
|
__int64* aRawCounter;
|
|
__int64* aBaseCounter;
|
|
__int64* aTimeStamp;
|
|
__int64 nResult = 0;
|
|
|
|
long lHandle = pProperty->GetHandle();
|
|
|
|
dwStatus = m_aPropertySamples[dwProp].GetData( &dwNumSamples, &aRawCounter, &aBaseCounter, &aTimeStamp );
|
|
|
|
if ( SUCCEEDED( dwStatus ) )
|
|
{
|
|
#ifdef _VERBOSE
|
|
{
|
|
unsigned __int64 Freq = pProperty->GetFrequency();
|
|
DbgPrintfA(0,"PropName %S sample %d\n"
|
|
"Raw %I64d %I64d\n"
|
|
"Base %I64d %I64d\n"
|
|
"Time %I64d %I64d\n"
|
|
"Freq %I64d\n",
|
|
pProperty->GetName(),dwNumSamples,
|
|
aRawCounter[0],aRawCounter[1],
|
|
aBaseCounter[0],aBaseCounter[1],
|
|
aTimeStamp[0],aTimeStamp[1],
|
|
Freq);
|
|
}
|
|
#endif
|
|
|
|
if (SUCCEEDED(dwStatus = pProperty->SetFrequency(m_pRawInstance))){
|
|
|
|
dwStatus = pProperty->Cook( dwNumSamples, aRawCounter, aBaseCounter, aTimeStamp, &nResult );
|
|
}
|
|
#ifdef _VERBOSE
|
|
DbgPrintfA(0,"Result %I64d dwStatus %08x\n",nResult,dwStatus);
|
|
#endif
|
|
};
|
|
|
|
if ( SUCCEEDED( dwStatus ) )
|
|
{
|
|
switch ( pProperty->GetType() )
|
|
{
|
|
case CIM_UINT32:
|
|
dwStatus = m_pCookingInstance->WriteDWORD( lHandle, (DWORD) nResult );
|
|
break;
|
|
case CIM_UINT64:
|
|
dwStatus = m_pCookingInstance->WriteQWORD( lHandle, nResult );
|
|
break;
|
|
default:
|
|
dwStatus = WBEM_E_TYPE_MISMATCH;
|
|
}
|
|
};
|
|
|
|
return dwStatus;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
//
|
|
//
|
|
// CEnumeratorCache
|
|
//
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
CEnumeratorCache::CEnumeratorCache() :
|
|
m_dwEnum( 0 )
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
//
|
|
//
|
|
// Parameters:
|
|
//
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
{
|
|
}
|
|
|
|
CEnumeratorCache::~CEnumeratorCache()
|
|
{
|
|
CInCritSec ics(&m_cs);
|
|
for (DWORD i=0;i<m_apEnumerators.size();i++)
|
|
{
|
|
CEnumeratorManager* pEnumMgr = m_apEnumerators[i];
|
|
if (pEnumMgr) pEnumMgr->Release();
|
|
}
|
|
}
|
|
|
|
WMISTATUS CEnumeratorCache::AddEnum( LPCWSTR wszCookingClass,
|
|
IWbemClassObject* pCookedClass,
|
|
IWbemClassObject* pRawClass,
|
|
IWbemHiPerfEnum* pCookedEnum,
|
|
IWbemHiPerfEnum* pRawEnum,
|
|
long lIDRaw,
|
|
DWORD* pdwID )
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
//
|
|
//
|
|
// Parameters:
|
|
//
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
{
|
|
WMISTATUS dwStatus = WBEM_NO_ERROR;
|
|
|
|
CEnumeratorManager* pEnumMgr = new CEnumeratorManager( wszCookingClass, pCookedClass, pRawClass, pCookedEnum, pRawEnum, lIDRaw );
|
|
if (NULL == pEnumMgr) return WBEM_E_OUT_OF_MEMORY;
|
|
|
|
CInCritSec ics(&m_cs);
|
|
if (SUCCEEDED(pEnumMgr->GetInithResult()))
|
|
{
|
|
DWORD i;
|
|
for (i=0;i<m_apEnumerators.size();i++)
|
|
{
|
|
if(m_apEnumerators[i] == NULL)
|
|
{
|
|
m_apEnumerators[i] = pEnumMgr;
|
|
if (pdwID)
|
|
{
|
|
*pdwID = i;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
// we need to expand the array
|
|
if (i == m_apEnumerators.size())
|
|
{
|
|
try
|
|
{
|
|
m_apEnumerators.push_back(pEnumMgr);
|
|
if (pdwID)
|
|
{
|
|
*pdwID = m_apEnumerators.size()-1;
|
|
}
|
|
}
|
|
catch (...)
|
|
{
|
|
pEnumMgr->Release();
|
|
dwStatus = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
dwStatus = pEnumMgr->GetInithResult();
|
|
}
|
|
|
|
return dwStatus;
|
|
}
|
|
|
|
WMISTATUS CEnumeratorCache::RemoveEnum( DWORD dwID , long * pRawId )
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
//
|
|
//
|
|
// Parameters:
|
|
//
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
{
|
|
WMISTATUS dwStatus = WBEM_NO_ERROR;
|
|
|
|
|
|
CInCritSec ics(&m_cs);
|
|
|
|
if ( dwID < m_apEnumerators.size() )
|
|
{
|
|
CEnumeratorManager* pEnumMgr = m_apEnumerators[dwID];
|
|
m_apEnumerators[dwID] = NULL;
|
|
|
|
if (pRawId) *pRawId = pEnumMgr->GetRawId();
|
|
|
|
pEnumMgr->Release();
|
|
}
|
|
else
|
|
{
|
|
dwStatus = E_FAIL;
|
|
}
|
|
return dwStatus;
|
|
}
|
|
|
|
WMISTATUS CEnumeratorCache::Refresh(DWORD dwRefreshId)
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
//
|
|
//
|
|
// Parameters:
|
|
//
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
{
|
|
WMISTATUS dwStatus = WBEM_NO_ERROR;
|
|
|
|
|
|
CEnumeratorManager** ppEnumMang = new CEnumeratorManager*[m_apEnumerators.size()];
|
|
wmilib::auto_buffer<CEnumeratorManager*> rm_(ppEnumMang);
|
|
if (!ppEnumMang)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
|
|
memset(ppEnumMang,0,sizeof(CEnumeratorManager*)*m_apEnumerators.size());
|
|
|
|
DWORD j=0;
|
|
DWORD i=0;
|
|
|
|
{
|
|
CInCritSec ics(&m_cs);
|
|
|
|
for (i=0;i<m_apEnumerators.size();i++)
|
|
{
|
|
CEnumeratorManager* pEnumMgr = m_apEnumerators[i];
|
|
if (pEnumMgr)
|
|
{
|
|
pEnumMgr->AddRef();
|
|
ppEnumMang[j] = pEnumMgr;
|
|
j++;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
for (i=0;i<j;i++)
|
|
{
|
|
dwStatus = ppEnumMang[i]->Refresh(dwRefreshId);
|
|
if (FAILED(dwStatus))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (i=0;i<j;i++)
|
|
{
|
|
ppEnumMang[i]->Release();
|
|
}
|
|
|
|
return dwStatus;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
//
|
|
//
|
|
// CEnumeratorManager
|
|
//
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
CEnumeratorManager::CEnumeratorManager( LPCWSTR wszCookingClass,
|
|
IWbemClassObject* pCookedClass,
|
|
IWbemClassObject* pRawClass,
|
|
IWbemHiPerfEnum* pCookedEnum,
|
|
IWbemHiPerfEnum* pRawEnum,
|
|
long lRawID )
|
|
: m_pCookedClass( pCookedClass ),
|
|
m_pRawEnum(pRawEnum),
|
|
m_pCookedEnum( pCookedEnum ),
|
|
m_pCooker(NULL),
|
|
m_lRawID(lRawID),
|
|
m_dwSignature('mMnE'),
|
|
m_cRef(1), //-------------- initial refcount
|
|
m_dwVector(0),
|
|
m_wszCookingClassName(NULL)
|
|
{
|
|
size_t length = wcslen( wszCookingClass ) + 1;
|
|
m_wszCookingClassName = new WCHAR[ length];
|
|
|
|
if ( NULL != m_wszCookingClassName )
|
|
StringCchCopyW( m_wszCookingClassName, length, wszCookingClass );
|
|
|
|
_DBG_ASSERT(m_pCookedClass);
|
|
m_pCookedClass->AddRef();
|
|
|
|
if ( NULL != m_pRawEnum )
|
|
m_pRawEnum->AddRef();
|
|
|
|
if ( NULL != m_pCookedEnum )
|
|
m_pCookedEnum->AddRef();
|
|
|
|
_DBG_ASSERT(pRawClass);
|
|
|
|
m_IsSingleton = IsSingleton(pRawClass);
|
|
|
|
m_InithRes = Initialize( pRawClass );
|
|
}
|
|
|
|
CEnumeratorManager::~CEnumeratorManager()
|
|
{
|
|
m_dwSignature = 'gmne';
|
|
|
|
delete m_wszCookingClassName;
|
|
|
|
// one reference is held by the CWMISimpleObjectCooker
|
|
if (m_pCookedClass ) m_pCookedClass->Release();
|
|
if (m_pRawEnum) m_pRawEnum->Release();
|
|
if (m_pCookedEnum) m_pCookedEnum->Release();
|
|
|
|
delete m_pCooker;
|
|
|
|
#ifdef _VERBOSE
|
|
DbgPrintfA(0,"~CEnumeratorManager %08x\n",this);
|
|
#endif
|
|
}
|
|
|
|
LONG CEnumeratorManager::AddRef()
|
|
{
|
|
return InterlockedIncrement(&m_cRef);
|
|
}
|
|
|
|
LONG CEnumeratorManager::Release()
|
|
{
|
|
LONG lRet = InterlockedDecrement(&m_cRef);
|
|
if (lRet == 0) delete this;
|
|
return lRet;
|
|
}
|
|
|
|
//
|
|
// called from the constructor
|
|
//
|
|
WMISTATUS CEnumeratorManager::Initialize( IWbemClassObject* pRawClass )
|
|
{
|
|
WMISTATUS dwStatus;
|
|
HRESULT hr1,hr2;
|
|
|
|
|
|
IWbemObjectAccess* pCookedAccess = NULL;
|
|
IWbemObjectAccess* pRawAccess = NULL;
|
|
|
|
hr1 = m_pCookedClass->QueryInterface( IID_IWbemObjectAccess, (void**)&pCookedAccess );
|
|
CReleaseMe arCookedAccess( pCookedAccess );
|
|
|
|
hr2 = pRawClass->QueryInterface( IID_IWbemObjectAccess, (void**)&pRawAccess );
|
|
CReleaseMe arRawAccess( pRawAccess );
|
|
|
|
if (SUCCEEDED(hr1) && SUCCEEDED(hr2))
|
|
{
|
|
m_pCooker = new CWMISimpleObjectCooker( m_wszCookingClassName,
|
|
pCookedAccess, // acquired by CWMISimpleObjectCooker
|
|
pRawAccess );
|
|
}
|
|
|
|
if (m_pCooker == NULL)
|
|
{
|
|
dwStatus = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
else
|
|
{
|
|
dwStatus = m_pCooker->GetLastHR();
|
|
}
|
|
|
|
return dwStatus;
|
|
}
|
|
|
|
|
|
//
|
|
// returns an hash-ed value of the __RELPATH in a ULONG_PTR with the lower bit stripped
|
|
// the lower bit is used to flag the entry when updating the enumerators
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
ULONG_PTR hash_string (WCHAR * pKey)
|
|
{
|
|
ULONG_PTR acc = 0;
|
|
ULONG_PTR i = 0;
|
|
WCHAR *this_char = pKey;
|
|
|
|
while (*this_char != NULL) {
|
|
acc ^= *(this_char++) << i;
|
|
i = (i + 1) % sizeof (void *);
|
|
}
|
|
|
|
return (acc<<1); // so we can save the LOWEST bit
|
|
}
|
|
|
|
//
|
|
// this function simply fills out an array of pointers to IWbemObejctAccess
|
|
// obtaining them from the RAW-Enumerator
|
|
// it also builds an array with hashes of the __RELPATHs of the instances
|
|
//
|
|
///////////////////////////////////////////////////////////////
|
|
WMISTATUS
|
|
CEnumeratorManager::GetRawEnumObjects(std::vector<IWbemObjectAccess*, wbem_allocator<IWbemObjectAccess*> > & refArray,
|
|
std::vector<ULONG_PTR, wbem_allocator<ULONG_PTR> > & refObjHashKeys)
|
|
{
|
|
WMISTATUS dwStatus = WBEM_NO_ERROR;
|
|
|
|
DWORD dwRet = 0,
|
|
dwNumRawObjects = 0;
|
|
|
|
IWbemObjectAccess** apObjAccess = NULL;
|
|
|
|
dwStatus = m_pRawEnum->GetObjects( 0L, 0, apObjAccess, &dwRet);
|
|
|
|
if ( WBEM_E_BUFFER_TOO_SMALL == dwStatus )
|
|
{
|
|
// Set the buffer size
|
|
// ===================
|
|
dwNumRawObjects = dwRet;
|
|
|
|
wmilib::auto_buffer<IWbemObjectAccess*> apObjAccess( new IWbemObjectAccess*[dwNumRawObjects]);
|
|
if ( NULL != apObjAccess.get() )
|
|
{
|
|
memset( apObjAccess.get(), 0, dwNumRawObjects * sizeof(IWbemObjectAccess*));
|
|
dwStatus = m_pRawEnum->GetObjects( 0L, dwNumRawObjects, (IWbemObjectAccess **)apObjAccess.get(), &dwRet );
|
|
}
|
|
else
|
|
{
|
|
dwStatus = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
|
|
if ( SUCCEEDED( dwStatus ) )
|
|
{
|
|
try
|
|
{
|
|
refArray.reserve(dwNumRawObjects);
|
|
refObjHashKeys.reserve(dwNumRawObjects);
|
|
}
|
|
catch (...)
|
|
{
|
|
dwStatus = WBEM_E_OUT_OF_MEMORY;
|
|
dwNumRawObjects = 0;
|
|
}
|
|
|
|
for (DWORD i=0;i<dwNumRawObjects;i++)
|
|
{
|
|
HRESULT hr1;
|
|
_variant_t VarKey; // does not throw, just container
|
|
hr1 = apObjAccess[i]->Get(L"__RELPATH",0,&VarKey,NULL,NULL);
|
|
if (SUCCEEDED(hr1))
|
|
{
|
|
DWORD Hash = hash_string(VarKey.bstrVal);
|
|
refObjHashKeys.push_back(Hash);
|
|
refArray.push_back(apObjAccess[i]);
|
|
}
|
|
else
|
|
{
|
|
// if we cannot give out the ownership of a pointer, release
|
|
apObjAccess[i]->Release();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return dwStatus;
|
|
}
|
|
|
|
//
|
|
// the problem that UpdateEnums and Refresh are trying to solve is the following:
|
|
// The Cooked enumerator needs 2 Raw values for calculating 1 value.
|
|
// the 2 values comes from two distinc enumeration
|
|
// the 2 distinct enumeration can give a different resultset
|
|
// OLD: A B C D E
|
|
// NEW: B C E F G
|
|
// we are adding to the "cooking cache" only the new objects,
|
|
// and we are removing the old ones
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
WMISTATUS
|
|
CEnumeratorManager::UpdateEnums(
|
|
/*out*/ std::vector<ULONG_PTR, wbem_allocator<ULONG_PTR> > & apObjKeyHash)
|
|
{
|
|
// cyclic logic:
|
|
// we have a 'circular array' of std::vector
|
|
// and the m_dwVector is the index
|
|
// circular increment of the index will decide
|
|
// who is the New and who is the Old
|
|
std::vector<ULONG_PTR, wbem_allocator<ULONG_PTR> > & Old = m_Delta[m_dwVector];
|
|
m_dwVector = (m_dwVector+1)%2;
|
|
m_Delta[m_dwVector].clear();
|
|
m_Delta[m_dwVector] = apObjKeyHash;
|
|
std::vector<ULONG_PTR, wbem_allocator<ULONG_PTR> > & New = m_Delta[m_dwVector];
|
|
|
|
DWORD j,k;
|
|
|
|
for (j=0;j<New.size();j++)
|
|
{
|
|
BOOL bFound = FALSE;
|
|
for (k=0;k<Old.size();k++)
|
|
{
|
|
if (Old[k] == New[j])
|
|
{
|
|
Old[k] |= 1;
|
|
bFound = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if (!bFound)
|
|
{
|
|
New[j] |= 1; // ad the very NEW bit
|
|
}
|
|
}
|
|
|
|
return WBEM_S_NO_ERROR;
|
|
|
|
}
|
|
|
|
WMISTATUS CEnumeratorManager::Refresh( DWORD dwRefreshStamp )
|
|
{
|
|
WMISTATUS dwStatus = WBEM_NO_ERROR;
|
|
|
|
std::vector<IWbemObjectAccess*, wbem_allocator<IWbemObjectAccess*> > apObjAccess;
|
|
std::vector<ULONG_PTR, wbem_allocator<ULONG_PTR> > apObjHashKeys;
|
|
|
|
dwStatus = GetRawEnumObjects( apObjAccess, apObjHashKeys );
|
|
|
|
// calculate the Delta of the caches
|
|
if (SUCCEEDED(dwStatus))
|
|
{
|
|
dwStatus = UpdateEnums(apObjHashKeys);
|
|
}
|
|
|
|
std::vector<ULONG_PTR, wbem_allocator<ULONG_PTR> > & New = m_Delta[m_dwVector];
|
|
std::vector<ULONG_PTR, wbem_allocator<ULONG_PTR> > & Old = m_Delta[(m_dwVector-1)%2];
|
|
|
|
{
|
|
CInCritSec ics(&m_cs);
|
|
|
|
// Merge into the cache
|
|
if ( SUCCEEDED(dwStatus) )
|
|
{
|
|
//
|
|
// Elements in the New array with the bit set are really new
|
|
//
|
|
DWORD j;
|
|
for (j=0; j< New.size(); j++)
|
|
{
|
|
if (New[j] & 1) // test the very new BIT
|
|
{
|
|
EnumCookId thisEnumCookId;
|
|
dwStatus = InsertCookingRecord( apObjAccess[j], &thisEnumCookId, dwRefreshStamp );
|
|
if (SUCCEEDED(dwStatus))
|
|
{
|
|
try
|
|
{
|
|
m_mapID[New[j]] = thisEnumCookId;
|
|
}
|
|
catch (...)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
//remove the bit
|
|
New[j] &= (~1);
|
|
}
|
|
}
|
|
|
|
for (j=0; j<Old.size(); j++)
|
|
{
|
|
if (Old[j] & 1)
|
|
{
|
|
Old[j] &= (~1); // remove the ALREADY_THERE bit
|
|
}
|
|
else
|
|
{
|
|
EnumCookId thisEnumCookId;
|
|
thisEnumCookId = m_mapID[Old[j]];
|
|
m_mapID.erase(Old[j]);
|
|
RemoveCookingRecord(&thisEnumCookId);
|
|
}
|
|
}
|
|
m_pCooker->Recalc(dwRefreshStamp);
|
|
}
|
|
|
|
}
|
|
|
|
// in any case ....
|
|
for (DWORD i=0;i<apObjAccess.size();i++)
|
|
{
|
|
apObjAccess[i]->Release();
|
|
};
|
|
|
|
|
|
return dwStatus;
|
|
}
|
|
|
|
WMISTATUS
|
|
CEnumeratorManager::InsertCookingRecord(
|
|
IWbemObjectAccess* pRawObject,
|
|
EnumCookId * pEnumCookId,
|
|
DWORD dwRefreshStamp)
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
//
|
|
//
|
|
// Parameters:
|
|
//
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
{
|
|
WMISTATUS dwStatus = WBEM_NO_ERROR;
|
|
|
|
if (!pRawObject || !pEnumCookId)
|
|
{
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
IWbemObjectAccess* pCookedObject = NULL;
|
|
|
|
long lID = 0;
|
|
|
|
dwStatus = CreateCookingObject( pRawObject, &pCookedObject );
|
|
CReleaseMe rm1(pCookedObject);
|
|
|
|
if ( SUCCEEDED( dwStatus ) )
|
|
{
|
|
dwStatus = m_pCooker->SetCookedInstance( pCookedObject, &lID );
|
|
|
|
if ( SUCCEEDED( dwStatus ) )
|
|
{
|
|
dwStatus = m_pCooker->BeginCooking( lID, pRawObject,dwRefreshStamp);
|
|
}
|
|
}
|
|
|
|
if ( SUCCEEDED( dwStatus ) )
|
|
{
|
|
DWORD dwTarget;
|
|
long EnumId = lID;
|
|
|
|
dwStatus = m_pCookedEnum->AddObjects( 0L, 1, &EnumId, &pCookedObject );
|
|
if (SUCCEEDED(dwStatus))
|
|
{
|
|
pEnumCookId->CookId = lID;
|
|
pEnumCookId->EnumId = EnumId;
|
|
m_dwUsage++;
|
|
}
|
|
else
|
|
{
|
|
pEnumCookId->CookId = 0;
|
|
pEnumCookId->EnumId = 0;
|
|
}
|
|
}
|
|
|
|
return dwStatus;
|
|
}
|
|
|
|
|
|
|
|
|
|
WMISTATUS CEnumeratorManager::CreateCookingObject(
|
|
IWbemObjectAccess* pRawObject,
|
|
IWbemObjectAccess** ppCookedObject )
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Create a new instance of the cooked object and set the key(s) based on the
|
|
// raw object's key(s) value.
|
|
//
|
|
// Parameters:
|
|
//
|
|
// pRawObject - The new object's corresponding raw object
|
|
// ppCookedObject - The new cooked object
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
{
|
|
|
|
HRESULT hr = WBEM_E_FAILED;
|
|
IWbemClassObject * pCookedInst = NULL;
|
|
|
|
hr = m_pCookedClass->SpawnInstance(0,&pCookedInst);
|
|
CReleaseMe rm1(pCookedInst);
|
|
|
|
if (SUCCEEDED(hr) &&
|
|
!m_IsSingleton)
|
|
{
|
|
|
|
// get the 'list' of all the key property
|
|
// if you haven't got it in the past
|
|
if (m_pKeyProps.size() == 0)
|
|
{
|
|
hr = pRawObject->BeginEnumeration(WBEM_FLAG_KEYS_ONLY);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
BSTR bstrName;
|
|
|
|
while(WBEM_S_NO_ERROR == pRawObject->Next(0,&bstrName,NULL,NULL,NULL))
|
|
{
|
|
try
|
|
{
|
|
m_pKeyProps.push_back(bstrName);
|
|
}
|
|
catch (...)
|
|
{
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
};
|
|
SysFreeString(bstrName);
|
|
};
|
|
|
|
pRawObject->EndEnumeration();
|
|
}
|
|
}
|
|
|
|
// copy all the key properties from the Raw to the cooked instance
|
|
if (m_pKeyProps.size() > 0 && SUCCEEDED(hr))
|
|
{
|
|
for(int i=0;i<m_pKeyProps.size();i++)
|
|
{
|
|
// does not thorow, just a container
|
|
_variant_t VarVal;
|
|
CIMTYPE ct;
|
|
hr = pRawObject->Get(m_pKeyProps[i],0,&VarVal,&ct,NULL);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pCookedInst->Put(m_pKeyProps[i],0,&VarVal,0);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
VarVal.Clear();
|
|
}
|
|
} else {
|
|
|
|
hr = WBEM_E_INVALID_CLASS;
|
|
|
|
}
|
|
};
|
|
|
|
if (SUCCEEDED(hr)){
|
|
hr = pCookedInst->QueryInterface( IID_IWbemObjectAccess, (void**)ppCookedObject );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
WMISTATUS CEnumeratorManager::RemoveCookingRecord( EnumCookId * pEnumCookID )
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
//
|
|
//
|
|
// Parameters:
|
|
//
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
{
|
|
if (!pEnumCookID)
|
|
{
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
WMISTATUS dwStatus = WBEM_NO_ERROR;
|
|
|
|
dwStatus = m_pCookedEnum->RemoveObjects( 0L, 1, &pEnumCookID->EnumId );
|
|
|
|
m_pCooker->StopCooking(pEnumCookID->CookId);
|
|
m_pCooker->Remove(pEnumCookID->CookId);
|
|
|
|
--m_dwUsage;
|
|
|
|
return dwStatus;
|
|
}
|
|
|