Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

499 lines
14 KiB

/*++
Copyright (C) 1998-2001 Microsoft Corporation
Module Name:
Abstract:
History:
--*/
//////////////////////////////////////////////////////////////////////
//
// HiPerfProv.cpp
//
//
//
//////////////////////////////////////////////////////////////////////
#include "precomp.h"
#include <stdio.h>
#include <wbemidl.h>
#include <wbemint.h>
#include "common.h"
#include "HiPerProv.h"
///////////////////////////////////////////////////////////////////
//
// CHiPerfProvider
//
///////////////////////////////////////////////////////////////////
CHiPerfProvider::CHiPerfProvider(CLifeControl *pControl) :
CUnk(pControl), m_XProviderInit(this), m_XHiPerfProvider(this), m_XRefresher(this)
//ok
{
LOG("CHiPerfProvider::CHiPerfProvider");
// Initialize internal instance cache to empty
for (int i = 0; i < NUM_SAMPLE_INSTANCES; i++)
m_aInstances[i] = 0;
// Initialize property value handles to zero
m_hName = 0;
}
CHiPerfProvider::~CHiPerfProvider()
//ok
{
LOG("CHiPerfProvider::~CHiPerfProvider");
// Release all the objects which have been added to the array.
for (int i = 0; i < NUM_SAMPLE_INSTANCES; i++)
{
if (m_aInstances[i])
m_aInstances[i]->Release();
}
}
void* CHiPerfProvider::GetInterface(REFIID riid)
//ok
{
if(riid == IID_IWbemProviderInit)
return &m_XProviderInit;
if (riid == IID_IWbemHiPerfProvider)
return &m_XHiPerfProvider;
if (riid == IID_IUnknown)
return &m_XHiPerfProvider;
return NULL;
}
///////////////////////////////////////////////////////////////////
//
// COM implementations
//
///////////////////////////////////////////////////////////////////
HRESULT CHiPerfProvider::SetHandles(IWbemClassObject* pSampleClass)
//ok
{
LOG("CHiPerfProvider::SetHandles");
// Get the property handles for the well-known properties in
// this counter type. These property handles are available
// to all nested classes of HiPerfProvider
IWbemObjectAccess *pAccess;
LONG hName = 0;
HRESULT hRes = 0;
BSTR PropName = 0;
hRes = pSampleClass->QueryInterface(IID_IWbemObjectAccess, (LPVOID *)&pAccess);
if (FAILED(hRes))
{
LOGERROR("Could not retrieve the IWbemObjectAccess object");
return hRes;
}
// Name handle
PropName = SysAllocString(L"Name");
hRes = pAccess->GetPropertyHandle(PropName, 0, &hName);
if (FAILED(hRes))
{
LOGERROR("Could not get access handle for Name property");
pAccess->Release();
return hRes;
}
m_hName = hName;
SysFreeString(PropName);
pAccess->Release();
return WBEM_NO_ERROR;
}
STDMETHODIMP CHiPerfProvider::XProviderInit::Initialize(
/* [unique][in] */ LPWSTR wszUser,
/* [in] */ LONG lFlags,
/* [in] */ LPWSTR wszNamespace,
/* [unique][in] */ LPWSTR wszLocale,
/* [in] */ IWbemServices __RPC_FAR *pNamespace,
/* [in] */ IWbemContext __RPC_FAR *pCtx,
/* [in] */ IWbemProviderInitSink __RPC_FAR *pInitSink)
//ok
{
LOG("CHiPerfProvider::XProviderInit::Initialize");
IWbemClassObject *pSampleClass = 0;
IWbemObjectAccess *pAccess = 0;
// Get a copy of our sample class def so that we can create & maintain
// instances of it.
BSTR bstrObject = SysAllocString(SAMPLE_CLASS);
HRESULT hRes = pNamespace->GetObject(bstrObject, 0, pCtx, &pSampleClass, 0);
SysFreeString(bstrObject);
if (FAILED(hRes))
{
LOGERROR("Could not create a sample object");
return hRes;
}
hRes = m_pObject->SetHandles(pSampleClass);
if (FAILED(hRes))
{
pSampleClass->Release();
return hRes;
}
// Precreate 10 instances, and set them up in an array which
// is a member of this C++ class.
//
// We only store the IWbemObjectAccess pointers, since
// we are updating 'well-known' properties and already
// know their names.
for (int i = 0; i < NUM_SAMPLE_INSTANCES; i++)
{
IWbemClassObject *pInst = 0;
hRes = pSampleClass->SpawnInstance(0, &pInst);
if (FAILED(hRes))
{
LOGERROR("Could not spawn an instance of the sample class");
pSampleClass->Release();
return hRes;
}
// Get the IWbemObjectAccess interface and cache it
pInst->QueryInterface(IID_IWbemObjectAccess, (LPVOID *)&pAccess);
pInst->Release();
// Set the instance's name.
WCHAR wcsName[128];
swprintf(wcsName, L"Inst_%d", i);
hRes = pAccess->WritePropertyValue(m_pObject->m_hName, (wcslen(wcsName)+1)*sizeof(wchar_t), (BYTE*)wcsName);
if (FAILED(hRes))
{
LOGERROR("Failed to set name of sample class");
pSampleClass->Release();
pAccess->Release();
return hRes;
}
// Add to the instance array
m_pObject->m_aInstances[i] = pAccess;
}
// We now have all the instances ready to go and all the
// property handles cached. Tell WINMGMT that we're
// ready to start 'providing'.
pInitSink->SetStatus(WBEM_S_INITIALIZED, 0);
pSampleClass->Release();
return NO_ERROR;
}
STDMETHODIMP CHiPerfProvider::XHiPerfProvider::QueryInstances(
/* [in] */ IWbemServices __RPC_FAR *pNamespace,
/* [string][in] */ WCHAR __RPC_FAR *wszClass,
/* [in] */ long lFlags,
/* [in] */ IWbemContext __RPC_FAR *pCtx,
/* [in] */ IWbemObjectSink __RPC_FAR *pSink )
//ok
{
LOG("CHiPerfProvider::XHiPerfProvider::QueryInstances");
HRESULT hRes;
if (pNamespace == 0 || wszClass == 0 || pSink == 0)
return WBEM_E_INVALID_PARAMETER;
for (int i = 0; i < NUM_SAMPLE_INSTANCES; i++)
{
IWbemObjectAccess *pAccess = m_pObject->m_aInstances[i];
// Every object can be access one of two ways. In this case
// we get the 'other' (primary) interface to this same object.
IWbemClassObject *pOtherFormat = 0;
hRes = pAccess->QueryInterface(IID_IWbemClassObject, (LPVOID *) &pOtherFormat);
if (FAILED(hRes))
{
LOGERROR("Could not obtain the IWbemClassObject interface");
return hRes;
}
// Send a copy back to the caller.
pSink->Indicate(1, &pOtherFormat);
pOtherFormat->Release(); // Don't need this any more
}
// Tell WINMGMT we are all finished supplying objects.
pSink->SetStatus(0, WBEM_NO_ERROR, 0, 0);
return NO_ERROR;
}
STDMETHODIMP CHiPerfProvider::XHiPerfProvider::CreateRefresher(
/* [in] */ IWbemServices __RPC_FAR *pNamespace,
/* [in] */ long lFlags,
/* [out] */ IWbemRefresher __RPC_FAR *__RPC_FAR *ppRefresher )
//////////////////////////////////////////////////////////////////////
//
// Called whenever a new refresher is needed by the client.
//
// Parameters:
// <pNamespace> A pointer to the relevant namespace. Not used.
// <lFlags> Not used.
// <ppRefresher> Receives the requested refresher.
//
//////////////////////////////////////////////////////////////////////
//ok
{
LOG("CContinousProvider::XContinousProvider::CreateRefresher");
*ppRefresher = NULL;
return NO_ERROR;
}
STDMETHODIMP CHiPerfProvider::XHiPerfProvider::CreateRefreshableObject(
/* [in] */ IWbemServices __RPC_FAR *pNamespace,
/* [in] */ IWbemObjectAccess __RPC_FAR *pTemplate,
/* [in] */ IWbemRefresher __RPC_FAR *pRefresher,
/* [in] */ long lFlags,
/* [in] */ IWbemContext __RPC_FAR *pContext,
/* [out] */ IWbemObjectAccess __RPC_FAR *__RPC_FAR *ppRefreshable,
/* [out] */ long __RPC_FAR *plId )
//////////////////////////////////////////////////////////////////////
//
// Called whenever a user wants to include an object in a refresher.
//
// Parameters:
// <pNamespace> A pointer to the relevant namespace in WINMGMT.
// <pTemplate> A pointer to a copy of the object which is to be
// added. This object itself cannot be used, as
// it not owned locally.
// <pRefresher> The refresher to which to add the object.
// <lFlags> Not used.
// <pContext> Not used here.
// <ppRefreshable> A pointer to the internal object which was added
// to the refresher.
// <plId> The Object Id (for identification during removal).
//
//////////////////////////////////////////////////////////////////////
//ok
{
LOG("CHiPerfProvider::XHiPerfProvider::CreateRefreshableObject");
// Find out which object is being requested for addition.
wchar_t wcsBuf[128];
*wcsBuf = 0;
LONG lNameLength = 0;
pTemplate->ReadPropertyValue(m_pObject->m_hName, (wcslen(wcsBuf)+1)*sizeof(wchar_t), &lNameLength, LPBYTE(wcsBuf));
// Scan out the index from the instance name. We only do this
// because the instance name is a string.
DWORD dwIndex = 0;
swscanf(wcsBuf, L"Inst_%u", &dwIndex);
// Now we know which object is desired.
IWbemObjectAccess *pOurCopy = m_pObject->m_aInstances[dwIndex];
pOurCopy->ReadPropertyValue(m_pObject->m_hName, 128, &lNameLength, LPBYTE(wcsBuf));
char szbuf[256];
wcstombs(szbuf, wcsBuf, 127);
LOG(szbuf);
// The refresher being supplied by the caller is actually
// one of our own refreshers, so a simple cast is convenient
// so that we can access private members.
XRefresher *pOurRefresher;
if (pRefresher)
{
LOG ("NON-NULL refresher");
pOurRefresher = (XRefresher *) pRefresher;
}
else
{
LOG ("NULL refresher");
pOurRefresher = &m_pObject->m_XRefresher;
}
if(pOurRefresher)
pOurRefresher->AddObject(pOurCopy, plId);
// Return a copy of the internal object.
pOurCopy->AddRef();
*ppRefreshable = pOurCopy;
*plId = LONG(dwIndex);
return NO_ERROR;
}
STDMETHODIMP CHiPerfProvider::XHiPerfProvider::StopRefreshing(
/* [in] */ IWbemRefresher __RPC_FAR *pRefresher,
/* [in] */ long lId,
/* [in] */ long lFlags )
//////////////////////////////////////////////////////////////////////
//
// Called whenever a user wants to remove an object from a refresher.
//
// Parameters:
// <pRefresher> The refresher object from which we are to
// remove the perf object.
// <lId> The ID of the object.
// <lFlags> Not used.
//
//////////////////////////////////////////////////////////////////////
//ok
{
LOG("CHiPerfProvider::XHiPerfProvider::StopRefreshing");
// The refresher being supplied by the caller is actually
// one of our own refreshers, so a simple cast is convenient
// so that we can access private members.
XRefresher *pOurRefresher;
if (pRefresher)
{
LOG ("NON-NULL refresher");
pOurRefresher = (XRefresher *) pRefresher;
}
else
{
LOG ("NULL refresher");
pOurRefresher = &m_pObject->m_XRefresher;
}
pOurRefresher->RemoveObject(lId);
return NO_ERROR;
}
STDMETHODIMP CHiPerfProvider::XHiPerfProvider::CreateRefreshableEnum(
/* [in] */ IWbemServices* pNamespace,
/* [in, string] */ LPCWSTR wszClass,
/* [in] */ IWbemRefresher* pRefresher,
/* [in] */ long lFlags,
/* [in] */ IWbemContext* pContext,
/* [in] */ IWbemHiPerfEnum* pHiPerfEnum,
/* [out] */ long* plId )
{
// Just a placeholder for now
LOG("CHiPerfProvider::XHiPerfProvider::CreateRefreshableEnum");
return E_NOTIMPL;
}
STDMETHODIMP CHiPerfProvider::XHiPerfProvider::GetObjects(
/* [in] */ IWbemServices* pNamespace,
/* [in] */ long lNumObjects,
/* [in,size_is(lNumObjects)] */ IWbemObjectAccess** apObj,
/* [in] */ long lFlags,
/* [in] */ IWbemContext* pContext)
{
// Just a placeholder for now
LOG("CHiPerfProvider::XHiPerfProvider::GetObjects");
return E_NOTIMPL;
}
CHiPerfProvider::XRefresher::XRefresher(CHiPerfProvider *pObject) :
CImpl<IWbemRefresher, CHiPerfProvider>(pObject)
//ok
{
LOG("CHiPerfProvider::XRefresher::XRefresher");
// Initialize the instance cache to be empty
for (int i = 0; i < NUM_SAMPLE_INSTANCES; i++)
m_aRefInstances[i] = 0;
}
CHiPerfProvider::XRefresher::~XRefresher()
//ok
{
LOG("CHiPerfProvider::XRefresher::~XRefresher");
// Release the cached IWbemObjectAccess instances.
for (DWORD i = 0; i < NUM_SAMPLE_INSTANCES; i++)
{
if (m_aRefInstances[i])
m_aRefInstances[i]->Release();
}
}
BOOL CHiPerfProvider::XRefresher::AddObject(IWbemObjectAccess *pObj, LONG *plId)
//////////////////////////////////////////////////////////////////////
//
// Adds an object to the refresher. This is a private mechanism
// used by CHiPerfProvider and not part of the COM interface.
//
// The ID we return for future identification is simply
// the array index.
//
//////////////////////////////////////////////////////////////////////
//ok
{
LOG("CHiPerfProvider::XRefresher::AddObject");
for (DWORD i = 0; i < NUM_SAMPLE_INSTANCES; i++)
{
if (m_aRefInstances[i] == 0)
{
pObj->AddRef();
m_aRefInstances[i] = pObj;
// The ID we return for future identification is simply
// the array index.
*plId = i;
LOG("Added Object");
return TRUE;
}
}
LOGERROR("Failed to Add Object");
return FALSE;
}
BOOL CHiPerfProvider::XRefresher::RemoveObject(LONG lId)
//////////////////////////////////////////////////////////////////////
//
// Removes an object from the refresher. This is a private mechanism
// used by CHiPerfProvider and not part of the COM interface.
//
// Removes an object from the refresher by ID. In our case, the ID
// is actually the array index we used internally, so it is simple
// to locate and remove the object.
//
//////////////////////////////////////////////////////////////////////
//ok
{
LOG("CHiPerfProvider::XRefresher::RemoveObject");
if (m_aRefInstances[lId] == 0)
return FALSE;
m_aRefInstances[lId]->Release();
m_aRefInstances[lId] = 0;
return TRUE;
}
HRESULT CHiPerfProvider::XRefresher::Refresh(/* [in] */ long lFlags)
//////////////////////////////////////////////////////////////////////
//
// Executed to refresh a set of instances bound to the particular
// refresher.
//
//////////////////////////////////////////////////////////////////////
//ok
{
LOG("CHiPerfProvider::XRefresher::Refresh");
return NO_ERROR;
}