//////////////////////////////////////////////////////////////////////////////////////// // // WDMPerf.cpp // // Module: WMI WDM high performance provider // // This file includes the provider and refresher code. // // Copyright (c) 2000-2002 Microsoft Corporation, All Rights Reserved // //////////////////////////////////////////////////////////////////////////////////////// #include "precomp.h" #if defined(_WIN64) ULONG Hash ( const LONG a_Arg ) {return a_Arg;} #include #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(),m_pProvider->RepositoryPtr(),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,m_pIWbemRepository,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(_WIN64) if (m_HashTable == NULL) { hr = WBEM_E_OUT_OF_MEMORY; } else #endif { hr = WMI.Initialize(TRUE,WMIGUID_QUERY,&m_HandleMap,NULL,pNamespace,m_pIWbemRepository,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(_WIN64) 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(_WIN64) if (m_HashTable == NULL) { hr = WBEM_E_OUT_OF_MEMORY; } else #endif { hr = WMI.Initialize(TRUE,WMIGUID_QUERY,&m_HandleMap,(WCHAR*)wcsClass,pNamespace,m_pIWbemRepository,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(_WIN64) 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(_WIN64) 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,m_pIWbemRepository,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; }