windows-nt/Source/XPSP1/NT/admin/wmi/wbem/providers/wdmprovider/wdmperf.cpp
2020-09-26 16:20:57 +08:00

539 lines
17 KiB
C++

////////////////////////////////////////////////////////////////////////////////////////
//
// WDMPerf.cpp
//
// Module: WMI WDM high performance provider
//
// This file includes the provider and refresher code.
//
// Copyright (c) 2000-2001 Microsoft Corporation, All Rights Reserved
//
////////////////////////////////////////////////////////////////////////////////////////
#include "precomp.h"
#if defined(_AMD64_) || defined(_IA64_)
ULONG Hash ( const LONG a_Arg ) {return a_Arg;}
#include <Allocator.cpp>
#endif
////////////////////////////////////////////////////////////////////////////////////////
//
// CRefresher
//
////////////////////////////////////////////////////////////////////////////////////////
CRefresher::CRefresher(CWMI_Prov* pProvider)
{
m_lRef = 0;
// ===========================================================
// Retain a copy of the provider
// ===========================================================
m_pProvider = pProvider;
if (m_pProvider)
{
m_pProvider->AddRef();
}
// ===========================================================
// Increment the global COM object counter
// ===========================================================
InterlockedIncrement(&g_cObj);
}
////////////////////////////////////////////////////////////////////////////////////////
CRefresher::~CRefresher()
{
// ===========================================================
// Release the provider
// ===========================================================
if (m_pProvider){
m_pProvider->Release();
}
// ===========================================================
// Decrement the global COM object counter
// ===========================================================
InterlockedDecrement(&g_cObj);
}
////////////////////////////////////////////////////////////////////////////////////////
//
// Standard COM mterface
//
////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CRefresher::QueryInterface(REFIID riid, void** ppv)
{
HRESULT hr = E_NOINTERFACE;
*ppv = NULL;
if (riid == IID_IUnknown)
{
*ppv = (LPVOID)(IUnknown*)this;
}
else if (riid == IID_IWbemRefresher)
{
*ppv = (LPVOID)(IWbemRefresher*)this;
}
if( *ppv )
{
AddRef();
hr = S_OK;
}
return hr;
}
////////////////////////////////////////////////////////////////////////////////////////
//
// Standard COM AddRef
//
////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG) CRefresher::AddRef()
{
return InterlockedIncrement(&m_lRef);
}
////////////////////////////////////////////////////////////////////////////////////////
//
// Standard COM Release
//
////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG) CRefresher::Release()
{
long lRef = InterlockedDecrement(&m_lRef);
if(lRef == 0)
{
delete this;
}
return lRef;
}
////////////////////////////////////////////////////////////////////////////////////////
//**************************************************************************************
//
// Externally called
//
//**************************************************************************************
////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////
//
// Executed to refresh a set of instances bound to the particular refresher.
//
// In most situations the instance data, such as counter values and
// the set of current instances within any existing enumerators, would
// be updated whenever Refresh was called.
//
////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CRefresher::Refresh(/* [in] */ long lFlags)
{
HRESULT hr = WBEM_NO_ERROR;
IWbemObjectAccess* pObj = NULL;
SetStructuredExceptionHandler seh;
CWMIHiPerfShell WMI(TRUE);
try
{
// ================================================================
// Updates all instances that have been added to the refresher, and
// updates their counter values
// ================================================================
hr = WMI.Initialize(TRUE,WMIGUID_QUERY,m_pProvider->HandleMapPtr(),NULL,m_pProvider->ServicesPtr(),NULL,NULL);
if( SUCCEEDED(hr))
{
WMI.SetHiPerfHandleMap(&m_HiPerfHandleMap);
hr = WMI.RefreshCompleteList();
}
}
STANDARD_CATCH
return hr;
}
////////////////////////////////////////////////////////////////////////////////////////
//
// 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.
//
// Parameters:
// pNamespace - A pointer to the relevant namespace.
// 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.
//
////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CWMI_Prov::QueryInstances( IWbemServices __RPC_FAR *pNamespace,
WCHAR __RPC_FAR *wcsClass, long lFlags,
IWbemContext __RPC_FAR *pCtx, IWbemObjectSink __RPC_FAR *pHandler )
{
// Since we have implemented a IWbemServices interface, this code lives in CreateInstanceEnum instead
return E_NOTIMPL;
}
////////////////////////////////////////////////////////////////////////////////////////
//
// Called whenever a new refresher is needed by the client.
//
// Parameters:
// pNamespace - A pointer to the relevant namespace. Not used.
// lFlags - Reserved.
// ppRefresher - Receives the requested refresher.
//
////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CWMI_Prov::CreateRefresher( IWbemServices __RPC_FAR *pNamespace, long lFlags,
IWbemRefresher __RPC_FAR *__RPC_FAR *ppRefresher )
{
HRESULT hr = WBEM_E_FAILED;
CWMIHiPerfShell WMI(TRUE);
SetStructuredExceptionHandler seh;
if (pNamespace == 0 || ppRefresher == 0)
{
return WBEM_E_INVALID_PARAMETER;
}
// =========================================================
// Construct and initialize a new empty refresher
// =========================================================
try
{
hr = WMI.Initialize(TRUE,WMIGUID_QUERY,&m_HandleMap,NULL,pNamespace,NULL,NULL);
if( SUCCEEDED(hr))
{
CRefresher* pNewRefresher = new CRefresher(this);
if( pNewRefresher )
{
// =========================================================
// Follow COM rules and AddRef() the thing before sending it
// back
// =========================================================
pNewRefresher->AddRef();
*ppRefresher = pNewRefresher;
hr = WBEM_NO_ERROR;
}
}
}
STANDARD_CATCH
return hr;
}
////////////////////////////////////////////////////////////////////////////////////////
//
// Called whenever a user wants to include an object in a refresher.
//
// Note that the object returned in ppRefreshable is a clone of the
// actual instance maintained by the provider. If refreshers shared
// a copy of the same instance, then a refresh call on one of the
// refreshers would impact the state of both refreshers. This would
// break the refresher rules. Instances in a refresher are only
// allowed to be updated when 'Refresh' is called.
//
// 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).
//
////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CWMI_Prov::CreateRefreshableObject( IWbemServices __RPC_FAR *pNamespace,
IWbemObjectAccess __RPC_FAR *pAccess,
IWbemRefresher __RPC_FAR *pRefresher,
long lFlags,
IWbemContext __RPC_FAR *pCtx,
IWbemObjectAccess __RPC_FAR *__RPC_FAR *ppRefreshable,
long __RPC_FAR *plId )
{
HRESULT hr = WBEM_E_FAILED;
CWMIHiPerfShell WMI(FALSE);
SetStructuredExceptionHandler seh;
if (pNamespace == 0 || pAccess == 0 || pRefresher == 0)
{
return WBEM_E_INVALID_PARAMETER;
}
// =========================================================
// 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.
// =========================================================
try
{
#if defined(_AMD64_) || defined(_IA64_)
if (m_HashTable == NULL)
{
hr = WBEM_E_OUT_OF_MEMORY;
}
else
#endif
{
hr = WMI.Initialize(TRUE,WMIGUID_QUERY,&m_HandleMap,NULL,pNamespace,NULL,pCtx);
if( SUCCEEDED(hr))
{
CRefresher *pOurRefresher = (CRefresher *) pRefresher;
if( pOurRefresher )
{
// =================================================
// Add the object to the refresher. The ID is set by
// AddObject
// =================================================
WMI.SetHiPerfHandleMap(pOurRefresher->HiPerfHandleMap());
ULONG_PTR realId = 0;
hr = WMI.AddAccessObjectToRefresher(pAccess,ppRefreshable, &realId);
#if defined(_AMD64_) || defined(_IA64_)
if (SUCCEEDED(hr))
{
CCritical_SectionWrapper csw(&m_CS);
if (csw.IsLocked())
{
*plId = m_ID;
m_ID++;
if (e_StatusCode_Success != m_HashTable->Insert (*plId, realId))
{
hr = WBEM_E_FAILED;
}
}
else
{
hr = WBEM_E_FAILED;
}
}
#else
*plId = realId;
#endif
}
}
}
}
STANDARD_CATCH
return hr;
}
////////////////////////////////////////////////////////////////////////////////////////
//
// Called when an enumerator is being added to a refresher. The
// enumerator will obtain a fresh set of instances of the specified
// class every time that refresh is called.
//
// wszClass must be examined to determine which class the enumerator
// is being assigned.
//
// Parameters:
// pNamespace - A pointer to the relevant namespace.
// wszClass - The class name for the requested enumerator.
// pRefresher - The refresher object for which we will add the enumerator
// lFlags - Reserved.
// pContext - Not used here.
// pHiPerfEnum - The enumerator to add to the refresher.
// plId - A provider specified ID for the enumerator.
//
////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CWMI_Prov::CreateRefreshableEnum( IWbemServices* pNamespace,
LPCWSTR wcsClass,
IWbemRefresher* pRefresher,
long lFlags, IWbemContext* pCtx,
IWbemHiPerfEnum* pHiPerfEnum, long* plId )
{
HRESULT hr = WBEM_E_FAILED;
SetStructuredExceptionHandler seh;
if( !pHiPerfEnum || wcsClass == NULL || (wcslen(wcsClass) == 0))
{
return WBEM_E_INVALID_PARAMETER;
}
CWMIHiPerfShell WMI(FALSE);
// ===========================================================
// 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.
// ===========================================================
try
{
#if defined(_AMD64_) || defined(_IA64_)
if (m_HashTable == NULL)
{
hr = WBEM_E_OUT_OF_MEMORY;
}
else
#endif
{
hr = WMI.Initialize(TRUE,WMIGUID_QUERY,&m_HandleMap,(WCHAR*)wcsClass,pNamespace,NULL,pCtx);
if( SUCCEEDED(hr))
{
ULONG_PTR realId = 0;
CRefresher *pOurRefresher = (CRefresher *) pRefresher;
if( pOurRefresher )
{
// ===========================================================
// Add the enumerator to the refresher
// ===========================================================
WMI.SetHiPerfHandleMap(pOurRefresher->HiPerfHandleMap());
hr = WMI.AddEnumeratorObjectToRefresher(pHiPerfEnum,&realId);
#if defined(_AMD64_) || defined(_IA64_)
if (SUCCEEDED(hr))
{
CCritical_SectionWrapper csw(&m_CS);
if (csw.IsLocked())
{
*plId = m_ID;
m_ID++;
if (e_StatusCode_Success != m_HashTable->Insert (*plId, realId))
{
hr = WBEM_E_FAILED;
}
}
else
{
hr = WBEM_E_FAILED;
}
}
#else
*plId = realId;
#endif
}
if(SUCCEEDED(hr))
{
if(FAILED(hr = WMI.RefreshCompleteList()))
{
// This function is called before as RemoveObjectFromHandleMap
// deletes the member variables and resets the pointers
WMI.RemoveObjectFromHandleMap(realId);
*plId = 0;
}
}
}
}
}
STANDARD_CATCH
return hr;
}
////////////////////////////////////////////////////////////////////////////////////////
//
// 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.
//
////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CWMI_Prov::StopRefreshing( IWbemRefresher __RPC_FAR *pInRefresher, long lId, long lFlags )
{
HRESULT hr = WBEM_S_NO_ERROR;
CWMIHiPerfShell WMI(TRUE);
SetStructuredExceptionHandler seh;
// ===========================================================
// 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.
// ===========================================================
try
{
#if defined(_AMD64_) || defined(_IA64_)
ULONG_PTR realId = 0;
if (m_HashTable != NULL)
{
CCritical_SectionWrapper csw(&m_CS);
if (csw.IsLocked())
{
if (e_StatusCode_Success != m_HashTable->Find (lId, realId))
{
hr = WBEM_E_FAILED;
}
else
{
m_HashTable->Delete (lId) ;
}
}
else
{
hr = WBEM_E_FAILED;
}
}
else
{
hr = WBEM_E_OUT_OF_MEMORY;
}
#else
ULONG_PTR realId = lId;
#endif
if (SUCCEEDED(hr))
{
hr = WMI.Initialize(TRUE,WMIGUID_QUERY,&m_HandleMap,NULL,m_pIWbemServices,NULL, NULL);
if( SUCCEEDED(hr))
{
CRefresher *pRefresher = (CRefresher *) pInRefresher;
WMI.SetHiPerfHandleMap(pRefresher->HiPerfHandleMap());
if(FAILED(hr))
{
// This function is called before as RemoveObjectFromHandleMap
// deletes the member variables and resets the pointers
}
else
{
hr = WMI.RemoveObjectFromHandleMap(realId);
}
}
}
}
STANDARD_CATCH
return hr;
}
////////////////////////////////////////////////////////////////////////////////////////
//
// Called when a request is made to provide all instances currently being managed by
// the provider in the specified namespace.
//
// Parameters:
// pNamespace - A pointer to the relevant namespace.
// lNumObjects - The number of instances being returned.
// apObj - The array of instances being returned.
// lFlags - Reserved.
// pContext - Not used here.
//
////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CWMI_Prov::GetObjects( IWbemServices* pNamespace, long lNumObjects,
IWbemObjectAccess** apObj, long lFlags,
IWbemContext* pCtx)
{
// Since we have implemented a IWbemServices interface, this code lives in CreateInstanceEnum instead
return E_NOTIMPL;
}