Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2355 lines
65 KiB

/*++
Copyright (C) 1999-2001 Microsoft Corporation
Module Name:
ADAPCLS.CPP
Abstract:
History:
--*/
#include "precomp.h"
#include <wbemcli.h>
#include <throttle.h>
#include <cominit.h>
#include <winmgmtr.h>
#include "perfndb.h"
#include "adaputil.h"
#include "adapreg.h"
#include "ntreg.h"
#include "WMIBroker.h"
#include "ClassBroker.h"
#include "adapcls.h"
#include <comdef.h>
extern HANDLE g_hAbort;
WCHAR * g_aBaseClass[] =
{
ADAP_PERF_RAW_BASE_CLASS,
ADAP_PERF_COOKED_BASE_CLASS
};
CLocaleDefn::CLocaleDefn( WCHAR* pwcsLangId,
HKEY hKey )
: m_wstrLangId( pwcsLangId ),
m_LangId( 0 ),
m_LocaleId( 0 ),
m_pNamespace( NULL ),
m_pNameDb( NULL ),
m_bOK( FALSE ),
m_hRes(WBEM_E_FAILED)
{
HRESULT hr = WBEM_S_NO_ERROR;
// Initialize the base class array
// ===============================
memset( m_apBaseClass, NULL, WMI_ADAP_NUM_TYPES * sizeof( IWbemClassObject* ) );
// A NULL means it is the default locale
// =====================================
if ( NULL != pwcsLangId )
{
hr = InitializeLID();
}
// Initialize the namespace and base class and verify their schema
// ===============================================================
if ( SUCCEEDED( hr ) )
{
hr = InitializeWMI();
}
// Create the names' database for the locale
// =========================================
if ( SUCCEEDED( hr ) )
{
m_pNameDb = new CPerfNameDb( hKey );
if ( ( NULL == m_pNameDb ) || ( !m_pNameDb->IsOk() ) )
{
if ( NULL != m_pNameDb )
{
m_pNameDb->Release();
m_pNameDb = NULL;
}
ERRORTRACE((LOG_WMIADAP,"failure in loading HKEY %p for locale %S err: %d\n",hKey,(LPCWSTR)pwcsLangId,GetLastError()));
hr = WBEM_E_FAILED;
}
}
// If every thing work out, then set the initialization flag
// =========================================================
if ( SUCCEEDED( hr ) )
{
m_bOK = TRUE;
}
else
{
m_hRes = hr;
}
}
CLocaleDefn::~CLocaleDefn()
{
if ( m_pNamespace )
m_pNamespace->Release();
for ( DWORD dw = 0; dw < WMI_ADAP_NUM_TYPES; dw++ )
{
if ( m_apBaseClass[dw] )
m_apBaseClass[dw]->Release();
}
if ( m_pNameDb )
m_pNameDb->Release();
}
HRESULT CLocaleDefn::InitializeLID()
{
HRESULT hr = WBEM_S_NO_ERROR;
LPCWSTR pwstrLangId = (LPWSTR) m_wstrLangId;
// Get the length of the text LID
// ==============================
DWORD dwLangIdLen = m_wstrLangId.Length();
// Ensure that all characters are numeric
// ======================================
for ( DWORD dwCtr = 0; dwCtr < dwLangIdLen && iswxdigit( pwstrLangId[dwCtr] ); dwCtr++ );
if ( dwCtr >= dwLangIdLen )
{
// Now look for the first non-zero character
// =========================================
LPCWSTR pwcsNumStart = pwstrLangId;
for ( dwCtr = 0; dwCtr < dwLangIdLen && *pwcsNumStart == L'0'; dwCtr++, pwcsNumStart++ );
// As long as the LID was not all zeros and the LID is
// 3 digits or less convert the LID to a number
// ===================================================
if ( dwCtr < dwLangIdLen && wcslen( pwcsNumStart ) <= 3 )
{
// Convert the LID to a hex value
// ==============================
WORD wPrimaryLangId = (WORD) wcstoul( pwcsNumStart, NULL, 16 );
// If we are reading the default system id, ensure that we have
// the proper sublanguage and then convert to the member types
// ============================================================
LANGID wSysLID = GetSystemDefaultUILanguage();
if ( ( wSysLID & 0x03FF ) == wPrimaryLangId )
{
m_LangId = wSysLID;
}
else
{
m_LangId = MAKELANGID( wPrimaryLangId, SUBLANG_DEFAULT );
}
m_LocaleId = MAKELCID( m_LangId, SORT_DEFAULT );
WCHAR wcsTemp[32];
StringCchPrintfW(wcsTemp,32, L"0x%.4X", m_LangId );
m_wstrLocaleId = wcsTemp;
StringCchPrintfW( wcsTemp,32, L"MS_%hX", m_LangId );
m_wstrSubNameSpace = wcsTemp;
}
else
{
hr = WBEM_E_FAILED;
}
}
else
{
hr = WBEM_E_FAILED;
}
return hr;
}
HRESULT CLocaleDefn::InitializeWMI()
{
HRESULT hr = WBEM_S_NO_ERROR;
// Initialize the namespace name
// =============================
WString wstrNamespace;
hr = GetNamespaceName(wstrNamespace);
// Initialize the localization namespace
// =====================================
if ( SUCCEEDED( hr ) )
{
hr = CWMIBroker::GetNamespace( wstrNamespace, &m_pNamespace );
}
// Initialize the base classes
// ===========================
for ( DWORD dwBase = 0; ( dwBase < WMI_ADAP_NUM_TYPES ) && SUCCEEDED( hr ); dwBase++ )
{
BSTR bstrBaseClass = SysAllocString( g_aBaseClass[dwBase]);
if (NULL == bstrBaseClass) { hr = WBEM_E_OUT_OF_MEMORY; continue; };
CSysFreeMe sfmBaseClass( bstrBaseClass );
hr = m_pNamespace->GetObject( bstrBaseClass, 0L, NULL, (IWbemClassObject**)&m_apBaseClass[dwBase], NULL );
}
return hr;
}
HRESULT CLocaleDefn::GetLID( int & nLID )
{
nLID = m_LangId;
return WBEM_S_NO_ERROR;
}
HRESULT CLocaleDefn::GetNamespaceName( WString & wstrNamespaceName )
{
HRESULT hr = WBEM_S_NO_ERROR;
try
{
wstrNamespaceName = ADAP_ROOT_NAMESPACE;
if ( 0 != m_LangId )
{
wstrNamespaceName += L"\\";
wstrNamespaceName += m_wstrSubNameSpace;
}
}
catch(CX_MemoryException)
{
hr = WBEM_E_OUT_OF_MEMORY;
}
return hr;
}
HRESULT CLocaleDefn::GetNamespace( IWbemServices** ppNamespace )
{
if (NULL == ppNamespace) return WBEM_E_INVALID_PARAMETER;
*ppNamespace = m_pNamespace;
if ( NULL != *ppNamespace )
{
(*ppNamespace)->AddRef();
}
else
{
return WBEM_E_FAILED;
}
return WBEM_S_NO_ERROR;
}
HRESULT CLocaleDefn::GetNameDb( CPerfNameDb** ppNameDb )
{
if (NULL == ppNameDb) return WBEM_E_INVALID_PARAMETER;
HRESULT hr = WBEM_S_NO_ERROR;
*ppNameDb = m_pNameDb;
if ( NULL != *ppNameDb )
{
(*ppNameDb)->AddRef();
}
else
{
hr = WBEM_E_FAILED;
}
return hr;
}
HRESULT CLocaleDefn::GetBaseClass( DWORD dwType, IWbemClassObject** ppObject )
{
HRESULT hr = WBEM_S_NO_ERROR;
if ( dwType < WMI_ADAP_NUM_TYPES && ppObject)
{
if ( m_apBaseClass[dwType] )
{
*ppObject = m_apBaseClass[dwType];
(*ppObject)->AddRef();
}
else
{
hr = WBEM_E_FAILED;
}
} else
return WBEM_E_INVALID_PARAMETER;
return hr;
}
////////////////////////////////////////////////////////////////////////////////
//
// CLocaleCache
//
////////////////////////////////////////////////////////////////////////////////
CLocaleCache::CLocaleCache( )
: m_nEnumIndex( -1 )
{
}
CLocaleCache::~CLocaleCache()
{
}
HRESULT CLocaleCache::Reset()
{
HRESULT hr = WBEM_NO_ERROR;
m_apLocaleDefn.RemoveAll();
Initialize();
return hr;
}
#define ENGLISH_DEFAULT_LANGID MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)
//#define ENGLISH_DEFAULT_LOCID MAKELCID( MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT )
HRESULT CLocaleCache::Initialize()
{
CLocaleDefn* pDefn = NULL;
DWORD dwIndex = 0;
long lError = 0;
// Setup the default defn
// ======================
pDefn = new CLocaleDefn( NULL, HKEY_PERFORMANCE_TEXT );
CAdapReleaseMe arm( pDefn );
if ( NULL == pDefn || !pDefn->IsOK() )
{
ERRORTRACE((LOG_WMIADAP,"CLocaleDefn failed hr = %08x\n",(pDefn)?pDefn->GetHRESULT():WBEM_E_OUT_OF_MEMORY));
return WBEM_E_FAILED;
}
if (-1 == m_apLocaleDefn.Add( pDefn )) return WBEM_E_OUT_OF_MEMORY;
LANGID wSysLID = GetSystemDefaultUILanguage();
//
// on non english box, always add the classes to the MS_409 namespace
//
if (ENGLISH_DEFAULT_LANGID != wSysLID)
{
WCHAR pLangEng[8];
StringCchPrintfW(pLangEng,8,L"%03x",0x3FF & ENGLISH_DEFAULT_LANGID );
CLocaleDefn* pDefnEng = new CLocaleDefn( pLangEng, HKEY_PERFORMANCE_TEXT );
CAdapReleaseMe armDefnEng( pDefnEng );
if ( NULL == pDefnEng || !pDefnEng->IsOK() )
{
ERRORTRACE((LOG_WMIADAP,"CLocaleDefn(%S) failed hr = %08x\n", pLangEng,pDefn->GetHRESULT()));
return WBEM_E_FAILED;
}
if (-1 == m_apLocaleDefn.Add( pDefnEng ))return WBEM_E_OUT_OF_MEMORY;;
}
WCHAR pLang[8];
StringCchPrintfW(pLang,8,L"%03x",0x3FF & wSysLID);
pDefn = new CLocaleDefn( pLang, HKEY_PERFORMANCE_NLSTEXT );
CAdapReleaseMe armDefn( pDefn );
if ( ( NULL != pDefn ) && ( pDefn->IsOK() ) )
{
if (-1 == m_apLocaleDefn.Add( pDefn )) return WBEM_E_OUT_OF_MEMORY;
}
else // sometimes NLSTEXT is not found
{
CLocaleDefn* pDefn2 = new CLocaleDefn( pLang, HKEY_PERFORMANCE_TEXT );
CAdapReleaseMe armDefn2( pDefn2 );
if ( NULL == pDefn2 || !pDefn2->IsOK() )
{
ERRORTRACE((LOG_WMIADAP,"CLocaleDefn(%S) failed hr = %08x\n", pLang,pDefn2->GetHRESULT()));
return WBEM_E_FAILED;
}
if (-1 == m_apLocaleDefn.Add( pDefn2 )) return WBEM_E_OUT_OF_MEMORY;
}
return WBEM_S_NO_ERROR;
}
HRESULT CLocaleCache::GetDefaultDefn( CLocaleDefn** ppDefn )
{
HRESULT hr = WBEM_E_FAILED;
// Get the definition at location 0
// ================================
int nLID = -1;
if ( 0 < m_apLocaleDefn.GetSize() )
{
CLocaleDefn* pDefn = m_apLocaleDefn[0];
// And verify that it has a locale of 0
// ====================================
if ( NULL != pDefn )
{
hr = pDefn->GetLID( nLID );
}
if ( SUCCEEDED( hr ) && ( 0 == nLID ) )
{
*ppDefn = pDefn;
(*ppDefn)->AddRef();
}
else
{
hr = WBEM_E_FAILED;
}
}
return hr;
}
HRESULT CLocaleCache::BeginEnum( )
{
HRESULT hr = WBEM_S_NO_ERROR;
// 1 is the first localized defnintion
// ===================================
m_nEnumIndex = 1;
return hr;
}
HRESULT CLocaleCache::Next( CLocaleDefn** ppDefn )
{
HRESULT hr = WBEM_S_NO_ERROR;
CLocaleDefn* pDefn = NULL;
int nSize = m_apLocaleDefn.GetSize();
if ( ( -1 < m_nEnumIndex ) && ( nSize > m_nEnumIndex ) )
{
pDefn = m_apLocaleDefn[m_nEnumIndex++];
}
else
{
m_nEnumIndex = -1;
hr = WBEM_E_FAILED;
}
if ( SUCCEEDED( hr ) )
{
*ppDefn = pDefn;
if ( NULL != *ppDefn )
(*ppDefn)->AddRef();
else
hr = WBEM_E_FAILED;
}
return hr;
}
HRESULT CLocaleCache::EndEnum()
{
HRESULT hr = WBEM_S_NO_ERROR;
m_nEnumIndex = -1;
return hr;
}
//
//
// Known Service
//
///////////////////////////////////////////////////////////
//
//
//
bool
WCmp::operator()(WString pFirst,WString pSec) const
{
int res = wbem_wcsicmp(pFirst,pSec);
return (res<0);
}
CKnownSvcs::CKnownSvcs(WCHAR * pMultiSzName):
m_cRef(1),
m_MultiSzName(pMultiSzName)
{
}
CKnownSvcs::~CKnownSvcs()
{
}
DWORD
CKnownSvcs::Add(WCHAR * pService)
{
if (pService)
{
MapSvc::iterator it = m_SetServices.find(pService);
if (it == m_SetServices.end())
{
try
{
m_SetServices.insert(MapSvc::value_type(pService,ServiceRec(true)));
}
catch (CX_MemoryException)
{
return ERROR_OUTOFMEMORY;
}
}
return 0;
}
else
return ERROR_INVALID_PARAMETER;
}
DWORD
CKnownSvcs::Get(WCHAR * pService, ServiceRec ** ppServiceRec)
{
if (pService && ppServiceRec)
{
MapSvc::iterator it = m_SetServices.find(pService);
if (it == m_SetServices.end())
{
*ppServiceRec = NULL;
return ERROR_OBJECT_NOT_FOUND;
}
else
{
*ppServiceRec = &(it->second);
return 0;
}
}
else
return ERROR_INVALID_PARAMETER;
}
DWORD
CKnownSvcs::Remove(WCHAR * pService)
{
if (pService)
{
MapSvc::iterator it = m_SetServices.find(pService);
if (it != m_SetServices.end())
{
try {
m_SetServices.erase(it);
} catch (CX_MemoryException) {
return ERROR_OUTOFMEMORY;
}
}
return 0;
}
else
return ERROR_INVALID_PARAMETER;
}
DWORD
CKnownSvcs::Load()
{
// get the MULTI_SZ key
LONG lRet;
HKEY hKey;
lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
WBEM_REG_WINMGMT,
NULL,
KEY_READ,
&hKey);
if (ERROR_SUCCESS == lRet)
{
DWORD dwSize = 0;
DWORD dwType = REG_MULTI_SZ;
lRet = RegQueryValueEx(hKey,
m_MultiSzName,
NULL,
&dwType,
NULL,
&dwSize);
if (ERROR_SUCCESS == lRet && (dwSize > 0))
{
BYTE * pStrBYTE = new BYTE[dwSize];
if (pStrBYTE)
{
CVectorDeleteMe<BYTE> vdm(pStrBYTE);
lRet = RegQueryValueEx(hKey,
m_MultiSzName,
NULL,
&dwType,
(BYTE *)pStrBYTE,
&dwSize);
if (ERROR_SUCCESS == lRet && REG_MULTI_SZ == dwType)
{
TCHAR * pStr = (TCHAR *)pStrBYTE;
DWORD dwLen = 0;
while(dwLen = lstrlen(pStr))
{
try
{
m_SetServices.insert(MapSvc::value_type(pStr,ServiceRec(true)));
pStr += (dwLen+1);
}
catch (CX_MemoryException)
{
lRet = ERROR_OUTOFMEMORY;
break;
}
}
}
}
else
{
lRet = ERROR_OUTOFMEMORY;
}
}
RegCloseKey(hKey);
}
return lRet;
}
DWORD
CKnownSvcs::Save()
{
// Write the MULTI_SZ key
MapSvc::iterator it;
DWORD dwAllocSize = 1; // the trailing \0
for (it = m_SetServices.begin();it != m_SetServices.end();++it)
{
dwAllocSize += (1+lstrlenW( (*it).first ));
}
WCHAR * pMultiSz = new WCHAR[dwAllocSize];
if (!pMultiSz)
return ERROR_NOT_ENOUGH_MEMORY;
WCHAR * pTmp = pMultiSz;
for (it = m_SetServices.begin();it != m_SetServices.end();++it)
{
const WCHAR * pSrc = (const wchar_t *)it->first;
DWORD i;
for (i=0;pSrc[i];i++){
*pTmp = pSrc[i];
pTmp++;
};
*pTmp = L'\0';
pTmp++;
};
// last char
*pTmp = L'\0';
DWORD dwSize;
LONG lRet;
HKEY hKey;
lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
WBEM_REG_WINMGMT,
NULL,
KEY_WRITE,
&hKey);
if (ERROR_SUCCESS == lRet)
{
lRet = RegSetValueEx(hKey,
m_MultiSzName,
NULL,
REG_MULTI_SZ,
(BYTE*)pMultiSz,
dwAllocSize * sizeof(WCHAR));
RegCloseKey(hKey);
}
if (pMultiSz)
delete [] pMultiSz;
return lRet;
}
////////////////////////////////////////////////////////////////////////////////
//
// CClassElem
//
////////////////////////////////////////////////////////////////////////////////
CClassElem::CClassElem( IWbemClassObject* pObj,
CLocaleCache* pLocaleCache,
CKnownSvcs * pKnownSvcs)
: m_pLocaleCache( pLocaleCache ),
m_pDefaultObject( pObj ),
m_dwIndex( 0 ),
m_bCostly( FALSE ),
m_dwStatus( 0 ),
m_bOk( FALSE ),
m_pKnownSvcs(pKnownSvcs),
m_bReportEventCalled(FALSE)
{
HRESULT hr = WBEM_S_NO_ERROR;
if (m_pKnownSvcs) m_pKnownSvcs->AddRef();
if (m_pLocaleCache ) m_pLocaleCache->AddRef();
if (m_pDefaultObject )
{
m_pDefaultObject->AddRef();
hr = InitializeMembers();
}
if ( SUCCEEDED( hr ) &&
( NULL != m_pLocaleCache ) &&
( NULL != m_pDefaultObject ) )
{
m_bOk = TRUE;
}
}
CClassElem::CClassElem( PERF_OBJECT_TYPE* pPerfObj,
DWORD dwType,
BOOL bCostly,
WString wstrServiceName,
CLocaleCache* pLocaleCache,
CKnownSvcs * pKnownSvcs)
: m_pLocaleCache( pLocaleCache ),
m_pDefaultObject( NULL ),
m_dwIndex( 0 ),
m_bCostly( bCostly ),
m_dwStatus( 0 ),
m_bOk( FALSE ),
m_wstrServiceName( wstrServiceName ),
m_pKnownSvcs(pKnownSvcs),
m_bReportEventCalled(FALSE)
{
HRESULT hr = WBEM_S_NO_ERROR;
CLocaleDefn* pDefn = NULL;
IWbemClassObject* pBaseClass = NULL;
CPerfNameDb* pNameDb = NULL;
if ( m_pKnownSvcs) m_pKnownSvcs->AddRef();
if ( m_pLocaleCache )
{
m_pLocaleCache->AddRef();
// Get the default locale record
// =============================
hr = m_pLocaleCache->GetDefaultDefn( &pDefn );
CAdapReleaseMe rmDefn( pDefn );
// Get the names' database
// =======================
if ( FAILED( hr ) || NULL == pDefn ) return;
hr = pDefn->GetNameDb( &pNameDb );
CAdapReleaseMe rmNameDb( pNameDb );
// Create the requested class
// ==========================
if ( SUCCEEDED( hr ) )
{
hr = pDefn->GetBaseClass( dwType, &pBaseClass );
}
CReleaseMe rmBaseClass( pBaseClass );
if ( SUCCEEDED( hr ) )
{
hr = CDefaultClassBroker::GenPerfClass( pPerfObj,
dwType,
m_bCostly,
pBaseClass,
pNameDb,
m_wstrServiceName,
&m_pDefaultObject );
}
}
else
{
hr = WBEM_E_FAILED;
}
// Initialize the class members
// ============================
if ( SUCCEEDED( hr ) )
{
hr = InitializeMembers();
}
if ( SUCCEEDED( hr ) )
{
m_bOk = TRUE;
}
}
VOID
CClassElem::SetKnownSvcs(CKnownSvcs * pKnownSvcs)
{
if (m_pKnownSvcs)
return;
m_pKnownSvcs = pKnownSvcs;
if (m_pKnownSvcs)
m_pKnownSvcs->AddRef();
}
CClassElem::~CClassElem()
{
if ( m_pLocaleCache ) m_pLocaleCache->Release();
if ( m_pDefaultObject ) m_pDefaultObject->Release();
if ( m_pKnownSvcs) m_pKnownSvcs->Release();
}
HRESULT CClassElem::InitializeMembers()
// If the class name is unavaiable, then the initialization fails. It is not a fatal error if a qualifier is unavailable
{
HRESULT hr = WBEM_NO_ERROR;
VARIANT var;
try
{
// Get the object's name
// =====================
if ( SUCCEEDED( hr ) )
{
hr = m_pDefaultObject->Get(L"__CLASS", 0L, &var, NULL, NULL );
if ( SUCCEEDED( hr ) )
{
m_wstrClassName = var.bstrVal;
VariantClear( &var );
}
}
if ( SUCCEEDED( hr ) )
{
IWbemQualifierSet* pQualSet = NULL;
hr = m_pDefaultObject->GetQualifierSet( &pQualSet );
CReleaseMe rmQualSet( pQualSet );
// Get the service name
// ====================
if ( SUCCEEDED( hr ) )
{
hr = pQualSet->Get( L"registrykey", 0L, &var, NULL );
if ( SUCCEEDED( hr ) )
{
m_wstrServiceName = var.bstrVal;
VariantClear( &var );
}
else
{
m_wstrServiceName.Empty();
hr = WBEM_S_FALSE;
}
}
// Get the perf index
// ==================
if ( SUCCEEDED( hr ) )
{
hr = pQualSet->Get( L"perfindex", 0L, &var, NULL );
if ( SUCCEEDED( hr ) )
{
m_dwIndex = var.lVal;
VariantClear( &var );
}
else
{
m_dwIndex = 0;
hr = WBEM_S_FALSE;
}
}
// Get the costly qualifier
// ========================
if ( SUCCEEDED( hr ) )
{
hr = pQualSet->Get( L"costly", 0L, &var, NULL );
if ( SUCCEEDED( hr ) )
{
m_bCostly = ( var.boolVal == VARIANT_TRUE );
VariantClear( &var );
}
else
{
VariantClear( &var );
m_bCostly = FALSE;
hr = WBEM_NO_ERROR;
}
}
}
}
catch(...)
{
hr = WBEM_E_OUT_OF_MEMORY;
}
return hr;
}
HRESULT CClassElem::UpdateObj( CClassElem* pEl )
// Replaces the WMI object in this element. The commit will do a CompareTo to compare the
// original object (if it exists) and replace it with the updated version
{
HRESULT hr = WBEM_S_NO_ERROR;
IWbemClassObject* pObj = NULL;
hr = pEl->GetObject( &pObj );
if ( SUCCEEDED( hr ) )
{
if ( NULL != pObj )
{
// Release the old object
// ======================
m_pDefaultObject->Release();
// Initialize the new object - already addref'd by GetObject
// =========================================================
m_pDefaultObject = pObj;
}
else
{
hr = WBEM_E_FAILED;
}
}
return hr;
}
HRESULT CClassElem::Remove(BOOL CleanRegistry)
{
HRESULT hr = WBEM_S_NO_ERROR;
IWbemServices* pNamespace = NULL;
BSTR bstrClassName = SysAllocString( m_wstrClassName );
if (NULL == bstrClassName) return WBEM_E_OUT_OF_MEMORY;
CSysFreeMe sfmClassName( bstrClassName );
// Delete the localized objects
// ============================
CLocaleDefn* pDefn = NULL;
m_pLocaleCache->BeginEnum();
while ( ( SUCCEEDED( hr ) ) && ( WBEM_S_NO_ERROR == m_pLocaleCache->Next( &pDefn ) ) )
{
CAdapReleaseMe rmDefn( pDefn );
// Get the localization namespace
// ==============================
hr = pDefn->GetNamespace( &pNamespace );
CReleaseMe rmNamespace( pNamespace );
// And delete it
// =============
if ( SUCCEEDED( hr ) )
{
IWbemClassObject * pObj = NULL;
hr = pNamespace->GetObject(bstrClassName,WBEM_FLAG_RETURN_WBEM_COMPLETE,NULL,&pObj,NULL);
// release the object before deleting
if(pObj) pObj->Release();
if (SUCCEEDED(hr))
{
hr = pNamespace->DeleteClass( bstrClassName, 0, NULL, NULL );
if ( FAILED( hr ) )
{
try
{
// Write on the trace
WString wstrNamespaceName;
if (SUCCEEDED(hr = pDefn->GetNamespaceName( wstrNamespaceName )))
{
LPSTR pClass = m_wstrClassName.GetLPSTR();
LPSTR pNames = wstrNamespaceName.GetLPSTR();
CDeleteMe<CHAR> a(pClass);
CDeleteMe<CHAR> b(pNames);
ERRORTRACE( ( LOG_WMIADAP,"DeleteClass %s from %s 0x%08x",pClass,pNames,hr));
}
}
catch(...)
{
hr = WBEM_E_OUT_OF_MEMORY;
}
}
} else {
// class not found
// nothing to delete
}
}
}
m_pLocaleCache->EndEnum();
// Delete the default object
// =========================
if ( SUCCEEDED( hr ) )
{
hr = m_pLocaleCache->GetDefaultDefn( &pDefn );
CAdapReleaseMe rmDefn( pDefn );
if ( SUCCEEDED( hr ) && pDefn )
{
hr = pDefn->GetNamespace( &pNamespace );
CReleaseMe rmNamespace( pNamespace );
if ( SUCCEEDED( hr ) )
{
hr = pNamespace->DeleteClass( bstrClassName, 0, NULL, NULL );
if ( FAILED( hr ) )
{
// Log an event
// ============
ServiceRec * pSvcRec = NULL;
if (0 == m_pKnownSvcs->Get(m_wstrServiceName,&pSvcRec))
{
if (!pSvcRec->IsELCalled() && !m_bReportEventCalled)
{
try
{
WString wstrNamespaceName;
if (SUCCEEDED(hr = pDefn->GetNamespaceName( wstrNamespaceName )))
{
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
WBEM_MC_ADAP_PERFLIB_REMOVECLASS_FAILURE,
(LPCWSTR) m_wstrClassName,
(LPCWSTR) wstrNamespaceName,
CHex( hr ) );
pSvcRec->SetELCalled();
m_bReportEventCalled = TRUE;
}
}
catch(...)
{
hr = WBEM_E_OUT_OF_MEMORY;
}
}
}
else
{
if (!m_bReportEventCalled)
{
try
{
WString wstrNamespaceName;
if (SUCCEEDED(hr = pDefn->GetNamespaceName( wstrNamespaceName )))
{
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
WBEM_MC_ADAP_PERFLIB_REMOVECLASS_FAILURE,
(LPCWSTR) m_wstrClassName,
(LPCWSTR) wstrNamespaceName,
CHex( hr ) );
m_bReportEventCalled = TRUE;
}
}
catch(...)
{
hr = WBEM_E_OUT_OF_MEMORY;
}
}
}
}
}
}
}
if (SUCCEEDED(hr))
{
if (m_pKnownSvcs)
m_pKnownSvcs->Remove((WCHAR *)m_wstrServiceName);
}
if (CleanRegistry && SUCCEEDED(hr))
{
WString wszRegPath = L"SYSTEM\\CurrentControlSet\\Services\\";
wszRegPath += m_wstrServiceName;
wszRegPath += L"\\Performance";
CNTRegistry reg;
int nRet = 0;
nRet = reg.Open( HKEY_LOCAL_MACHINE, wszRegPath );
switch( nRet )
{
case CNTRegistry::no_error:
{
reg.DeleteValue(ADAP_PERFLIB_STATUS_KEY);
reg.DeleteValue(ADAP_PERFLIB_SIGNATURE);
reg.DeleteValue(ADAP_PERFLIB_SIZE);
reg.DeleteValue(ADAP_PERFLIB_TIME);
}
break;
case CNTRegistry::not_found:
{
hr = WBEM_E_FAILED;
}
break;
case CNTRegistry::access_denied:
{
ServiceRec * pSvcRec = NULL;
if (0 == m_pKnownSvcs->Get(m_wstrServiceName,&pSvcRec))
{
if (!pSvcRec->IsELCalled() && !m_bReportEventCalled)
{
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
WBEM_MC_ADAP_PERFLIB_REG_VALUE_FAILURE,
(LPWSTR)wszRegPath, nRet );
pSvcRec->SetELCalled();
m_bReportEventCalled = TRUE;
}
}
else
{
if (!m_bReportEventCalled)
{
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
WBEM_MC_ADAP_PERFLIB_REG_VALUE_FAILURE,
(LPWSTR)wszRegPath, nRet );
m_bReportEventCalled = TRUE;
}
}
}
break;
}
}
return hr;
}
HRESULT CClassElem::Insert()
{
HRESULT hr = WBEM_S_NO_ERROR;
CLocaleDefn* pDefaultDefn = NULL;
IWbemServices* pNamespace = NULL;
// perform object validation
_IWmiObject * pInternal = NULL;
hr = m_pDefaultObject->QueryInterface(IID__IWmiObject,(void **)&pInternal);
if (SUCCEEDED(hr))
{
CReleaseMe rmi(pInternal);
hr = pInternal->ValidateObject(WMIOBJECT_VALIDATEOBJECT_FLAG_FORCE);
if (FAILED(hr))
{
#ifdef DBG
DebugBreak();
#endif
ERRORTRACE((LOG_WMIADAP,"ValidateObject(%S) %08x\n",(LPWSTR)m_wstrClassName,hr));
return hr;
}
}
// Add the object to the default namespace
// =======================================
hr = m_pLocaleCache->GetDefaultDefn( &pDefaultDefn );
if (FAILED(hr) || NULL == pDefaultDefn) return (FAILED(hr)?hr:WBEM_E_FAILED);
CAdapReleaseMe rmDefaultDefn( pDefaultDefn );
hr = pDefaultDefn->GetNamespace( &pNamespace );
CReleaseMe rmNamespace( pNamespace );
if ( SUCCEEDED( hr ) )
{
hr = pNamespace->PutClass( m_pDefaultObject, WBEM_FLAG_CREATE_OR_UPDATE, NULL, NULL );
if ( FAILED( hr ) )
{
ServiceRec * pSvcRec = NULL;
if (0 == m_pKnownSvcs->Get(m_wstrServiceName,&pSvcRec))
{
if (!pSvcRec->IsELCalled() && !m_bReportEventCalled)
{
try
{
WString wstrNamespace;
if (SUCCEEDED(hr = pDefaultDefn->GetNamespaceName( wstrNamespace )))
{
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
WBEM_MC_ADAP_PERFLIB_PUTCLASS_FAILURE,
(LPCWSTR)m_wstrClassName,
(LPCWSTR) wstrNamespace,
CHex( hr ) );
m_bReportEventCalled = TRUE;
pSvcRec->SetELCalled();
}
}
catch(...)
{
hr = WBEM_E_OUT_OF_MEMORY;
}
}
}
else
{
if (!m_bReportEventCalled)
{
try
{
WString wstrNamespace;
if (SUCCEEDED(hr = pDefaultDefn->GetNamespaceName( wstrNamespace )))
{
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
WBEM_MC_ADAP_PERFLIB_PUTCLASS_FAILURE,
(LPCWSTR)m_wstrClassName,
(LPCWSTR) wstrNamespace,
CHex( hr ) );
m_bReportEventCalled = TRUE;
}
}
catch(...)
{
hr = WBEM_E_OUT_OF_MEMORY;
}
}
}
}
}
if ( SUCCEEDED( hr ) )
{
//
// Add the servicename to the MultiSz Key
//
if (m_pKnownSvcs)
m_pKnownSvcs->Add((WCHAR *)m_wstrServiceName);
hr = VerifyLocales();
}
if ( SUCCEEDED( hr ) )
{
SetStatus( ADAP_OBJECT_IS_REGISTERED );
}
return hr;
}
HRESULT CClassElem::GetClassName( WString& wstr )
{
HRESULT hr = WBEM_S_NO_ERROR;
try
{
wstr = m_wstrClassName;
}
catch(CX_MemoryException)
{
hr = WBEM_E_OUT_OF_MEMORY;
}
return hr;
}
HRESULT CClassElem::GetClassName( BSTR* pbStr )
{
if (NULL == pbStr) return WBEM_E_INVALID_PARAMETER;
if (NULL == (*pbStr = SysAllocString( (LPCWSTR) m_wstrClassName )))
return WBEM_E_OUT_OF_MEMORY;
return WBEM_S_NO_ERROR;
}
HRESULT CClassElem::GetObject( IWbemClassObject** ppObj )
{
if (NULL == ppObj) return WBEM_E_INVALID_PARAMETER;
HRESULT hr = WBEM_S_NO_ERROR;
if ( NULL != m_pDefaultObject )
{
*ppObj = m_pDefaultObject;
(*ppObj)->AddRef();
}
else
{
hr = WBEM_E_FAILED;
}
return hr;
}
HRESULT CClassElem::GetServiceName( WString& wstrServiceName )
{
HRESULT hr = WBEM_S_NO_ERROR;
try
{
wstrServiceName = m_wstrServiceName;
}
catch(CX_MemoryException)
{
hr = WBEM_E_OUT_OF_MEMORY;
}
return hr;
}
BOOL CClassElem::SameName( CClassElem* pEl )
{
WString wstrOtherName;
try
{
if ( FAILED ( pEl->GetClassName( wstrOtherName ) ) )
return FALSE;
}
catch(...)
{
return FALSE;
}
return m_wstrClassName.Equal( wstrOtherName );
}
BOOL CClassElem::SameObject( CClassElem* pEl )
{
BOOL bRes = FALSE;
IWbemClassObject* pObj = NULL;
if (FAILED(pEl->GetObject( &pObj ))) return FALSE;
CReleaseMe rmObj( pObj );
bRes = ( m_pDefaultObject->CompareTo( WBEM_FLAG_IGNORE_OBJECT_SOURCE, pObj ) == WBEM_S_SAME );
return bRes;
}
HRESULT CClassElem::Commit()
{
HRESULT hr = WBEM_S_NO_ERROR;
// Ensure that object is in default namespace
// ==========================================
if ( CheckStatus( ADAP_OBJECT_IS_DELETED ) )
{
hr = Remove( CheckStatus(ADAP_OBJECT_IS_TO_BE_CLEARED) );
}
else if ( CheckStatus( ADAP_OBJECT_IS_REGISTERED | ADAP_OBJECT_IS_NOT_IN_PERFLIB ) && !CheckStatus( ADAP_OBJECT_IS_INACTIVE ) )
{
if ( IsPerfLibUnloaded() )
{
hr = Remove( TRUE );
}
else // the object is there
{
if (m_pKnownSvcs)
m_pKnownSvcs->Add((WCHAR *)m_wstrServiceName);
}
}
else if ( !CheckStatus( ADAP_OBJECT_IS_REGISTERED ) )
{
hr = Insert();
}
else
{
if (m_pKnownSvcs)
m_pKnownSvcs->Add((WCHAR *)m_wstrServiceName);
// non localized classes do not cause an error
VerifyLocales();
}
return hr;
}
BOOL CClassElem::IsPerfLibUnloaded()
{
// Unless we can specifically prove that the perflib has been unloaded, then we assume that it is still loaded
BOOL bLoaded = TRUE;
HRESULT hr = WBEM_S_FALSE;
WCHAR wszRegPath[256];
DWORD dwFirstCtr = 0,
dwLastCtr = 0;
WCHAR* wszObjList = NULL;
CNTRegistry reg;
int nRet = 0;
if ( 0 == m_wstrServiceName.Length() )
{
bLoaded = FALSE;
}
else if ( m_wstrServiceName.EqualNoCase( L"PERFOS" ) ||
m_wstrServiceName.EqualNoCase( L"TCPIP" ) ||
m_wstrServiceName.EqualNoCase( L"PERFPROC" ) ||
m_wstrServiceName.EqualNoCase( L"PERFDISK" ) ||
m_wstrServiceName.EqualNoCase( L"PERFNET" ) ||
m_wstrServiceName.EqualNoCase( L"TAPISRV" ) ||
m_wstrServiceName.EqualNoCase( L"SPOOLER" ) ||
m_wstrServiceName.EqualNoCase( L"MSFTPSvc" ) ||
m_wstrServiceName.EqualNoCase( L"RemoteAccess" ) ||
m_wstrServiceName.EqualNoCase( L"WINS" ) ||
m_wstrServiceName.EqualNoCase( L"MacSrv" ) ||
m_wstrServiceName.EqualNoCase( L"AppleTalk" ) ||
m_wstrServiceName.EqualNoCase( L"NM" ) ||
m_wstrServiceName.EqualNoCase( L"RSVP" ))
{
// This is the list of the hardcoded perflibs - according
// to BobW, they are always considered to be loaded
// ======================================================
bLoaded = TRUE;
}
else
{
// Try to open the service's registry key and read the object list or the first/last counter values
// ================================================================================================
StringCchPrintfW( wszRegPath,256, L"SYSTEM\\CurrentControlSet\\Services\\%s\\Performance", (WCHAR *)m_wstrServiceName );
nRet = reg.Open( HKEY_LOCAL_MACHINE, wszRegPath );
switch( nRet )
{
case CNTRegistry::not_found:
{
bLoaded = FALSE;
}break;
case CNTRegistry::no_error:
{
bLoaded = ( reg.GetStr( L"Object List", &wszObjList ) == CNTRegistry::no_error ) ||
( ( reg.GetDWORD( L"First Counter", &dwFirstCtr ) == CNTRegistry::no_error ) &&
( reg.GetDWORD( L"Last Counter", &dwLastCtr ) == CNTRegistry::no_error )
);
}break;
case CNTRegistry::access_denied:
{
ServiceRec * pSvcRec = NULL;
if (0 == m_pKnownSvcs->Get(m_wstrServiceName,&pSvcRec))
{
if (!pSvcRec->IsELCalled() && !m_bReportEventCalled)
{
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
WBEM_MC_ADAP_PERFLIB_REG_VALUE_FAILURE,
wszRegPath, nRet );
m_bReportEventCalled = TRUE;
pSvcRec->SetELCalled();
}
}
else
{
if (!m_bReportEventCalled)
{
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
WBEM_MC_ADAP_PERFLIB_REG_VALUE_FAILURE,
wszRegPath, nRet );
m_bReportEventCalled = TRUE;
}
}
}break;
}
}
return !bLoaded;
}
HRESULT CClassElem::CompareLocale( CLocaleDefn* pLocaleDefn, IWbemClassObject* pObj )
{
HRESULT hr = WBEM_S_NO_ERROR;
CLocaleDefn* pDefaultDefn = NULL;
IWbemClassObject* pLocaleObj = NULL;
hr = m_pLocaleCache->GetDefaultDefn( &pDefaultDefn );
if (FAILED(hr) || NULL == pDefaultDefn) return (FAILED(hr)?hr:WBEM_E_FAILED);
CAdapReleaseMe armDefaultDefn( pDefaultDefn );
hr = CLocaleClassBroker::ConvertToLocale( m_pDefaultObject, pLocaleDefn, pDefaultDefn, &pLocaleObj);
CReleaseMe rmLocaleObj( pLocaleObj );
if ( SUCCEEDED( hr ) )
{
hr = pObj->CompareTo( WBEM_FLAG_IGNORE_OBJECT_SOURCE, pLocaleObj );
}
return hr;
}
HRESULT CClassElem::InsertLocale( CLocaleDefn* pLocaleDefn )
{
HRESULT hr = WBEM_S_NO_ERROR;
CLocaleDefn* pDefaultDefn = NULL;
IWbemClassObject* pLocaleObj = NULL;
IWbemServices* pNamespace = NULL;
hr = m_pLocaleCache->GetDefaultDefn( &pDefaultDefn );
if (FAILED(hr) || NULL == pDefaultDefn) return (FAILED(hr)?hr:WBEM_E_FAILED);
CAdapReleaseMe armDefaultDefn( pDefaultDefn );
hr = CLocaleClassBroker::ConvertToLocale( m_pDefaultObject, pLocaleDefn, pDefaultDefn, &pLocaleObj);
CReleaseMe rmLocaleObj( pLocaleObj );
if (SUCCEEDED(hr))
{
// perform object validation
_IWmiObject * pInternal = NULL;
hr = pLocaleObj->QueryInterface(IID__IWmiObject,(void **)&pInternal);
if (SUCCEEDED(hr))
{
CReleaseMe rmi(pInternal);
hr = pInternal->ValidateObject(WMIOBJECT_VALIDATEOBJECT_FLAG_FORCE);
if (FAILED(hr))
{
#ifdef DBG
DebugBreak();
#endif
ERRORTRACE((LOG_WMIADAP,"ValidateObject(%S) %08x\n",(LPWSTR)m_wstrClassName,hr));
return hr;
}
}
}
// And add it to the localized namespace
// =====================================
if ( SUCCEEDED( hr ) )
{
hr = pLocaleDefn->GetNamespace( &pNamespace );
CReleaseMe rmNamespace( pNamespace );
if ( SUCCEEDED( hr ) )
{
hr = pNamespace->PutClass( pLocaleObj, WBEM_FLAG_CREATE_OR_UPDATE, NULL, NULL );
if ( FAILED( hr ) )
{
ServiceRec * pSvcRec = NULL;
if (0 == m_pKnownSvcs->Get(m_wstrServiceName,&pSvcRec))
{
if (!pSvcRec->IsELCalled() && !m_bReportEventCalled)
{
try
{
WString wstrNamespace;
if (SUCCEEDED(hr = pLocaleDefn->GetNamespaceName( wstrNamespace )))
{
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
WBEM_MC_ADAP_PERFLIB_PUTCLASS_FAILURE,
(LPCWSTR)m_wstrClassName, (LPCWSTR) wstrNamespace, CHex( hr ) );
m_bReportEventCalled = TRUE;
pSvcRec->SetELCalled();
}
}
catch(...)
{
hr = WBEM_E_OUT_OF_MEMORY;
}
}
}
else
{
if (!m_bReportEventCalled)
{
try
{
WString wstrNamespace;
if (SUCCEEDED(hr = pLocaleDefn->GetNamespaceName( wstrNamespace )))
{
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
WBEM_MC_ADAP_PERFLIB_PUTCLASS_FAILURE,
(LPCWSTR)m_wstrClassName, (LPCWSTR) wstrNamespace, CHex( hr ) );
m_bReportEventCalled = TRUE;
}
}
catch(...)
{
hr = WBEM_E_OUT_OF_MEMORY;
}
}
}
}
}
}
else
{
// no localized class
ERRORTRACE( ( LOG_WMIADAP, "InsertLocale PutClass(%S) %08x\n",(LPWSTR)m_wstrClassName,hr) );
}
return hr;
}
HRESULT CClassElem::VerifyLocales()
{
HRESULT hr = WBEM_S_NO_ERROR;
CLocaleDefn* pLocaleDefn = NULL;
IWbemClassObject* pLocaleObj = NULL;
IWbemServices* pNamespace = NULL;
// Get the localized objects
// =========================
hr = m_pLocaleCache->BeginEnum();
while ( ( SUCCEEDED( hr ) ) && ( WBEM_S_NO_ERROR == m_pLocaleCache->Next( &pLocaleDefn ) ) )
{
CAdapReleaseMe rmLocaleDefn( pLocaleDefn );
// Get the localization namespace
// ==============================
hr = pLocaleDefn->GetNamespace( &pNamespace );
CReleaseMe rmNamespace( pNamespace );
// Get the localized object
// ========================
if ( SUCCEEDED( hr ) )
{
BSTR bstrClassName = SysAllocString( m_wstrClassName );
if (NULL == bstrClassName) { hr = WBEM_E_OUT_OF_MEMORY; continue; }
CSysFreeMe sfmClassName( bstrClassName );
hr = pNamespace->GetObject( bstrClassName, 0L, NULL, &pLocaleObj, NULL );
CReleaseMe rmLocaleObj( pLocaleObj );
if ( SUCCEEDED( hr ) )
{
if ( CompareLocale( pLocaleDefn, pLocaleObj ) != WBEM_S_SAME )
{
hr = InsertLocale( pLocaleDefn );
}
}
else
{
hr = InsertLocale( pLocaleDefn );
}
}
pLocaleObj = NULL;
}
m_pLocaleCache->EndEnum();
return hr;
}
HRESULT CClassElem::SetStatus( DWORD dwStatus )
{
m_dwStatus |= dwStatus;
return WBEM_NO_ERROR;
}
HRESULT CClassElem::ClearStatus( DWORD dwStatus )
{
m_dwStatus &= ~dwStatus;
return WBEM_NO_ERROR;
}
BOOL CClassElem::CheckStatus( DWORD dwStatus )
{
return ( ( m_dwStatus & dwStatus ) == dwStatus );
}
////////////////////////////////////////////////////////////////////////////////////////////
//
// CClassList
//
////////////////////////////////////////////////////////////////////////////////////////////
CClassList::CClassList( CLocaleCache* pLocaleCache )
: m_pLocaleCache( pLocaleCache ),
m_nEnumIndex( -1 ),
m_fOK( FALSE )
{
if ( m_pLocaleCache )
m_pLocaleCache->AddRef();
}
CClassList::~CClassList( void )
{
if ( m_pLocaleCache )
m_pLocaleCache->Release();
}
HRESULT CClassList::BeginEnum()
{
m_nEnumIndex = 0;
return WBEM_S_NO_ERROR;
}
HRESULT CClassList::Next( CClassElem** ppEl )
{
if (NULL == ppEl) return WBEM_E_INVALID_PARAMETER;
HRESULT hr = WBEM_S_NO_ERROR;
int nSize = m_array.GetSize();
CClassElem* pEl = NULL;
do
{
if ( ( -1 < m_nEnumIndex ) && ( nSize > m_nEnumIndex ) )
{
pEl = m_array[m_nEnumIndex++];
}
else
{
m_nEnumIndex = -1;
hr = WBEM_E_FAILED;
}
}
while ( ( SUCCEEDED( hr ) ) && ( pEl->CheckStatus( ADAP_OBJECT_IS_DELETED ) ) );
if ( SUCCEEDED( hr ) )
{
*ppEl = pEl;
if ( NULL != *ppEl )
{
(*ppEl)->AddRef();
}
else
{
hr = WBEM_E_FAILED;
}
}
return hr;
}
HRESULT CClassList::EndEnum()
{
m_nEnumIndex = -1;
return WBEM_S_NO_ERROR;
}
HRESULT CClassList::AddElement( CClassElem* pElem )
{
HRESULT hr = WBEM_S_NO_ERROR;
if ( ( NULL != pElem ) && ( pElem->IsOk() ) )
{
if ( -1 == m_array.Add( pElem ) )
{
// Add failed
// ==========
hr = WBEM_E_OUT_OF_MEMORY;
}
}
else
{
hr = WBEM_E_FAILED;
}
return hr;
}
// Removes the object at the index
HRESULT CClassList::RemoveAt( int nIndex )
{
HRESULT hr = WBEM_S_NO_ERROR;
// Should auto release the object
m_array.RemoveAt( nIndex );
return hr;
}
////////////////////////////////////////////////////////////////////////////////
//
// CPerfClassList
//
////////////////////////////////////////////////////////////////////////////////
CPerfClassList::CPerfClassList( CLocaleCache* pLocaleCache, WCHAR* pwcsServiceName )
: CClassList( pLocaleCache ),
m_wstrServiceName( pwcsServiceName )
{
}
HRESULT CPerfClassList::AddPerfObject( PERF_OBJECT_TYPE* pObj, DWORD dwType, BOOL bCostly )
{
HRESULT hr = WBEM_S_NO_ERROR;
// Create the WMI object
// =====================
CClassElem* pElem = new CClassElem( pObj, dwType, bCostly, m_wstrServiceName, m_pLocaleCache );
CAdapReleaseMe armElem( pElem );
if ( ( NULL != pElem ) && ( pElem->IsOk() ) )
{
hr = AddElement( pElem );
}
else
{
hr = WBEM_E_FAILED;
}
return hr;
}
HRESULT CPerfClassList::AddElement( CClassElem *pEl )
{
HRESULT hr = WBEM_S_NO_ERROR;
CClassElem* pCurrEl = NULL;
BOOL bFound = FALSE;
hr = BeginEnum();
while ( ( WBEM_S_NO_ERROR == Next( &pCurrEl ) ) && ( SUCCEEDED( hr ) ) )
{
CAdapReleaseMe rmCurEl( pCurrEl );
if ( pCurrEl->SameName( pEl ) )
{
bFound = TRUE;
break;
}
}
EndEnum();
if ( bFound )
{
WString wstrClassName;
WString wstrServiceName;
if(FAILED(hr = pEl->GetClassName( wstrClassName ))) return hr;
if(FAILED(hr = pEl->GetServiceName( wstrServiceName ))) return hr;
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
WBEM_MC_ADAP_DUPLICATE_CLASS,
(LPCWSTR)wstrClassName, (LPCWSTR)wstrServiceName );
}
else
{
if (-1 == m_array.Add( pEl )) hr = WBEM_E_OUT_OF_MEMORY;
}
return hr;
}
////////////////////////////////////////////////////////////////////////////////
//
// CMasterClassList
//
////////////////////////////////////////////////////////////////////////////////
CMasterClassList::CMasterClassList( CLocaleCache* pLocaleCache,
CKnownSvcs * pCKnownSvcs)
: CClassList( pLocaleCache ),
m_pKnownSvcs(pCKnownSvcs)
{
if (m_pKnownSvcs)
m_pKnownSvcs->AddRef();
}
CMasterClassList::~CMasterClassList()
{
if (m_pKnownSvcs)
m_pKnownSvcs->Release();
}
// Adds an element to the classlist
HRESULT CMasterClassList::AddClassObject( IWbemClassObject* pObj, BOOL bSourceWMI, BOOL bDelta )
{
HRESULT hr = WBEM_NO_ERROR;
// Create a new class list element
// ===============================
CClassElem* pElem = new CClassElem( pObj, m_pLocaleCache );
CAdapReleaseMe armElem( pElem );
if ( ( NULL != pElem ) && ( pElem->IsOk() ) )
{
if ( bSourceWMI )
{
pElem->SetStatus( ADAP_OBJECT_IS_REGISTERED | ADAP_OBJECT_IS_NOT_IN_PERFLIB );
}
if ( -1 == m_array.Add( pElem ) )
{
hr = WBEM_E_OUT_OF_MEMORY;
}
else
{
pElem->SetKnownSvcs(m_pKnownSvcs);
}
}
else
{
hr = WBEM_E_FAILED;
}
return hr;
}
// Builds a list of class objects that can be located by name
HRESULT CMasterClassList::BuildList( WCHAR* wszBaseClass,
BOOL bDelta,
BOOL bThrottle )
{
HRESULT hr = WBEM_S_NO_ERROR;
CLocaleDefn* pDefn = NULL;
IWbemServices* pNamespace = NULL;
// Create the class enumerator
// ===========================
hr = m_pLocaleCache->GetDefaultDefn( &pDefn );
if (FAILED(hr) || NULL == pDefn) return (FAILED(hr)?hr:WBEM_E_FAILED);
CAdapReleaseMe rmDefn( pDefn );
hr = pDefn->GetNamespace( &pNamespace );
CReleaseMe rmNamespace( pNamespace );
if ( SUCCEEDED( hr ) )
{
BSTR bstrClass = SysAllocString( wszBaseClass );
CSysFreeMe sfmClass(bstrClass);
if ( NULL != bstrClass )
{
IEnumWbemClassObject* pEnum = NULL;
hr = pNamespace->CreateClassEnum( bstrClass,
WBEM_FLAG_SHALLOW,
NULL,
&pEnum );
// Walk the enumerator
// ===================
if ( SUCCEEDED( hr ) )
{
// Set Interface security
// ======================
hr = WbemSetProxyBlanket( pEnum, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL,
RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE );
// Walk the object list in blocks of 100
// =====================================
while ( SUCCEEDED( hr ) && WBEM_S_FALSE != hr)
{
ULONG ulNumReturned = 0;
IWbemClassObject* apObjectArray[100];
ZeroMemory( apObjectArray, sizeof(apObjectArray) );
// Fetch the objects from the enumerator in blocks of 100
// ======================================================
hr = pEnum->Next( WBEM_INFINITE,
100,
apObjectArray,
&ulNumReturned );
// For each object, add it to the class list array
// ===============================================
if ( SUCCEEDED( hr ) && ulNumReturned > 0 )
{
// Add the objects
// ===============
for ( int x = 0; SUCCEEDED( hr ) && x < ulNumReturned; x++ )
{
if (bThrottle )
{
HRESULT hrThr = Throttle(THROTTLE_USER|THROTTLE_IO,
ADAP_IDLE_USER,
ADAP_IDLE_IO,
ADAP_LOOP_SLEEP,
ADAP_MAX_WAIT);
if (THROTTLE_FORCE_EXIT == hrThr)
{
//OutputDebugStringA("(ADAP) Unthrottle command received\n");
bThrottle = FALSE;
UNICODE_STRING BaseUnicodeCommandLine = NtCurrentPeb()->ProcessParameters->CommandLine;
WCHAR * pT = wcschr(BaseUnicodeCommandLine.Buffer,L't');
if (0 == pT)
pT = wcschr(BaseUnicodeCommandLine.Buffer,L'T');
if (pT)
{
*pT = L' ';
pT--;
*pT = L' ';
}
}
}
HRESULT temphr = WBEM_S_NO_ERROR;
_variant_t var;
IWbemClassObject* pObject = apObjectArray[x];
// Only add generic perf counter objects
// =====================================
IWbemQualifierSet* pQualSet = NULL;
hr = pObject->GetQualifierSet( &pQualSet );
CReleaseMe rmQualSet( pQualSet );
if ( SUCCEEDED( hr ) )
{
var = bool(true);
temphr = pQualSet->Get( L"genericperfctr", 0L, &var, NULL );
if ( SUCCEEDED( temphr ) &&
( V_VT(&var) == VT_BOOL ) &&
( V_BOOL(&var) == VARIANT_TRUE ) )
{
hr = AddClassObject( pObject, TRUE, bDelta );
}
}
pObject->Release();
}
// If an add operation failed, release the rest of the pointers
// ============================================================
if ( FAILED( hr ) )
{
for ( ; x < ulNumReturned; x++ )
{
apObjectArray[x]->Release();
}
} // IF FAILED( hr ) )
} // IF Next
} // WHILE enuming
if ( WBEM_S_FALSE == hr )
{
hr = WBEM_S_NO_ERROR;
}
pEnum->Release();
} // IF CreateClassEnum
}
else
{
hr = WBEM_E_OUT_OF_MEMORY;
}
}
return hr;
}
HRESULT CMasterClassList::Merge( CClassList* pClassList, BOOL bDelta )
{
HRESULT hr = WBEM_S_NO_ERROR;
CClassElem* pEl = NULL;
hr = pClassList->BeginEnum();
// Does not return objects marked for deletion
while ( ( WBEM_S_NO_ERROR == pClassList->Next( &pEl ) ) && ( SUCCEEDED( hr ) ) )
{
CAdapReleaseMe rmEl( pEl );
hr = AddElement( pEl, bDelta );
}
pClassList->EndEnum();
return hr;
}
// Cycle through all of the objects and set the inactive status for any object
// with an index between the library's counter index range
HRESULT CMasterClassList::Commit(BOOL bThrottle)
{
HRESULT hr = WBEM_NO_ERROR;
int nEl,
nNumEl = m_array.GetSize();
DWORD dwWait;
dwWait = WaitForSingleObject( g_hAbort, 0 );
if ( WAIT_OBJECT_0 != dwWait )
{
// Validate object's uniqueness in list
// ====================================
for ( nEl = 0; SUCCEEDED( hr ) && nEl < nNumEl; nEl++ )
{
if (bThrottle)
{
HRESULT hrThr = Throttle(THROTTLE_USER|THROTTLE_IO,
ADAP_IDLE_USER,
ADAP_IDLE_IO,
ADAP_LOOP_SLEEP,
ADAP_MAX_WAIT);
if (THROTTLE_FORCE_EXIT == hrThr)
{
//OutputDebugStringA("(ADAP) Unthrottle command received\n");
bThrottle = FALSE;
UNICODE_STRING BaseUnicodeCommandLine = NtCurrentPeb()->ProcessParameters->CommandLine;
WCHAR * pT = wcschr(BaseUnicodeCommandLine.Buffer,L't');
if (0 == pT)
pT = wcschr(BaseUnicodeCommandLine.Buffer,L'T');
if (pT)
{
*pT = L' ';
pT--;
*pT = L' ';
}
}
}
CClassElem* pCurrElem = (CClassElem*)m_array[nEl];
pCurrElem->Commit();
}
}
else
{
hr = WBEM_E_CRITICAL_ERROR;
}
return hr;
}
HRESULT CMasterClassList::AddElement( CClassElem *pEl, BOOL bDelta )
{
HRESULT hr = WBEM_S_NO_ERROR;
CClassElem* pCurrEl = NULL;
BOOL bFound = FALSE;
hr = BeginEnum();
while ( ( WBEM_S_NO_ERROR == Next( &pCurrEl ) ) && ( SUCCEEDED( hr ) ) )
{
CAdapReleaseMe rmCurrEl( pCurrEl );
if ( pCurrEl->SameName( pEl ) )
{
bFound = TRUE;
if ( pCurrEl->SameObject( pEl ) )
{
// Set the satus as found
// ======================
pCurrEl->ClearStatus( ADAP_OBJECT_IS_NOT_IN_PERFLIB );
}
else
{
// Replace the current perflib
// ===========================
pCurrEl->UpdateObj( pEl );
pCurrEl->ClearStatus( ADAP_OBJECT_IS_NOT_IN_PERFLIB | ADAP_OBJECT_IS_REGISTERED );
}
break;
}
}
EndEnum();
if ( !bFound )
{
pEl->SetKnownSvcs(m_pKnownSvcs);
if (-1 == m_array.Add( pEl )) hr = WBEM_E_OUT_OF_MEMORY;
}
return hr;
}
HRESULT
CMasterClassList::ForceStatus(WCHAR* pServiceName,BOOL bSet,DWORD dwStatus)
{
if (NULL == pServiceName) return WBEM_E_INVALID_PARAMETER;
HRESULT hr = WBEM_S_NO_ERROR;
CClassElem* pCurrEl = NULL;
BOOL bFound = FALSE;
hr = BeginEnum();
while ( ( WBEM_S_NO_ERROR == Next( &pCurrEl ) ) && ( SUCCEEDED( hr ) ) )
{
CAdapReleaseMe rmCurrEl( pCurrEl );
WString wstr;
if(FAILED(hr = pCurrEl->GetServiceName(wstr))) break;
if (0 == wbem_wcsicmp((LPWSTR)wstr,pServiceName))
{
DEBUGTRACE((LOG_WMIADAP,"ForeceStatus %S %08x\n",(LPWSTR)wstr,pCurrEl->GetStatus()));
if (bSet){
pCurrEl->SetStatus(dwStatus);
} else {
pCurrEl->ClearStatus(dwStatus);
}
}
}
EndEnum();
return hr;
}
#ifdef _DUMP_LIST
HRESULT
CMasterClassList::Dump()
{
HRESULT hr = WBEM_S_NO_ERROR;
CClassElem* pCurrEl = NULL;
BOOL bFound = FALSE;
hr = BeginEnum();
while ( ( WBEM_S_NO_ERROR == Next( &pCurrEl ) ) && ( SUCCEEDED( hr ) ) )
{
CAdapReleaseMe rmCurrEl( pCurrEl );
WString wstr;
hr = pCurrEl->GetServiceName(wstr);
if(FAILED(hr))
return hr;
WString wstr2;
hr = pCurrEl->GetClassName(wstr2);
if(FAILED(hr))
return hr;
DEBUGTRACE((LOG_WMIADAP,"_DUMP_LIST %S %S\n",(LPWSTR)wstr,(LPWSTR)wstr2));
}
EndEnum();
return hr;
}
#endif