|
|
/*++
Copyright (C) 1997-1999 Microsoft Corporation
Module Name:
ntperf.cpp
Abstract:
Mapped NT5 Perf counter provider
History:
raymcc 02-Dec-97 Created. raymcc 20-Feb-98 Updated to use new initializer. bobw 8-Jun-98 tuned up
--*/
#include "wpheader.h"
#include <stdio.h>
#include "oahelp.inl"
#define __WBEMSECURITY 1
//***************************************************************************
//
// CNt5PerfProvider constructor
//
//***************************************************************************
// ok
CNt5PerfProvider::CNt5PerfProvider(enumCLSID OriginClsid) { m_lRef = 0; m_OriginClsid = OriginClsid; m_hClassMapMutex = CreateMutex(NULL, FALSE, NULL); }
//***************************************************************************
//
// CNt5PerfProvider destructor
//
//***************************************************************************
// ok
CNt5PerfProvider::~CNt5PerfProvider() { int i; CClassMapInfo *pClassElem;
assert (m_lRef == 0);
for (i = 0; i < m_aCache.Size(); i++) { pClassElem = (CClassMapInfo *) m_aCache[i]; m_PerfObject.RemoveClass (pClassElem->m_pClassDef); delete pClassElem; } m_aCache.Empty(); // reset the buffer pointers
if (m_hClassMapMutex != 0) CloseHandle(m_hClassMapMutex);
// RegCloseKey(HKEY_PERFORMANCE_DATA); // causes more problems than it solves
}
//***************************************************************************
//
// CNt5PerfProvider::AddRef
//
// Standard COM AddRef().
//
//***************************************************************************
// ok
ULONG CNt5PerfProvider::AddRef() { return InterlockedIncrement(&m_lRef); }
//***************************************************************************
//
// CNt5PerfProvider::Release
//
// Standard COM Release().
//
//***************************************************************************
// ok
ULONG CNt5PerfProvider::Release() { long lRef = InterlockedDecrement(&m_lRef); if(lRef == 0) { delete this; } return lRef; }
//***************************************************************************
//
// CNt5PerfProvider::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) { HRESULT hReturn;
if (riid == IID_IUnknown || riid == IID_IWbemHiPerfProvider) { *ppv = (IWbemHiPerfProvider*) this; AddRef(); hReturn = S_OK; } else if (riid == IID_IWbemProviderInit) { *ppv = (IWbemProviderInit *) this; AddRef(); hReturn = S_OK; } else { hReturn = E_NOINTERFACE; } return hReturn; }
//***************************************************************************
//
// CNt5PerfProvider::Initialize
//
// Called once during startup. Indicates to the provider which
// namespace it is being invoked for and which User. It also supplies
// a back pointer to CIMOM 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 CIMOM.
// <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 ) { UNREFERENCED_PARAMETER(wszUser); UNREFERENCED_PARAMETER(lFlags); UNREFERENCED_PARAMETER(wszNamespace); UNREFERENCED_PARAMETER(wszLocale); UNREFERENCED_PARAMETER(pNamespace); UNREFERENCED_PARAMETER(pCtx);
pInitSink->SetStatus(0, WBEM_S_INITIALIZED);
return NO_ERROR; } //***************************************************************************
//
// CNt5PerfProvider::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 or retained past the
// execution of this method.
// <wszClass> The class name for which instances are required.
// <lFlags> Reserved.
// <pCtx> The user-supplied context (used during callbacks
// into CIMOM).
// <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 ) { HRESULT hReturn; BOOL bRes ; CClassMapInfo *pClsMap = NULL;
UNREFERENCED_PARAMETER(lFlags);
#ifdef __WBEMSECURITY
hReturn = CoImpersonateClient(); // make sure we're legit.
BOOL fRevert = SUCCEEDED( hReturn );
// The following error appears to occur when we are in-proc and there is no
// proxy/stub, so we are effectively impersonating already
if ( RPC_E_CALL_COMPLETE == hReturn ) { hReturn = S_OK; }
if (S_OK == hReturn) { hReturn = CheckImpersonationLevel(); } // Check Registry security here.
if ((hReturn != S_OK) || (!HasPermission())) { // if Impersonation level is incorrect or
// the caller doesn't have permission to read
// from the registry, then they cannot continue
hReturn = WBEM_E_ACCESS_DENIED; }
#else
hReturn = S_OK; #endif
if (hReturn == S_OK) {
if (pNamespace == 0 || wszClass == 0 || pSink == 0) { hReturn = WBEM_E_INVALID_PARAMETER; } else {
// Ensure the class is in our cache and mapped.
// ============================================
bRes = MapClass(pNamespace, wszClass, pCtx);
if (bRes == FALSE) { // Class is not one of ours.
hReturn = WBEM_E_INVALID_CLASS; } else { pClsMap = FindClassMap(wszClass); if (pClsMap == NULL) { hReturn = WBEM_E_INVALID_CLASS; } }
if (hReturn == NO_ERROR) { // Refresh the instances.
// ======================
PerfHelper::QueryInstances(&m_PerfObject, pClsMap, pSink);
// Tell CIMOM we are finished.
// ===========================
pSink->SetStatus(0, WBEM_NO_ERROR, 0, 0); hReturn = NO_ERROR; } } } else { // return error
}
#ifdef __WBEMSECURITY
// Revert if we successfuly impersonated the user
if ( fRevert ) { CoRevertToSelf(); } #endif
return hReturn; }
//***************************************************************************
//
// CNt5PerfProvider::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 ) { HRESULT hReturn; CNt5Refresher *pNewRefresher;
UNREFERENCED_PARAMETER(lFlags);
#ifdef __WBEMSECURITY
hReturn = CoImpersonateClient(); // make sure we're legit.
BOOL fRevert = SUCCEEDED( hReturn );
// The following error appears to occur when we are in-proc and there is no
// proxy/stub, so we are effectively impersonating already
if ( RPC_E_CALL_COMPLETE == hReturn ) { hReturn = S_OK; }
if (S_OK == hReturn) { hReturn = CheckImpersonationLevel(); } // Check Registry security here.
if ((hReturn != S_OK) || (!HasPermission())) { // if Impersonation level is incorrect or
// the caller doesn't have permission to read
// from the registry, then they cannot continue
hReturn = WBEM_E_ACCESS_DENIED; }
#else
hReturn = S_OK; #endif
if (hReturn == S_OK) {
if (pNamespace == 0 || ppRefresher == 0) { hReturn = WBEM_E_INVALID_PARAMETER; } else { // Construct a new empty refresher.
// ================================
pNewRefresher = new CNt5Refresher (this);
if (pNewRefresher != NULL) { // Follow COM rules and AddRef() the thing before sending it back.
// ===============================================================
pNewRefresher->AddRef(); *ppRefresher = pNewRefresher; hReturn = NO_ERROR; } else { hReturn = WBEM_E_OUT_OF_MEMORY; } } }
#ifdef __WBEMSECURITY
// Revert if we successfuly impersonated the user
if ( fRevert ) { CoRevertToSelf(); } #endif
return hReturn; }
//***************************************************************************
//
// CNt5PerfProvider::CreateRefresherObject
//
// Called whenever a user wants to include an object in a refresher.
//
// Parameters:
// <pNamespace> A pointer to the relevant namespace in CIMOM.
// <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::CreateRefresherObject( /* [in] */ IWbemServices __RPC_FAR *pNamespace, /* [in] */ IWbemObjectAccess __RPC_FAR *pTemplate, /* [in] */ IWbemRefresher __RPC_FAR *pRefresher, /* [in] */ long lFlags, /* [in] */ IWbemContext __RPC_FAR *pContext, /* [string][in] */ LPCWSTR wszClass, /* [in] */ IWbemHiPerfEnum __RPC_FAR *pHiPerfEnum, /* [out] */ IWbemObjectAccess __RPC_FAR *__RPC_FAR *ppRefreshable, /* [out] */ long __RPC_FAR *plId ) { IWbemClassObject *pOriginal = 0; IWbemClassObject *pNewCopy = 0; IWbemObjectAccess *pNewAccess = 0; CNt5Refresher *pRef = 0; CClassMapInfo *pClsMap; VARIANT v; BOOL bRes; HRESULT hReturn = NO_ERROR;
UNREFERENCED_PARAMETER(lFlags);
if (ppRefreshable != NULL) { // Initialize the argument
*ppRefreshable = 0; }
// init the variant
VariantInit(&v);
if (pTemplate != NULL) { // Make a copy of the template object.
// ===================================
hReturn = pTemplate->QueryInterface(IID_IWbemClassObject, (LPVOID *) &pOriginal); if (hReturn == NO_ERROR) { hReturn = pOriginal->Clone(&pNewCopy);
// Get the class name of the object.
// =================================
if (hReturn == NO_ERROR) { hReturn = pOriginal->Get(CBSTR(cszClassName), 0, &v, 0, 0); if ((hReturn == NO_ERROR) && (v.vt != VT_BSTR)) { hReturn = WBEM_E_INVALID_CLASS; } }
// We are now done with the original object
// ========================================
pOriginal->Release(); }
if (hReturn == NO_ERROR) { // We now get the IWbemObjectAccess form of the cloned object
// and release the unused interface.
// ==========================================================
hReturn = pNewCopy->QueryInterface(IID_IWbemObjectAccess, (LPVOID *) &pNewAccess); if (hReturn == NO_ERROR) { pNewCopy->Release(); // We don't need the IWbemClassObject interface any more
// We now have an IWbemObjectAccess pointer for the refreshable
// object in <pNewAccess>.
// ============================================================
} } } else { // copy the class name passed in
v.vt = VT_BSTR; v.bstrVal = SysAllocString(wszClass); }
if (hReturn == NO_ERROR) { // cast refresher pointer to our refresher object
pRef = (CNt5Refresher *) pRefresher;
// Map the class info for this instance.
// =====================================
bRes = MapClass(pNamespace, V_BSTR(&v), pContext); if (bRes == FALSE) { // Class is not one of ours.
if (pNewAccess != NULL) pNewAccess->Release(); hReturn = WBEM_E_INVALID_CLASS; } else { pClsMap = FindClassMap(V_BSTR(&v)); if (pClsMap == 0) { if (pNewAccess != NULL) pNewAccess->Release(); hReturn = WBEM_E_INVALID_CLASS; } else { // Add the object to the refresher.
if (pHiPerfEnum != NULL) { // then this is an Enum object so add it
bRes = pRef->AddEnum ( pHiPerfEnum, pClsMap, plId); if (bRes) { // Return new ID to caller
// ==========================
hReturn = NO_ERROR; } else { // unable to add enumerator
hReturn = GetLastError(); } } else { // This method will AddRef() the object before returning.
// ======================================================
bRes = pRef->AddObject( &pNewAccess, pClsMap, plId); if (bRes) { // Return object to the user.
// ==========================
*ppRefreshable = pNewAccess; hReturn = NO_ERROR; } else { // unable to add object
hReturn = GetLastError(); } } } } }
VariantClear(&v);
return hReturn; }
//***************************************************************************
//
// CNt5PerfProvider::CreateRefreshableObject
//
// Called whenever a user wants to include an object in a refresher.
//
// Parameters:
// <pNamespace> A pointer to the relevant namespace in CIMOM.
// <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 ) {
HRESULT hReturn = NO_ERROR;
#ifdef __WBEMSECURITY
hReturn = CoImpersonateClient(); // make sure we're legit.
BOOL fRevert = SUCCEEDED( hReturn );
// The following error appears to occur when we are in-proc and there is no
// proxy/stub, so we are effectively impersonating already
if ( RPC_E_CALL_COMPLETE == hReturn ) { hReturn = S_OK; }
if (S_OK == hReturn) { hReturn = CheckImpersonationLevel(); } // Check Registry security here.
if ((hReturn != S_OK) || (!HasPermission())) { // if Impersonation level is incorrect or
// the caller doesn't have permission to read
// from the registry, then they cannot continue
hReturn = WBEM_E_ACCESS_DENIED; }
#else
hReturn = S_OK; #endif
if (hReturn == S_OK) { hReturn = CreateRefresherObject( pNamespace, pTemplate, pRefresher, lFlags, pContext, NULL, NULL, ppRefreshable, plId); }
#ifdef __WBEMSECURITY
// Revert if we successfuly impersonated the user
if ( fRevert ) { CoRevertToSelf(); } #endif
return hReturn; } //***************************************************************************
//
// CNt5PerfProvider::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 ) { CNt5Refresher *pRef; BOOL bRes ; HRESULT hReturn;
UNREFERENCED_PARAMETER(lFlags);
#ifdef __WBEMSECURITY
hReturn = CoImpersonateClient(); // make sure we're legit.
BOOL fRevert = SUCCEEDED( hReturn );
// The following error appears to occur when we are in-proc and there is no
// proxy/stub, so we are effectively impersonating already
if ( RPC_E_CALL_COMPLETE == hReturn ) { hReturn = S_OK; }
if (S_OK == hReturn) { hReturn = CheckImpersonationLevel(); } // Check Registry security here.
if ((hReturn != S_OK) || (!HasPermission())) { // if Impersonation level is incorrect or
// the caller doesn't have permission to read
// from the registry, then they cannot continue
hReturn = WBEM_E_ACCESS_DENIED; }
#else
hReturn = S_OK; #endif
if (hReturn == S_OK) {
pRef = (CNt5Refresher *) pRefresher;
bRes = pRef->RemoveObject(lId); if (bRes == FALSE) { hReturn = WBEM_E_FAILED; } else { hReturn = WBEM_NO_ERROR; } }
#ifdef __WBEMSECURITY
// Revert if we successfuly impersonated the user
if ( fRevert ) { CoRevertToSelf(); } #endif
return hReturn; } HRESULT CNt5PerfProvider::CreateRefreshableEnum( /* [in] */ IWbemServices __RPC_FAR *pNamespace, /* [string][in] */ LPCWSTR wszClass, /* [in] */ IWbemRefresher __RPC_FAR *pRefresher, /* [in] */ long lFlags, /* [in] */ IWbemContext __RPC_FAR *pContext, /* [in] */ IWbemHiPerfEnum __RPC_FAR *pHiPerfEnum, /* [out] */ long __RPC_FAR *plId) { HRESULT hReturn;
#ifdef __WBEMSECURITY
hReturn = CoImpersonateClient(); // make sure we're legit.
BOOL fRevert = SUCCEEDED( hReturn );
// The following error appears to occur when we are in-proc and there is no
// proxy/stub, so we are effectively impersonating already
if ( RPC_E_CALL_COMPLETE == hReturn ) { hReturn = S_OK; }
if (S_OK == hReturn) { hReturn = CheckImpersonationLevel(); } // Check Registry security here.
if ((hReturn != S_OK) || (!HasPermission())) { // if Impersonation level is incorrect or
// the caller doesn't have permission to read
// from the registry, then they cannot continue
hReturn = WBEM_E_ACCESS_DENIED; }
#else
hReturn = S_OK; #endif
if (hReturn == S_OK) {
hReturn = CreateRefresherObject( pNamespace, NULL, pRefresher, lFlags, pContext, wszClass, pHiPerfEnum, NULL, plId); }
#ifdef __WBEMSECURITY
// Revert if we successfuly impersonated the user
if ( fRevert ) { CoRevertToSelf(); } #endif
return hReturn; } HRESULT CNt5PerfProvider::GetObjects( /* [in] */ IWbemServices __RPC_FAR *pNamespace, /* [in] */ long lNumObjects, /* [size_is][in] */ IWbemObjectAccess __RPC_FAR *__RPC_FAR *apObj, /* [in] */ long lFlags, /* [in] */ IWbemContext __RPC_FAR *pContext) { DBG_UNREFERENCED_PARAMETER(pNamespace); DBG_UNREFERENCED_PARAMETER(lNumObjects); DBG_UNREFERENCED_PARAMETER(apObj); DBG_UNREFERENCED_PARAMETER(lFlags); DBG_UNREFERENCED_PARAMETER(pContext);
return WBEM_E_METHOD_NOT_IMPLEMENTED; } //***************************************************************************
//
// CNt5PerfProvider::MapClass
//
// Adds the class map to an internal cache.
//
// <pClsMap> The pointer to the map info to add. This pointer
// is acquired by this function and should not be
// deleted by the caller.
//
//***************************************************************************
// ok
BOOL CNt5PerfProvider::AddClassMap( IN CClassMapInfo *pClsMap ) { DWORD dwResult = ERROR_SUCCESS; int i; CClassMapInfo *pTracer; int nNumElements;
if (m_hClassMapMutex != 0) { if (WAIT_OBJECT_0 == WaitForSingleObject(m_hClassMapMutex, cdwClassMapTimeout)) { nNumElements = m_aCache.Size();
// Because of a problem in which perflibs seem to ignore supported methods of updating
// the perflib names database (lodctr/unlodctr), do a quick initial traversal to ensure
// that we don't have any duplicate object indices, since this can cause real problems
// during adding and refreshing, since incorrect indexes can be returned.
for (i = 0; i < nNumElements; i++) { pTracer = (CClassMapInfo *) m_aCache[i];
// We've got a problem -- we cannot add this class
if (pClsMap->m_dwObjectId == pTracer->m_dwObjectId ) { ReleaseMutex( m_hClassMapMutex ); return FALSE; } }
for (i = 0; i < nNumElements; i++) { pTracer = (CClassMapInfo *) m_aCache[i]; if (_wcsicmp(pClsMap->m_pszClassName, pTracer->m_pszClassName) < 0) { m_aCache.InsertAt(i, pClsMap); break; } } if (i == nNumElements) { // If here, add it to the end.
// ===========================
m_aCache.Add(pClsMap); }
// make sure the library is in the list
dwResult = m_PerfObject.AddClass (pClsMap->m_pClassDef, TRUE); ReleaseMutex(m_hClassMapMutex); } else { dwResult = ERROR_LOCK_FAILED; } } return (dwResult == ERROR_SUCCESS); }
//***************************************************************************
//
// CNt5PerfProvider::FindClassMap
//
//***************************************************************************
// ok
CClassMapInfo *CNt5PerfProvider::FindClassMap( LPWSTR pszClassName ) { int l = 0; int u; int m; CClassMapInfo *pClsMap; CClassMapInfo *pClsMapReturn = NULL;
// Binary search the cache.
// ========================
if (m_hClassMapMutex != 0) { if (WAIT_OBJECT_0 == WaitForSingleObject(m_hClassMapMutex, cdwClassMapTimeout)) {
u = m_aCache.Size() - 1;
while (l <= u) { m = (l + u) / 2;
pClsMap = (CClassMapInfo *) m_aCache[m];
if (pClsMap != NULL) { if (_wcsicmp(pszClassName, pClsMap->m_pszClassName) < 0) { u = m - 1; } else if (_wcsicmp(pszClassName, pClsMap->m_pszClassName) > 0) { l = m + 1; } else { // Hit!
pClsMapReturn = pClsMap; break; } } else { break; } } ReleaseMutex(m_hClassMapMutex); } } return pClsMapReturn; }
//***************************************************************************
//
// CNt5PerfProvider::MapClass
//
// Retrieves the requested class and places it in the cache.
//
// Parameters:
// pNs The namespace which contains the class definition.
// wsClass The class name.
// pCtx The inbound context object. Only used for reentrant
// calls.
//
//***************************************************************************
// ok
BOOL CNt5PerfProvider::MapClass( IN IWbemServices *pNs, IN WCHAR *wszClass, IN IWbemContext *pCtx ) { HRESULT hRes = 0; BOOL bReturn = FALSE; IWbemClassObject *pClsDef = 0; IWbemQualifierSet *pQSet = 0; VARIANT v; CClassMapInfo *pMapInfo = 0;
if (m_hClassMapMutex != 0) { if (WAIT_OBJECT_0 == WaitForSingleObject(m_hClassMapMutex, cdwClassMapTimeout)) { // See if the class is already in the cache.
// =========================================
if (FindClassMap(wszClass) != 0) { // already loaded so quit now
bReturn = TRUE; } else { // Get the class definition from CIMOM.
// ====================================
hRes = pNs->GetObject(CBSTR(wszClass), 0, pCtx, &pClsDef, 0); if (hRes == NO_ERROR) { // Verify the class is one of ours by checking
// the "provider" qualifier to ensure it matches
// the name that we we have for this component.
// =============================================
hRes = pClsDef->GetQualifierSet(&pQSet); if (hRes == NO_ERROR) { VariantInit(&v); hRes = pQSet->Get(CBSTR(cszProvider), 0, &v, 0); pQSet->Release(); if ((hRes == NO_ERROR) && (v.vt == VT_BSTR)) { if (_wcsicmp(V_BSTR(&v), cszProviderName) == 0) { // Get the property handles and mappings to the perf counter ids
// by calling the Map() method of CClassMapInfo.
// ==============================================================
pMapInfo = new CClassMapInfo; if (pMapInfo != NULL) { if (pMapInfo->Map(pClsDef)) { // Add it to the cache.
// ====================
bReturn = AddClassMap(pMapInfo); } else { // unable to add this to the cache
delete pMapInfo; //pClsDef->Release(); // this was not AddRef'd so no need to Release
} } else { // inable to create new class
bReturn = FALSE; } } else { // unable to read provider qualifier so bail
// as this isn't a dynamic provider
pClsDef->Release(); } } else { SetLastError ((DWORD)WBEM_E_INVALID_PROVIDER_REGISTRATION); } VariantClear(&v); } else { // unable to get qualifiers
pClsDef->Release(); } } else { // Unable to retrieve the class definition
} } ReleaseMutex(m_hClassMapMutex); } } return bReturn; }
//***************************************************************************
//
// CNt5PerfProvider::HasPermission
//
// tests to see if the caller has permission to access the functions
//
// Parameters:
// void N/A
//
//***************************************************************************
// ok
BOOL CNt5PerfProvider::HasPermission (void) { DWORD dwStatus; HKEY hKeyTest; BOOL bReturn;
dwStatus = RegOpenKeyExW ( HKEY_LOCAL_MACHINE, (LPCWSTR)L"Software\\Microsoft\\Windows NT\\CurrentVersion\\WbemPerf", 0, KEY_READ, &hKeyTest);
if ((dwStatus == ERROR_SUCCESS) || (dwStatus == ERROR_FILE_NOT_FOUND)) { bReturn = TRUE; if (dwStatus == ERROR_SUCCESS) RegCloseKey (hKeyTest); } else { bReturn = FALSE; }
return bReturn; }
//***************************************************************************
//
// CNt5PerfProvider::CheckImpersonationLevel
//
// tests caller's security impersonation level for correct access
//
// Only call here if CoImpersonate worked.
//
// Parameters:
// void N/A
//
//***************************************************************************
// ok
HRESULT CNt5PerfProvider::CheckImpersonationLevel (void) { HRESULT hr = WBEM_E_ACCESS_DENIED; BOOL bReturn;
// Now, let's check the impersonation level. First, get the thread token
HANDLE hThreadTok; DWORD dwImp, dwBytesReturned;
bReturn = OpenThreadToken( GetCurrentThread(), TOKEN_QUERY, TRUE, &hThreadTok);
if (!bReturn) {
// If the CoImpersonate works, but the OpenThreadToken fails, we are running under the
// process token (either local system, or if we are running with /exe, the rights of
// the logged in user). In either case, impersonation rights don't apply. We have the
// full rights of that user.
hr = WBEM_S_NO_ERROR;
} else { // We really do have a thread token, so let's retrieve its level
bReturn = GetTokenInformation( hThreadTok, TokenImpersonationLevel, &dwImp, sizeof(DWORD), &dwBytesReturned);
if (bReturn) { // Is the impersonation level Impersonate?
if ((dwImp == SecurityImpersonation) || (dwImp == SecurityDelegation)) { hr = WBEM_S_NO_ERROR; } else { hr = WBEM_E_ACCESS_DENIED; } } else { hr = WBEM_E_FAILED; }
// Done with this handle
CloseHandle(hThreadTok); }
return hr;
}
|