/*++ Copyright (C) 1998-2001 Microsoft Corporation Module Name: Abstract: History: --*/ ////////////////////////////////////////////////////////////////////// // // HiPerfProv.cpp // // // ////////////////////////////////////////////////////////////////////// #include "precomp.h" #include #include #include #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: // A pointer to the relevant namespace. Not used. // Not used. // 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: // A pointer to the relevant namespace in WINMGMT. // A pointer to a copy of the object which is to be // added. This object itself cannot be used, as // it not owned locally. // The refresher to which to add the object. // Not used. // Not used here. // A pointer to the internal object which was added // to the refresher. // 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: // The refresher object from which we are to // remove the perf object. // The ID of the object. // 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(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; }