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.
 
 
 
 
 
 

633 lines
18 KiB

/*++
Copyright (C) 1996-2001 Microsoft Corporation
Module Name:
Abstract:
History:
--*/
// WMIObjCooker.cpp
#include "precomp.h"
#include "WMIObjCooker.h"
#include "RawCooker.h"
#include <comdef.h>
#include <autoptr.h>
//
//
// Assumes pProp validated before entering
//
///////////////////////////////////////////////////////////////////////////////
WMISTATUS GetPropValue( CProperty* pProp, IWbemObjectAccess* pInstance, __int64 & nResult )
{
_DBG_ASSERT(pProp);
WMISTATUS dwStatus = WBEM_NO_ERROR;
DWORD dwRes = 0;
switch( pProp->GetType() )
{
case CIM_UINT32:
{
dwStatus = pInstance->ReadDWORD( pProp->GetHandle(), &dwRes );
nResult = dwRes;
}break;
case CIM_UINT64:
{
dwStatus = pInstance->ReadQWORD( pProp->GetHandle(), (unsigned __int64*)&nResult );
}break;
default:
dwStatus = WBEM_E_TYPE_MISMATCH;
}
return dwStatus;
}
//////////////////////////////////////////////////////////////
//
// CWMISimpleObjectCooker
//
//////////////////////////////////////////////////////////////
CWMISimpleObjectCooker::CWMISimpleObjectCooker( WCHAR* wszCookingClassName,
IWbemObjectAccess* pCookingClass,
IWbemObjectAccess* pRawClass,
IWbemServices * pNamespace ) :
m_lRef( 1 ),
m_pCookingClass( NULL ),
m_wszClassName(NULL),
m_pNamespace(NULL),
m_dwPropertyCacheSize( 16 ),
m_dwNumProperties( 0 ),
m_NumInst(0),
m_InitHR(WBEM_E_INITIALIZATION_FAILURE)
{
#ifdef _VERBOSE
DbgPrintfA(0,"+ Cooker %p\n",this);
#endif
if (pNamespace)
{
m_pNamespace = pNamespace;
m_pNamespace->AddRef();
}
m_InitHR = SetClass( wszCookingClassName, pCookingClass, pRawClass );
if (m_pNamespace)
{
m_pNamespace->Release();
m_pNamespace = NULL;
}
}
CWMISimpleObjectCooker::~CWMISimpleObjectCooker()
{
Reset();
// Release the cooking class
if ( m_pCookingClass ) m_pCookingClass->Release();
if (m_pNamespace) m_pNamespace->Release();
// Delete the property cache
for (DWORD i=0;i<m_apPropertyCache.size();i++)
{
CCookingProperty* pCookProp = m_apPropertyCache[i];
delete pCookProp;
}
delete [] m_wszClassName;
#ifdef _VERBOSE
DbgPrintfA(0,"- Cooker %p istances left %d\n",this,m_NumInst);
#endif
}
//////////////////////////////////////////////////////////////
//
// COM methods
//
//////////////////////////////////////////////////////////////
STDMETHODIMP CWMISimpleObjectCooker::QueryInterface(REFIID riid, void** ppv)
//////////////////////////////////////////////////////////////
//
// Standard QueryInterface
//
// Parameters:
// riid - the ID of the requested interface
// ppv - a pointer to the interface pointer
//
//////////////////////////////////////////////////////////////
//ok
{
if (NULL == ppv) return E_POINTER;
if(riid == IID_IUnknown)
{
*ppv = (LPVOID)(IUnknown*)(IWMISimpleCooker*)this;
}
else if(riid == IID_IWMISimpleCooker)
{
*ppv = (LPVOID)(IWMISimpleCooker*)this;
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
((IUnknown*)*ppv)->AddRef();
return S_OK;
}
STDMETHODIMP_(ULONG) CWMISimpleObjectCooker::AddRef()
{
return InterlockedIncrement(&m_lRef);
}
STDMETHODIMP_(ULONG) CWMISimpleObjectCooker::Release()
{
long lRef = InterlockedDecrement(&m_lRef);
if(lRef == 0) delete this;
return lRef;
}
STDMETHODIMP CWMISimpleObjectCooker::SetClass(
/*[in] */ WCHAR* wszCookingClassName,
/*[in] */ IWbemObjectAccess *pCookingClassAccess,
/*[in] */ IWbemObjectAccess *pRawClass )
{
HRESULT hResult = S_OK;
IWbemClassObject * pClass = NULL;
// Cannot override the original cooking class for now
// ==================================================
if ( ( NULL != m_pCookingClass ) || ( NULL == pCookingClassAccess ) )
hResult = E_FAIL;
// what we put here MUST be a class, Singletons are OK
// if we have an instance, we need to ask WinMgmt for a class
if (m_pNamespace)
{
_variant_t VarGenus;
hResult = pCookingClassAccess->Get(L"__GENUS",0,&VarGenus,NULL,NULL);
if (SUCCEEDED(hResult))
{
if ((CIM_SINT32 == V_VT(&VarGenus)) &&
WBEM_GENUS_CLASS == V_I4(&VarGenus))
{
}
else
{
BSTR BstrName = SysAllocString(wszCookingClassName);
if (BstrName)
{
CSysFreeMe sfm(BstrName);
m_pNamespace->GetObject(BstrName,0,NULL,&pClass,NULL);
}
else
{
hResult = WBEM_E_OUT_OF_MEMORY;
}
}
}
}
IWbemClassObject * pCookingClassAccess2;
pCookingClassAccess2 = (pClass)?pClass:pCookingClassAccess;
// Verify and process the cooking class
// ====================================
if ( SUCCEEDED( hResult ) )
{
BOOL bRet;
bRet = IsCookingClass( pCookingClassAccess );
if ( bRet )
{
// Save the class
m_pCookingClass = pCookingClassAccess;
m_pCookingClass->AddRef();
}
else
{
hResult = WBEM_E_INVALID_CLASS;
}
// Set the class name
if ( SUCCEEDED( hResult ) )
{
size_t length = wcslen( wszCookingClassName ) + 1;
m_wszClassName = new WCHAR[ length ];
if (m_wszClassName)
StringCchPrintfW( m_wszClassName, length, wszCookingClassName );
else
hResult = WBEM_E_OUT_OF_MEMORY;
}
// Initialize the cooking properties
if ( SUCCEEDED( hResult ) )
{
hResult = SetProperties( pCookingClassAccess2, pRawClass );
}
}
if (pClass)
{
pClass->Release();
}
return hResult;
}
WMISTATUS CWMISimpleObjectCooker::SetProperties( IWbemClassObject* pCookingClassObject, IWbemObjectAccess *pRawClass )
{
WMISTATUS dwStatus = WBEM_NO_ERROR;
BSTR strPropName = NULL;
long lHandle = 0;
CIMTYPE ct;
BOOL bAtLeastOne = FALSE;
IWbemObjectAccess * pCookingClassAccess = NULL;
dwStatus = pCookingClassObject->QueryInterface(IID_IWbemObjectAccess ,(void **)&pCookingClassAccess);
if (FAILED(dwStatus)) return dwStatus;
CReleaseMe rm(pCookingClassAccess );
// get only once the qualifier set
IWbemQualifierSet* pCookingClassQSet = NULL;
dwStatus = pCookingClassObject->GetQualifierSet(&pCookingClassQSet);
if (FAILED(dwStatus)) return dwStatus;
CReleaseMe rm1(pCookingClassQSet);
//
// should we be using [TimeStamp|Frequency]_[Time|Sys100ns|Object] ?
//
BOOL bUseWellKnownIfNeeded = FALSE;
dwStatus = pCookingClassQSet->Get(WMI_COOKER_AUTOCOOK_RAWDEFAULT,0,NULL,NULL);
// we have already verified version and property, just test if it's there
if ( SUCCEEDED(dwStatus) )
{
bUseWellKnownIfNeeded = TRUE;
}
else // do not propagate this error
{
dwStatus = WBEM_NO_ERROR;
}
// Enumerate and save the autocook properties
// ==========================================
pCookingClassObject->BeginEnumeration( WBEM_FLAG_NONSYSTEM_ONLY );
while ( WBEM_S_NO_ERROR == pCookingClassObject->Next(0,&strPropName,NULL,&ct,NULL) &&
SUCCEEDED(dwStatus))
{
CSysFreeMe afPropName( strPropName );
DWORD dwCounterType = 0;
DWORD dwReqProp = 0;
// Determine if it is an autocook property
// =======================================
if ( IsCookingProperty( strPropName, pCookingClassObject, &dwCounterType, &dwReqProp ) )
{
m_dwNumProperties++;
// The property is an autocook; save the Name, ObjectAccess handle, type and cooking object
// ========================================================================================
dwStatus = pCookingClassAccess->GetPropertyHandle( strPropName, &ct, &lHandle );
if ( SUCCEEDED( dwStatus ) )
{
#ifdef _VERBOSE
DbgPrintfA(0,"%S %08x %08x\n",strPropName,dwCounterType,dwReqProp);
#endif
CCookingProperty* pProperty = new CCookingProperty( strPropName,
dwCounterType,
lHandle,
ct,
dwReqProp,
bUseWellKnownIfNeeded);
if (NULL == pProperty)
{
dwStatus = WBEM_E_OUT_OF_MEMORY;
continue;
}
// Initialize the property object
// ==============================
IWbemQualifierSet* pCookingPropQualifierSet = NULL;
dwStatus = pCookingClassObject->GetPropertyQualifierSet( strPropName, &pCookingPropQualifierSet );
CReleaseMe arQualifierSet( pCookingPropQualifierSet );
if ( SUCCEEDED( dwStatus ) )
{
dwStatus = pProperty->Initialize( pCookingPropQualifierSet, pRawClass, pCookingClassQSet );
}
// If everything worked out then add the property to the cache
// ===========================================================
if ( SUCCEEDED( dwStatus ) )
{
try
{
m_apPropertyCache.push_back(pProperty);
bAtLeastOne = TRUE;
}
catch (...)
{
dwStatus = WBEM_E_OUT_OF_MEMORY;
}
}
if (FAILED(dwStatus)) // the std::vector did not get the ownership of the CCookingPropery
{
delete pProperty;
}
}
}
}
pCookingClassObject->EndEnumeration();
if (!bAtLeastOne && (SUCCEEDED(dwStatus)))
{
dwStatus = WBEM_E_INVALID_CLASS;
}
return dwStatus;
}
STDMETHODIMP CWMISimpleObjectCooker::SetCookedInstance(
/*[in] */ IWbemObjectAccess *pCookedInstance,
/*[out] */ long *plID)
{
HRESULT hResult = S_OK;
wmilib::auto_ptr<CCookingInstance> pInstance(new CCookingInstance( pCookedInstance, m_apPropertyCache.size() ));
if ((NULL == pInstance.get()) || !pInstance->IsValid()) return WBEM_E_OUT_OF_MEMORY;
for ( DWORD dwProp = 0; dwProp < m_apPropertyCache.size() && SUCCEEDED(hResult); dwProp++ )
{
CCookingProperty* pProp = m_apPropertyCache[dwProp];
hResult = pInstance->InitProperty( dwProp, pProp->NumberOfActiveSamples(), pProp->MinSamplesRequired() );
}
if (FAILED(hResult)) return hResult;
// Add new cooked instance
hResult = m_InstanceCache.Add( (DWORD *)plID, pInstance.get() );
if (FAILED(hResult)) return hResult;
pInstance.release(); // the cache got the ownership
m_NumInst++;
return hResult;
}
STDMETHODIMP CWMISimpleObjectCooker::BeginCooking(
/*[in] */ long lId,
/*[in] */ IWbemObjectAccess *pSampleInstance,
/*[in] */ DWORD dwRefreshStamp)
{
HRESULT hResult = S_OK;
CCookingInstance* pCookedInstance = NULL;
// Add an initial sample to the cache
// ==================================
hResult = m_InstanceCache.GetData( lId, &pCookedInstance );
if ( SUCCEEDED( hResult ) )
{
if ( NULL != pCookedInstance )
{
hResult = pCookedInstance->SetRawSourceInstance( pSampleInstance );
if ( SUCCEEDED( hResult ) )
{
hResult = UpdateSamples( pCookedInstance, dwRefreshStamp );
}
}
else
{
hResult = E_FAIL;
}
}
return hResult;
}
STDMETHODIMP CWMISimpleObjectCooker::StopCooking(
/*[in] */ long lId)
{
HRESULT hResult = S_OK;
// just test for existence pInstance is a pointer to data still kept by the Cache
CCookingInstance* pInstance = NULL;
hResult = m_InstanceCache.GetData( lId, &pInstance );
return hResult;
}
STDMETHODIMP CWMISimpleObjectCooker::Recalc(DWORD dwRefreshStamp)
{
HRESULT hResult = S_OK;
CCookingInstance* pInstance = NULL;
// Cook all of the instances which have a cached sample
// ====================================================
m_InstanceCache.BeginEnum();
OnDeleteObj0<IdCache<CCookingInstance *>,
HRESULT (IdCache<CCookingInstance *>:: *)(void),
&IdCache<CCookingInstance *>::EndEnum> cEndEnum(&m_InstanceCache);
DWORD i=0;
while ( S_OK == m_InstanceCache.Next( &pInstance ) )
{
if ( pInstance )
{
hResult = CookInstance( pInstance, dwRefreshStamp );
#ifdef _VERBOSE
DbgPrintfA(0,"%S %p %d\n",pInstance->GetKey(),pInstance,i++);
#endif
}
}
return hResult;
}
STDMETHODIMP CWMISimpleObjectCooker::Remove(
/*[in] */ long lId)
{
HRESULT hResult = S_OK;
// Remove the specified instance from the cache
CCookingInstance * pInst = NULL;
hResult = m_InstanceCache.Remove( lId, &pInst );
if (pInst)
{
delete pInst;
m_NumInst--;
}
return hResult;
}
STDMETHODIMP CWMISimpleObjectCooker::Reset()
{
HRESULT hResult = S_OK;
// Remove all of the instances from the cache
// ==========================================
CCookingInstance * pInstance = NULL;
m_InstanceCache.BeginEnum();
while ( S_OK == m_InstanceCache.Next( &pInstance ) )
{
if (pInstance)
{
delete pInstance;
m_NumInst--;
pInstance = NULL;
}
}
m_InstanceCache.EndEnum();
hResult = m_InstanceCache.RemoveAll();
return hResult;
}
WMISTATUS CWMISimpleObjectCooker::CookInstance( CCookingInstance* pInstance,
DWORD dwRefreshStamp)
{
WMISTATUS dwStatus = S_OK;
if ( SUCCEEDED( dwStatus ) )
{
dwStatus = UpdateSamples( pInstance, dwRefreshStamp );
// Loop through the cooking properties
// ===================================
for ( DWORD dwProp = 0; dwProp < m_apPropertyCache.size(); dwProp++ )
{
// Update the cooking instance property
// ====================================
pInstance->CookProperty( dwProp, m_apPropertyCache[dwProp] );
}
}
return dwStatus;
}
WMISTATUS CWMISimpleObjectCooker::UpdateSamples( CCookingInstance* pCookedInstance, DWORD dwRefreshStamp )
{
WMISTATUS dwStatus = WBEM_NO_ERROR;
IWbemObjectAccess* pRawInstance = NULL;
if ( NULL == pCookedInstance )
{
dwStatus = WBEM_E_INVALID_PARAMETER;
}
if ( SUCCEEDED( dwStatus ) )
{
dwStatus = pCookedInstance->GetRawSourceInstance( &pRawInstance );
CReleaseMe arRawInstance( pRawInstance );
if ( NULL == pRawInstance )
{
dwStatus = WBEM_E_FAILED;
}
#ifdef _VERBOSE
{
WCHAR pBuff[256];
_variant_t Var;
HRESULT hr = pRawInstance->Get(L"__RELPATH",0,&Var,NULL,NULL);
StringCchPrintfW(pBuff,256,L"%p hr %08x __RELPATH %s Key %s\n",pRawInstance,hr,V_BSTR(&Var),pCookedInstance->GetKey());
OutputDebugStringW(pBuff);
}
#endif
for ( DWORD dwProp = 0; ( SUCCEEDED( dwStatus ) ) && dwProp < m_apPropertyCache.size(); dwProp++ )
{
CCookingProperty* pProp = m_apPropertyCache[dwProp];
CProperty* pRawProp = pProp->GetRawCounterProperty();
CProperty* pBaseProp = pProp->GetBaseProperty();
CProperty* pTimeProp = pProp->GetTimeProperty();
__int64 nRawCounter = 0;
__int64 nRawBase = 0;
__int64 nTimeStamp = 0;
if (NULL == pRawProp) continue; // just go on with the other properties
dwStatus = GetPropValue( pRawProp, pRawInstance, nRawCounter );
if ( pBaseProp )
{
GetPropValue( pBaseProp, pRawInstance, nRawBase );
}
else if (pProp->IsReq(REQ_BASE))
{
nRawBase = 1;
}
if ( pTimeProp )
{
GetPropValue( pTimeProp, pRawInstance, nTimeStamp );
}
else if (pProp->IsReq(REQ_TIME))
{
LARGE_INTEGER li;
QueryPerformanceCounter(&li);
nTimeStamp = li.QuadPart;
}
dwStatus = pCookedInstance->AddSample( dwRefreshStamp, dwProp, nRawCounter, nRawBase, nTimeStamp );
#ifdef _VERBOSE
DbgPrintfA(0,"Prop %d status %08x\n"
" counter %I64u base %I64u time %I64u\n",
dwProp, dwStatus, nRawCounter, nRawBase, nTimeStamp);
#endif
}
}
return dwStatus;
}