797 lines
24 KiB
C++
797 lines
24 KiB
C++
|
/*++
|
||
|
|
||
|
Copyright (C) 1997-2001 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
History:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
//***************************************************************************
|
||
|
//
|
||
|
// NTPERF.CPP
|
||
|
//
|
||
|
// Sample NT5 Perf Counter Provider
|
||
|
//
|
||
|
// raymcc 02-Dec-97 Created
|
||
|
// raymcc 20-Feb-98 Updated to use new initializer
|
||
|
//
|
||
|
//***************************************************************************
|
||
|
|
||
|
#include "precomp.h"
|
||
|
#include <stdio.h>
|
||
|
|
||
|
#include <wbemidl.h>
|
||
|
|
||
|
#include <wbemint.h>
|
||
|
|
||
|
#include "ntperf.h"
|
||
|
|
||
|
//***************************************************************************
|
||
|
//
|
||
|
// CNt5Refresher constructor
|
||
|
//
|
||
|
//***************************************************************************
|
||
|
// ok
|
||
|
|
||
|
CNt5Refresher::CNt5Refresher()
|
||
|
{
|
||
|
m_lRef = 0; // COM Ref Count
|
||
|
|
||
|
// Set the instance cache to all zeros.
|
||
|
// As objects are added to the refresher
|
||
|
// we simply put them in unused slots in the array.
|
||
|
// ================================================
|
||
|
|
||
|
for (int i = 0; i < NUM_SAMPLE_INSTANCES; i++)
|
||
|
{
|
||
|
m_aInstances[i] = 0;
|
||
|
}
|
||
|
|
||
|
// Set the values of the property handles to zero.
|
||
|
// ===============================================
|
||
|
|
||
|
m_hName = 0;
|
||
|
m_hCounter1 = 0;
|
||
|
m_hCounter2 = 0;
|
||
|
m_hCounter3 = 0;
|
||
|
}
|
||
|
|
||
|
//***************************************************************************
|
||
|
//
|
||
|
// CNt5Refresher destructor
|
||
|
//
|
||
|
//***************************************************************************
|
||
|
// ok
|
||
|
|
||
|
CNt5Refresher::~CNt5Refresher()
|
||
|
{
|
||
|
// Release the cached IWbemObjectAccess instances.
|
||
|
// ===============================================
|
||
|
|
||
|
for (DWORD i = 0; i < NUM_SAMPLE_INSTANCES; i++)
|
||
|
{
|
||
|
if (m_aInstances[i])
|
||
|
m_aInstances[i]->Release();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//***************************************************************************
|
||
|
//
|
||
|
// CNt5Refresher::Refresh
|
||
|
//
|
||
|
// Executed to refresh a set of instances bound to the particular
|
||
|
// refresher.
|
||
|
//
|
||
|
//***************************************************************************
|
||
|
// ok
|
||
|
|
||
|
HRESULT CNt5Refresher::Refresh(/* [in] */ long lFlags)
|
||
|
{
|
||
|
// Zip through all the objects and increment the values.
|
||
|
// =====================================================
|
||
|
|
||
|
for (DWORD i = 0; i < NUM_SAMPLE_INSTANCES; i++)
|
||
|
{
|
||
|
// Get the object at this location.
|
||
|
// ================================
|
||
|
|
||
|
IWbemObjectAccess *pAccess = m_aInstances[i];
|
||
|
|
||
|
// If there is no object in this array slot (a NULL pointer)
|
||
|
// there is nothing to refresh.
|
||
|
// =========================================================
|
||
|
|
||
|
if (pAccess == 0)
|
||
|
continue;
|
||
|
|
||
|
// Increment all the counter values to simulate an update.
|
||
|
// The client already has a pointer to this object, so
|
||
|
// all we have to do is update the values.
|
||
|
// =======================================================
|
||
|
|
||
|
DWORD dwVal;
|
||
|
pAccess->ReadDWORD(m_hCounter1, &dwVal);
|
||
|
dwVal++;
|
||
|
pAccess->WriteDWORD(m_hCounter1, dwVal);
|
||
|
|
||
|
pAccess->ReadDWORD(m_hCounter3, &dwVal);
|
||
|
dwVal++;
|
||
|
pAccess->WriteDWORD(m_hCounter3, dwVal);
|
||
|
|
||
|
unsigned __int64 qwVal;
|
||
|
pAccess->ReadQWORD(m_hCounter2, &qwVal);
|
||
|
qwVal++;
|
||
|
pAccess->WriteQWORD(m_hCounter2, qwVal);
|
||
|
}
|
||
|
|
||
|
return NO_ERROR;
|
||
|
}
|
||
|
|
||
|
//***************************************************************************
|
||
|
//
|
||
|
// CNt5Refresher::TransferPropHandles
|
||
|
//
|
||
|
// This is a private mechanism used by CNt5PerfProvider.
|
||
|
// It is used to copy the property handles from the
|
||
|
// hi-perf provider object to the refresher. We need these handles to
|
||
|
// quickly access the properties in each instance. The same handles are
|
||
|
// used for all instances.
|
||
|
//
|
||
|
//***************************************************************************
|
||
|
// ok
|
||
|
|
||
|
void CNt5Refresher::TransferPropHandles(CNt5PerfProvider *pSrc)
|
||
|
{
|
||
|
m_hName = pSrc->m_hName;
|
||
|
m_hCounter1 = pSrc->m_hCounter1;
|
||
|
m_hCounter2 = pSrc->m_hCounter2;
|
||
|
m_hCounter3 = pSrc->m_hCounter3;
|
||
|
}
|
||
|
|
||
|
//***************************************************************************
|
||
|
//
|
||
|
// CNt5Refresher::AddRef
|
||
|
//
|
||
|
// Standard COM AddRef().
|
||
|
//
|
||
|
//***************************************************************************
|
||
|
// ok
|
||
|
ULONG CNt5Refresher::AddRef()
|
||
|
{
|
||
|
return InterlockedIncrement(&m_lRef);
|
||
|
}
|
||
|
|
||
|
//***************************************************************************
|
||
|
//
|
||
|
// CNt5Refresher::Release
|
||
|
//
|
||
|
// Standard COM Release().
|
||
|
//
|
||
|
//***************************************************************************
|
||
|
// ok
|
||
|
ULONG CNt5Refresher::Release()
|
||
|
{
|
||
|
long lRef = InterlockedDecrement(&m_lRef);
|
||
|
if(lRef == 0)
|
||
|
delete this;
|
||
|
return lRef;
|
||
|
}
|
||
|
|
||
|
//***************************************************************************
|
||
|
//
|
||
|
// CNt5Refresher::QueryInterface
|
||
|
//
|
||
|
// Standard COM QueryInterface().
|
||
|
//
|
||
|
//***************************************************************************
|
||
|
// ok
|
||
|
|
||
|
HRESULT CNt5Refresher::QueryInterface(REFIID riid, void** ppv)
|
||
|
{
|
||
|
if (riid == IID_IUnknown || riid == IID_IWbemRefresher)
|
||
|
{
|
||
|
*ppv = (IWbemRefresher *) this;
|
||
|
AddRef();
|
||
|
return S_OK;
|
||
|
}
|
||
|
else return E_NOINTERFACE;
|
||
|
}
|
||
|
|
||
|
//***************************************************************************
|
||
|
//
|
||
|
// CNt5Refresher::AddObject
|
||
|
//
|
||
|
// Adds an object to the refresher. This is a private mechanism
|
||
|
// used by CNt5PerfProvider and not part of the COM interface.
|
||
|
//
|
||
|
// The ID we return for future identification is simply
|
||
|
// the array index.
|
||
|
//
|
||
|
//***************************************************************************
|
||
|
// ok
|
||
|
|
||
|
BOOL CNt5Refresher::AddObject(
|
||
|
IWbemObjectAccess *pObj,
|
||
|
LONG *plId
|
||
|
)
|
||
|
{
|
||
|
for (DWORD i = 0; i < NUM_SAMPLE_INSTANCES; i++)
|
||
|
{
|
||
|
if (m_aInstances[i] == 0)
|
||
|
{
|
||
|
pObj->AddRef();
|
||
|
m_aInstances[i] = pObj;
|
||
|
|
||
|
// The ID we return for future identification is simply
|
||
|
// the array index.
|
||
|
// ====================================================
|
||
|
*plId = i;
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
//***************************************************************************
|
||
|
//
|
||
|
// CNt5Refresher::RemoveObject
|
||
|
//
|
||
|
// This is a private mechanism used by CNt5PerfProvider 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.
|
||
|
//
|
||
|
//***************************************************************************
|
||
|
|
||
|
BOOL CNt5Refresher::RemoveObject(LONG lId)
|
||
|
{
|
||
|
if (m_aInstances[lId] == 0)
|
||
|
return FALSE;
|
||
|
|
||
|
m_aInstances[lId]->Release();
|
||
|
m_aInstances[lId] = 0;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//***************************************************************************
|
||
|
//
|
||
|
// CNt5PerfProvider constructor
|
||
|
//
|
||
|
//***************************************************************************
|
||
|
// ok
|
||
|
|
||
|
CNt5PerfProvider::CNt5PerfProvider()
|
||
|
{
|
||
|
m_lRef = 0;
|
||
|
m_pSampleClass = 0;
|
||
|
|
||
|
// All the instances we work with are cached internally.
|
||
|
// =====================================================
|
||
|
|
||
|
for (int i = 0; i < NUM_SAMPLE_INSTANCES; i++)
|
||
|
m_aInstances[i] = 0;
|
||
|
|
||
|
// Property value handles.
|
||
|
// =======================
|
||
|
|
||
|
m_hName = 0; // "Name" property in the MOF
|
||
|
m_hCounter1 = 0; // "Counter1" in the MOF
|
||
|
m_hCounter2 = 0; // "Counter2" in the MOF
|
||
|
m_hCounter3 = 0; // "Counter3" in the MOF
|
||
|
}
|
||
|
|
||
|
//***************************************************************************
|
||
|
//
|
||
|
// CNt5PerfProvider destructor
|
||
|
//
|
||
|
//***************************************************************************
|
||
|
// ok
|
||
|
|
||
|
CNt5PerfProvider::~CNt5PerfProvider()
|
||
|
{
|
||
|
// 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();
|
||
|
|
||
|
if (m_pSampleClass)
|
||
|
m_pSampleClass->Release();
|
||
|
}
|
||
|
|
||
|
|
||
|
//***************************************************************************
|
||
|
//
|
||
|
// CNt5Refresher::AddRef
|
||
|
//
|
||
|
// Standard COM AddRef().
|
||
|
//
|
||
|
//***************************************************************************
|
||
|
// ok
|
||
|
|
||
|
ULONG CNt5PerfProvider::AddRef()
|
||
|
{
|
||
|
return InterlockedIncrement(&m_lRef);
|
||
|
}
|
||
|
|
||
|
//***************************************************************************
|
||
|
//
|
||
|
// CNt5Refresher::Release
|
||
|
//
|
||
|
// Standard COM Release().
|
||
|
//
|
||
|
//***************************************************************************
|
||
|
// ok
|
||
|
|
||
|
ULONG CNt5PerfProvider::Release()
|
||
|
{
|
||
|
long lRef = InterlockedDecrement(&m_lRef);
|
||
|
if(lRef == 0)
|
||
|
delete this;
|
||
|
return lRef;
|
||
|
}
|
||
|
|
||
|
//***************************************************************************
|
||
|
//
|
||
|
// CNt5Refresher::QueryInterface
|
||
|
//
|
||
|
// Standard COM QueryInterface(). We have to support two interfaces,
|
||
|
// the IWbemHiPerfProvider interface itself to provide the objects and
|
||
|
// the IWbemProviderInit interface to initialize the provider.
|
||
|
//
|
||
|
//***************************************************************************
|
||
|
// ok
|
||
|
|
||
|
HRESULT CNt5PerfProvider::QueryInterface(REFIID riid, void** ppv)
|
||
|
{
|
||
|
if(riid == IID_IUnknown || riid == IID_IWbemHiPerfProvider)
|
||
|
{
|
||
|
*ppv = (IWbemHiPerfProvider*) this;
|
||
|
AddRef();
|
||
|
return S_OK;
|
||
|
}
|
||
|
else if (riid == IID_IWbemProviderInit)
|
||
|
{
|
||
|
*ppv = (IWbemProviderInit *) this;
|
||
|
AddRef();
|
||
|
return S_OK;
|
||
|
}
|
||
|
else return E_NOINTERFACE;
|
||
|
}
|
||
|
|
||
|
|
||
|
//***************************************************************************
|
||
|
//
|
||
|
// CNt5Refresher::Initialize
|
||
|
//
|
||
|
// Called once during startup. Insdicates to the provider which
|
||
|
// namespace it is being invoked for and which User. It also supplies
|
||
|
// a back pointer to WINMGMT so that class definitions can be retrieved.
|
||
|
//
|
||
|
// We perform any one-time initialization in this routine. The
|
||
|
// final call to Release() is for any cleanup.
|
||
|
//
|
||
|
// <wszUser> The current user.
|
||
|
// <lFlags> Reserved.
|
||
|
// <wszNamespace> The namespace for which we are being activated.
|
||
|
// <wszLocale> The locale under which we are to be running.
|
||
|
// <pNamespace> An active pointer back into the current namespace
|
||
|
// from which we can retrieve schema objects.
|
||
|
// <pCtx> The user's context object. We simply reuse this
|
||
|
// during any reentrant operations into WINMGMT.
|
||
|
// <pInitSink> The sink to which we indicate our readiness.
|
||
|
//
|
||
|
//***************************************************************************
|
||
|
// ok
|
||
|
|
||
|
HRESULT CNt5PerfProvider::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
|
||
|
)
|
||
|
{
|
||
|
BSTR PropName = 0;
|
||
|
IWbemObjectAccess *pAccess = 0;
|
||
|
|
||
|
// Get a copy of our sample class def so that we can create & maintain
|
||
|
// instances of it.
|
||
|
// ===================================================================
|
||
|
|
||
|
HRESULT hRes = pNamespace->GetObject(BSTR(L"Win32_Nt5PerfTest"),
|
||
|
0, pCtx, &m_pSampleClass, 0
|
||
|
);
|
||
|
|
||
|
if (hRes)
|
||
|
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;
|
||
|
m_pSampleClass->SpawnInstance(0, &pInst);
|
||
|
|
||
|
// Write out the instance name.
|
||
|
// ============================
|
||
|
|
||
|
wchar_t buf[128];
|
||
|
swprintf(buf, L"Inst_%d", i);
|
||
|
|
||
|
VARIANT vName;
|
||
|
VariantInit(&vName);
|
||
|
V_BSTR(&vName) = SysAllocString(buf);
|
||
|
V_VT(&vName) = VT_BSTR;
|
||
|
|
||
|
BSTR PropName = SysAllocString(L"Name");
|
||
|
pInst->Put(PropName, 0, &vName, 0);
|
||
|
SysFreeString(PropName);
|
||
|
VariantClear(&vName);
|
||
|
|
||
|
pInst->QueryInterface(IID_IWbemObjectAccess, (LPVOID *) &pAccess);
|
||
|
|
||
|
m_aInstances[i] = pAccess;
|
||
|
pInst->Release();
|
||
|
}
|
||
|
|
||
|
|
||
|
// Get the property handles for the well-known properties in
|
||
|
// this counter type. We cache the property handles
|
||
|
// for each property so that we can transfer them to the
|
||
|
// refresher later on.
|
||
|
// =========================================================
|
||
|
|
||
|
m_pSampleClass->QueryInterface(IID_IWbemObjectAccess,
|
||
|
(LPVOID *) &pAccess);
|
||
|
|
||
|
|
||
|
PropName = SysAllocString(L"Name");
|
||
|
hRes = pAccess->GetPropertyHandle(PropName, 0, &m_hName);
|
||
|
SysFreeString(PropName);
|
||
|
|
||
|
PropName = SysAllocString(L"Counter1");
|
||
|
hRes = pAccess->GetPropertyHandle(PropName, 0, &m_hCounter1);
|
||
|
SysFreeString(PropName);
|
||
|
|
||
|
PropName = SysAllocString(L"Counter2");
|
||
|
hRes = pAccess->GetPropertyHandle(PropName, 0, &m_hCounter2);
|
||
|
SysFreeString(PropName);
|
||
|
|
||
|
PropName = SysAllocString(L"Counter3");
|
||
|
hRes = pAccess->GetPropertyHandle(PropName, 0, &m_hCounter3);
|
||
|
SysFreeString(PropName);
|
||
|
|
||
|
pAccess->Release();
|
||
|
|
||
|
// Now let's set all the instance to some default values.
|
||
|
// ======================================================
|
||
|
|
||
|
for (i = 0; i < NUM_SAMPLE_INSTANCES; i++)
|
||
|
{
|
||
|
IWbemObjectAccess *pAccess = m_aInstances[i];
|
||
|
|
||
|
hRes = pAccess->WriteDWORD(m_hCounter1, DWORD(i));
|
||
|
hRes = pAccess->WriteQWORD(m_hCounter2, (_int64) + 100 + i);
|
||
|
hRes = pAccess->WriteDWORD(m_hCounter3, DWORD(i + 1000));
|
||
|
}
|
||
|
|
||
|
|
||
|
// 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(0, WBEM_S_INITIALIZED);
|
||
|
|
||
|
return NO_ERROR;
|
||
|
}
|
||
|
|
||
|
|
||
|
//***************************************************************************
|
||
|
//
|
||
|
// CNt5Refresher::QueryInstances
|
||
|
//
|
||
|
// Called whenever a complete, fresh list of instances for a given
|
||
|
// class is required. The objects are constructed and sent back to the
|
||
|
// caller through the sink. The sink can be used in-line as here, or
|
||
|
// the call can return and a separate thread could be used to deliver
|
||
|
// the instances to the sink.
|
||
|
//
|
||
|
// Parameters:
|
||
|
// <pNamespace> A pointer to the relevant namespace. This
|
||
|
// should not be AddRef'ed.
|
||
|
// <wszClass> The class name for which instances are required.
|
||
|
// <lFlags> Reserved.
|
||
|
// <pCtx> The user-supplied context (not used here).
|
||
|
// <pSink> The sink to which to deliver the objects. The objects
|
||
|
// can be delivered synchronously through the duration
|
||
|
// of this call or asynchronously (assuming we
|
||
|
// had a separate thread). A IWbemObjectSink::SetStatus
|
||
|
// call is required at the end of the sequence.
|
||
|
//
|
||
|
//***************************************************************************
|
||
|
// ok
|
||
|
|
||
|
HRESULT CNt5PerfProvider::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
|
||
|
)
|
||
|
{
|
||
|
if (pNamespace == 0 || wszClass == 0 || pSink == 0)
|
||
|
return WBEM_E_INVALID_PARAMETER;
|
||
|
|
||
|
// Quickly zip through the instances and update the values before
|
||
|
// returning them. This is just a dummy operation to make it
|
||
|
// look like the instances are continually changing like real
|
||
|
// perf counters.
|
||
|
// ==============================================================
|
||
|
|
||
|
for (int i = 0; i < NUM_SAMPLE_INSTANCES; i++)
|
||
|
{
|
||
|
IWbemObjectAccess *pAccess = 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;
|
||
|
pAccess->QueryInterface(IID_IWbemClassObject, (LPVOID *) &pOtherFormat);
|
||
|
|
||
|
|
||
|
// 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;
|
||
|
}
|
||
|
|
||
|
|
||
|
//***************************************************************************
|
||
|
//
|
||
|
// CNt5Refresher::CreateRefresher
|
||
|
//
|
||
|
// 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
|
||
|
|
||
|
HRESULT CNt5PerfProvider::CreateRefresher(
|
||
|
/* [in] */ IWbemServices __RPC_FAR *pNamespace,
|
||
|
/* [in] */ long lFlags,
|
||
|
/* [out] */ IWbemRefresher __RPC_FAR *__RPC_FAR *ppRefresher
|
||
|
)
|
||
|
{
|
||
|
if (pNamespace == 0 || ppRefresher == 0)
|
||
|
return WBEM_E_INVALID_PARAMETER;
|
||
|
|
||
|
// Construct a new empty refresher.
|
||
|
// ================================
|
||
|
|
||
|
CNt5Refresher *pNewRefresher = new CNt5Refresher();
|
||
|
|
||
|
// Move copies of the property handles to the refresher
|
||
|
// so that it can quickly update property values during
|
||
|
// a refresh operation.
|
||
|
// ====================================================
|
||
|
|
||
|
pNewRefresher->TransferPropHandles(this);
|
||
|
|
||
|
// Follow COM rules and AddRef() the thing before sending it back.
|
||
|
// ===============================================================
|
||
|
|
||
|
pNewRefresher->AddRef();
|
||
|
*ppRefresher = pNewRefresher;
|
||
|
|
||
|
return NO_ERROR;
|
||
|
}
|
||
|
|
||
|
//***************************************************************************
|
||
|
//
|
||
|
// CNt5Refresher::CreateRefreshableObject
|
||
|
//
|
||
|
// 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
|
||
|
|
||
|
HRESULT CNt5PerfProvider::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
|
||
|
)
|
||
|
{
|
||
|
// The object supplied by <pTemplate> must not be copied.
|
||
|
// Instead, we want to find out which object the caller is after
|
||
|
// and return a pointer to *our* own private instance which is
|
||
|
// already set up internally. This value will be sent back to the
|
||
|
// caller so that everyone is sharing the same exact instance
|
||
|
// in memory.
|
||
|
// ===============================================================
|
||
|
|
||
|
// Find out which object is being requested for addition.
|
||
|
// ======================================================
|
||
|
|
||
|
wchar_t buf[128];
|
||
|
*buf = 0;
|
||
|
LONG lNameLength = 0;
|
||
|
pTemplate->ReadPropertyValue(m_hName, 128, &lNameLength, LPBYTE(buf));
|
||
|
|
||
|
// Scan out the index from the instance name. We only do this
|
||
|
// because the instance name is a string.
|
||
|
// ===========================================================
|
||
|
|
||
|
DWORD dwIndex = 0;
|
||
|
swscanf(buf, L"Inst_%u", &dwIndex);
|
||
|
// Now we know which object is desired.
|
||
|
// ====================================
|
||
|
|
||
|
IWbemObjectAccess *pOurCopy = m_aInstances[dwIndex];
|
||
|
|
||
|
// 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.
|
||
|
// =========================================================
|
||
|
|
||
|
CNt5Refresher *pOurRefresher = (CNt5Refresher *) pRefresher;
|
||
|
|
||
|
pOurRefresher->AddObject(pOurCopy, plId);
|
||
|
|
||
|
// Return a copy of the internal object.
|
||
|
// =====================================
|
||
|
|
||
|
pOurCopy->AddRef();
|
||
|
*ppRefreshable = pOurCopy;
|
||
|
*plId = LONG(dwIndex);
|
||
|
|
||
|
return NO_ERROR;
|
||
|
}
|
||
|
|
||
|
|
||
|
//***************************************************************************
|
||
|
//
|
||
|
// CNt5Refresher::StopRefreshing
|
||
|
//
|
||
|
// 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
|
||
|
|
||
|
HRESULT CNt5PerfProvider::StopRefreshing(
|
||
|
/* [in] */ IWbemRefresher __RPC_FAR *pRefresher,
|
||
|
/* [in] */ long lId,
|
||
|
/* [in] */ long lFlags
|
||
|
)
|
||
|
{
|
||
|
// 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.
|
||
|
// =========================================================
|
||
|
|
||
|
CNt5Refresher *pOurRefresher = (CNt5Refresher *) pRefresher;
|
||
|
|
||
|
pOurRefresher->RemoveObject(lId);
|
||
|
|
||
|
return NO_ERROR;
|
||
|
}
|
||
|
|
||
|
//***************************************************************************
|
||
|
//
|
||
|
// CNt5Refresher::CreateRefreshableEnum
|
||
|
//
|
||
|
// Called whenever a user wants to create an enumeration in a refresher.
|
||
|
//
|
||
|
// Parameters:
|
||
|
// <pNamespace> The namespace this is for
|
||
|
// <wszClass> Name of the class we are enumerating
|
||
|
// <pRefresher> The refresher object from which we are to
|
||
|
// remove the perf object.
|
||
|
// <lFlags> Not used.
|
||
|
// <pContext> Wbem Context object
|
||
|
// <pHiPerfEnum> Enumerator object into which refresher should place
|
||
|
// its results
|
||
|
// <plId> The enum id (for identification during removal)
|
||
|
//
|
||
|
//***************************************************************************
|
||
|
// ok
|
||
|
HRESULT CNt5PerfProvider::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
|
||
|
return E_NOTIMPL;
|
||
|
}
|
||
|
|
||
|
//***************************************************************************
|
||
|
//
|
||
|
// CNt5Refresher::CreateRefreshableEnum
|
||
|
//
|
||
|
// Called whenever a user wants to create an enumeration in a refresher.
|
||
|
//
|
||
|
// Parameters:
|
||
|
// <pNamespace> The namespace this is for
|
||
|
// <lNumObjects> Number of objects in the array
|
||
|
// <apObj> Objects to retrieve (keys are set)
|
||
|
// <lFlags> Not used.
|
||
|
// <pContext> Wbem Context object
|
||
|
// <pHiPerfEnum> Enumerator object into which refresher should place
|
||
|
// its results
|
||
|
// <plId> The enum id (for identification during removal)
|
||
|
//
|
||
|
//***************************************************************************
|
||
|
// ok
|
||
|
HRESULT CNt5PerfProvider::GetObjects(
|
||
|
/* [in] */ IWbemServices* pNamespace,
|
||
|
/* [in] */ long lNumObjects,
|
||
|
/* [in,size_is(lNumObjects)] */ IWbemObjectAccess** apObj,
|
||
|
/* [in] */ long lFlags,
|
||
|
/* [in] */ IWbemContext* pContext)
|
||
|
{
|
||
|
// Just a placeholder for now
|
||
|
return E_NOTIMPL;
|
||
|
}
|