mirror of https://github.com/tongzx/nt5src
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.
2276 lines
65 KiB
2276 lines
65 KiB
/*++
|
|
|
|
Copyright (C) 1999-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
CLASSBROKER.CPP
|
|
|
|
Abstract:
|
|
|
|
History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#include <objbase.h>
|
|
#include <oaidl.h>
|
|
#include <winmgmtr.h>
|
|
#include "adaputil.h"
|
|
#include "classbroker.h"
|
|
|
|
#include <comdef.h>
|
|
|
|
struct _CookingTypeRec
|
|
{
|
|
DWORD dwType;
|
|
WCHAR wcsName[128];
|
|
}
|
|
g_aCookingRecs[] =
|
|
{
|
|
0x00000000, L"PERF_COUNTER_RAWCOUNT_HEX",
|
|
0x00000100, L"PERF_COUNTER_LARGE_RAWCOUNT_HEX",
|
|
0x00000B00, L"PERF_COUNTER_TEXT",
|
|
0x00010000, L"PERF_COUNTER_RAWCOUNT",
|
|
0x00010100, L"PERF_COUNTER_LARGE_RAWCOUNT",
|
|
0x00012000, L"PERF_DOUBLE_RAW",
|
|
0x00400400, L"PERF_COUNTER_DELTA",
|
|
0x00400500, L"PERF_COUNTER_LARGE_DELTA",
|
|
0x00410400, L"PERF_SAMPLE_COUNTER",
|
|
0x00450400, L"PERF_COUNTER_QUEUELEN_TYPE",
|
|
0x00450500, L"PERF_COUNTER_LARGE_QUEUELEN_TYPE",
|
|
0x00550500, L"PERF_COUNTER_100NS_QUEUELEN_TYPE",
|
|
0x00650500, L"PERF_COUNTER_OBJ_TIME_QUEUELEN_TYPE",
|
|
0x10410400, L"PERF_COUNTER_COUNTER",
|
|
0x10410500, L"PERF_COUNTER_BULK_COUNT",
|
|
0x20020400, L"PERF_RAW_FRACTION",
|
|
0x20410500, L"PERF_COUNTER_TIMER",
|
|
0x20470500, L"PERF_PRECISION_SYSTEM_TIMER",
|
|
0x20510500, L"PERF_100NSEC_TIMER",
|
|
0x20570500, L"PERF_PRECISION_100NS_TIMER",
|
|
0x20610500, L"PERF_OBJ_TIME_TIMER",
|
|
0x20670500, L"PERF_PRECISION_OBJECT_TIMER",
|
|
0x20C20400, L"PERF_SAMPLE_FRACTION",
|
|
0x21410500, L"PERF_COUNTER_TIMER_INV",
|
|
0x21510500, L"PERF_100NSEC_TIMER_INV",
|
|
0x22410500, L"PERF_COUNTER_MULTI_TIMER",
|
|
0x22510500, L"PERF_100NSEC_MULTI_TIMER",
|
|
0x23410500, L"PERF_COUNTER_MULTI_TIMER_INV",
|
|
0x23510500, L"PERF_100NSEC_MULTI_TIMER_INV",
|
|
0x30020400, L"PERF_AVERAGE_TIMER",
|
|
0x30240500, L"PERF_ELAPSED_TIME",
|
|
0x40000200, L"PERF_COUNTER_NODATA",
|
|
0x40020500, L"PERF_AVERAGE_BULK",
|
|
0x40030401, L"PERF_SAMPLE_BASE",
|
|
0x40030402, L"PERF_AVERAGE_BASE",
|
|
0x40030403, L"PERF_RAW_BASE",
|
|
0x40030500, L"PERF_PRECISION_TIMESTAMP",
|
|
0x40030503, L"PERF_LARGE_RAW_BASE",
|
|
0x42030500, L"PERF_COUNTER_MULTI_BASE",
|
|
0x80000000, L"PERF_COUNTER_HISTOGRAM_TYPE",
|
|
};
|
|
|
|
HRESULT GetCounterTypeString( DWORD dwType, WCHAR** pwcsString )
|
|
{
|
|
HRESULT hRes = WBEM_E_NOT_FOUND;
|
|
|
|
DWORD dwLeft = 0,
|
|
dwRight = sizeof( g_aCookingRecs ) / sizeof( _CookingTypeRec ),
|
|
dwMid = ( dwLeft + dwRight ) / 2;
|
|
|
|
while ( ( dwLeft <= dwRight ) && FAILED( hRes ) )
|
|
{
|
|
if ( g_aCookingRecs[dwMid].dwType < dwType )
|
|
{
|
|
dwLeft = dwMid + 1;
|
|
}
|
|
else if ( g_aCookingRecs[dwMid].dwType > dwType )
|
|
{
|
|
dwRight = dwMid - 1;
|
|
}
|
|
else
|
|
{
|
|
*pwcsString = g_aCookingRecs[dwMid].wcsName;
|
|
hRes = WBEM_NO_ERROR;
|
|
break;
|
|
}
|
|
|
|
dwMid = ( dwLeft + dwRight ) / 2;
|
|
}
|
|
|
|
return hRes;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CAdapPerfClassElem
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
CClassBroker::CClassBroker( IWbemClassObject* pBaseClass,
|
|
WString wstrClassName,
|
|
CPerfNameDb* pDefaultNameDb )
|
|
: m_pPerfObj( NULL ),
|
|
m_pBaseClass( pBaseClass ),
|
|
m_wstrClassName( wstrClassName ),
|
|
m_pDefaultNameDb( pDefaultNameDb )
|
|
{
|
|
if ( NULL != m_pBaseClass )
|
|
m_pBaseClass->AddRef();
|
|
|
|
if ( NULL != m_pDefaultNameDb )
|
|
m_pDefaultNameDb->AddRef();
|
|
}
|
|
|
|
CClassBroker::CClassBroker( PERF_OBJECT_TYPE* pPerfObj,
|
|
BOOL bCostly,
|
|
IWbemClassObject* pBaseClass,
|
|
CPerfNameDb* pDefaultNameDb,
|
|
WCHAR* pwcsServiceName )
|
|
: m_pPerfObj( pPerfObj ),
|
|
m_bCostly( bCostly ),
|
|
m_pBaseClass( pBaseClass ),
|
|
m_pDefaultNameDb( pDefaultNameDb ),
|
|
m_wstrServiceName( pwcsServiceName )
|
|
{
|
|
if ( NULL != m_pBaseClass )
|
|
m_pBaseClass->AddRef();
|
|
|
|
if ( NULL != m_pDefaultNameDb )
|
|
m_pDefaultNameDb->AddRef();
|
|
}
|
|
|
|
CClassBroker::~CClassBroker()
|
|
{
|
|
if ( NULL != m_pBaseClass )
|
|
m_pBaseClass->Release();
|
|
|
|
if ( NULL != m_pDefaultNameDb )
|
|
m_pDefaultNameDb->Release();
|
|
}
|
|
|
|
HRESULT CClassBroker::Generate( DWORD dwType, IWbemClassObject** ppObj )
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Generates a class based on the object BLOB passed in via the constructor
|
|
//
|
|
// Parameters:
|
|
// ppObj - A pointer to the new class object interface pointer
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
{
|
|
IWbemClassObject* pNewClass = NULL;
|
|
|
|
// Create the new class
|
|
// ====================
|
|
HRESULT hr = m_pBaseClass->SpawnDerivedClass( 0L, &pNewClass );
|
|
CReleaseMe rmNewClass( pNewClass );
|
|
|
|
// And initialize the data
|
|
// =======================
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
// Class name
|
|
// ==========
|
|
hr = SetClassName( dwType, pNewClass );
|
|
|
|
// Class Qualifiers
|
|
// ================
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = SetClassQualifiers( pNewClass, dwType, ( ADAP_DEFAULT_OBJECT == m_pPerfObj->ObjectNameTitleIndex ) );
|
|
}
|
|
|
|
// Standard Properties
|
|
// ===================
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = AddDefaultProperties( pNewClass );
|
|
}
|
|
|
|
// Perf Counter Properties
|
|
// =======================
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = EnumProperties( dwType, pNewClass );
|
|
}
|
|
|
|
// Return the class object interface
|
|
// =================================
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = pNewClass->QueryInterface( IID_IWbemClassObject, (void**) ppObj );
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CClassBroker::SetClassName( DWORD dwType, IWbemClassObject* pClass )
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Sets the name of the new WMI class. The syntax is:
|
|
//
|
|
// Win32_Perf_<servicename>_<displayname>
|
|
//
|
|
// where the service name is the name of the namespace and the display name
|
|
// is the name of the object located in the perf name database
|
|
//
|
|
// Parameters:
|
|
// pClass - The object which requires the name
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
{
|
|
HRESULT hr = WBEM_NO_ERROR;
|
|
|
|
WString wstrObjectName;
|
|
WString wstrTempSvcName;
|
|
|
|
if ( 0 == m_wstrClassName.Length() )
|
|
{
|
|
try
|
|
{
|
|
switch( dwType )
|
|
{
|
|
case WMI_ADAP_RAW_CLASS: m_wstrClassName = ADAP_PERF_RAW_BASE_CLASS L"_"; break;
|
|
case WMI_ADAP_COOKED_CLASS: m_wstrClassName = ADAP_PERF_COOKED_BASE_CLASS L"_"; break;
|
|
default: hr = WBEM_E_INVALID_PARAMETER_ID; break;
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
|
|
// Process the performance class name
|
|
// ==================================
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
// Get the performance class' display name
|
|
// =======================================
|
|
hr = m_pDefaultNameDb->GetDisplayName( m_pPerfObj->ObjectNameTitleIndex, wstrObjectName );
|
|
|
|
// If no object name was returned, then log an error
|
|
// =================================================
|
|
if ( FAILED( hr ) )
|
|
{
|
|
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
|
|
WBEM_MC_ADAP_MISSING_OBJECT_INDEX,
|
|
m_pPerfObj->ObjectNameTitleIndex,
|
|
(LPCWSTR)m_wstrServiceName );
|
|
}
|
|
|
|
// Replace reserved characters with proper names
|
|
// =============================================
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = ReplaceReserved( wstrObjectName );
|
|
}
|
|
|
|
// Remove whitespace and extraneous characters
|
|
// ===========================================
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = RemoveWhitespaceAndNonAlphaNum( wstrObjectName );
|
|
}
|
|
}
|
|
|
|
// Now do the same for the service name
|
|
// ====================================
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
// Get the service name
|
|
// ====================
|
|
wstrTempSvcName = m_wstrServiceName;
|
|
|
|
// Replace reserved characters with proper names
|
|
// =============================================
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = ReplaceReserved( wstrTempSvcName );
|
|
}
|
|
|
|
// Remove whitespace and extraneous characters
|
|
// ===========================================
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = RemoveWhitespaceAndNonAlphaNum( wstrTempSvcName );
|
|
}
|
|
}
|
|
|
|
// Now we can build the rest of the name and try setting it in the object
|
|
// ======================================================================
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
try
|
|
{
|
|
m_wstrClassName += wstrTempSvcName;
|
|
m_wstrClassName += L"_";
|
|
m_wstrClassName += wstrObjectName;
|
|
if ( m_bCostly )
|
|
{
|
|
m_wstrClassName += "_Costly";
|
|
}
|
|
|
|
}
|
|
catch( ... )
|
|
{
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Set the class name in the WMI object
|
|
// ====================================
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
_variant_t var = (LPWSTR) m_wstrClassName;
|
|
hr = pClass->Put( L"__CLASS", 0L, &var, CIM_STRING );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CClassBroker::RemoveWhitespaceAndNonAlphaNum( WString& wstr )
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Removes spaces, tabs, etc. and non-alphanumeric characters from the
|
|
// input string
|
|
//
|
|
// Parameters:
|
|
// wstr - The string to be processed
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
WCHAR* pWstr = wstr.UnbindPtr();
|
|
|
|
CVectorDeleteMe<WCHAR> vdmWstr( pWstr );
|
|
|
|
if ( NULL != pWstr )
|
|
{
|
|
try
|
|
{
|
|
WCHAR* pNewWstr = new WCHAR[lstrlenW(pWstr) + 1];
|
|
|
|
int x = 0,
|
|
y = 0;
|
|
|
|
// Dump all of the leading, trailing and internal whitespace
|
|
// =========================================================
|
|
for ( ; NULL != pWstr[x]; x++ )
|
|
{
|
|
if ( !iswspace( pWstr[x] ) && isunialphanum( pWstr[x] ) )
|
|
{
|
|
pNewWstr[y] = pWstr[x];
|
|
y++;
|
|
}
|
|
}
|
|
|
|
pNewWstr[y] = NULL;
|
|
|
|
// This will cause the WString to acquire the new pointer
|
|
// ======================================================
|
|
wstr.BindPtr( pNewWstr );
|
|
}
|
|
catch(...)
|
|
{
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CClassBroker::ReplaceReserved( WString& wstr )
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// This is a 2-pass filter. First we must determine the size of the new buffer by counting
|
|
// the number of replacement candidates, and, after creating the new buffer, we copy the
|
|
// data, replacing the restricted characters where required.
|
|
//
|
|
// Replaces:
|
|
// "/" with "Per",
|
|
// "%" with "Percent",
|
|
// "#" with "Number",
|
|
// "@" with "At",
|
|
// "&" with "And"
|
|
//
|
|
// Parameters:
|
|
// wstr - String to be processed
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
int x = 0,
|
|
y = 0;
|
|
|
|
// Get the data buffer for processing
|
|
// ==================================
|
|
WCHAR* pWstr = wstr.UnbindPtr();
|
|
|
|
CVectorDeleteMe<WCHAR> vdmWstr( pWstr );
|
|
|
|
if ( NULL != pWstr )
|
|
{
|
|
// First pass: Count the number of reserved characters
|
|
// ===================================================
|
|
DWORD dwNumSlashes = 0,
|
|
dwNumPercent = 0,
|
|
dwNumAt = 0,
|
|
dwNumNumber = 0,
|
|
dwNumAmper = 0,
|
|
dwNumReserved = 0;
|
|
|
|
for ( ; NULL != pWstr[x]; x++ )
|
|
{
|
|
switch ( pWstr[x] )
|
|
{
|
|
case L'/': dwNumSlashes++; dwNumReserved++; break;
|
|
case L'%': dwNumPercent++; dwNumReserved++; break;
|
|
case L'@': dwNumAt++; dwNumReserved++; break;
|
|
case L'#': dwNumNumber++; dwNumReserved++; break;
|
|
case L'&': dwNumAmper++; dwNumReserved++; break;
|
|
default: break;
|
|
}
|
|
}
|
|
|
|
try
|
|
{
|
|
// Create the new buffer
|
|
// =====================
|
|
DWORD dwBuffSize = lstrlenW(pWstr) + 1 + ( 3 * dwNumSlashes ) + ( 7 * dwNumPercent ) +
|
|
( 2 * dwNumAt ) + ( 6 * dwNumNumber ) + ( 3 * dwNumAmper );
|
|
|
|
WCHAR* pNewWstr = new WCHAR[dwBuffSize];
|
|
|
|
// Second pass: Replace reserved characters
|
|
// ========================================
|
|
for ( x = 0; NULL != pWstr[x]; x++ )
|
|
{
|
|
BOOL AllIsUpper = FALSE;
|
|
DWORD Cnt;
|
|
switch ( pWstr[x] )
|
|
{
|
|
case L'/':
|
|
// if all characters up to the end of string or to the next space are uppercase
|
|
for (Cnt=1;pWstr[x+Cnt] && pWstr[x+Cnt]!=' ';Cnt++)
|
|
{
|
|
if (isupper(pWstr[x+Cnt]))
|
|
{
|
|
AllIsUpper = TRUE;
|
|
}
|
|
else
|
|
{
|
|
AllIsUpper = FALSE;
|
|
break;
|
|
}
|
|
};
|
|
if (!AllIsUpper)
|
|
{
|
|
lstrcpyW( &pNewWstr[y], L"Per" );
|
|
y+=3;
|
|
}
|
|
else
|
|
{
|
|
x++;
|
|
pNewWstr[y]=pWstr[x];
|
|
y++;
|
|
}
|
|
break;
|
|
case L'%': lstrcpyW( &pNewWstr[y], L"Percent" ); y+=7; break;
|
|
case L'@': lstrcpyW( &pNewWstr[y], L"At" ); y+=2; break;
|
|
case L'#': lstrcpyW( &pNewWstr[y], L"Number" ); y+=6; break;
|
|
case L'&': lstrcpyW( &pNewWstr[y], L"And" ); y+=3; break;
|
|
default: pNewWstr[y] = pWstr[x]; y++; break;
|
|
}
|
|
}
|
|
|
|
pNewWstr[y] = NULL;
|
|
|
|
// This will cause the WString to acquire the new pointer
|
|
// ======================================================
|
|
wstr.BindPtr( pNewWstr );
|
|
}
|
|
catch(...)
|
|
{
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CLocaleClassBroker
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
CLocaleClassBroker::CLocaleClassBroker( IWbemClassObject* pBaseClass,
|
|
WString wstrClassName,
|
|
CPerfNameDb* pDefaultNameDb,
|
|
CPerfNameDb* pLocaleNameDb )
|
|
: CClassBroker( pBaseClass, wstrClassName, pDefaultNameDb ),
|
|
m_pLocaleNameDb( pLocaleNameDb )
|
|
{
|
|
if ( NULL != m_pLocaleNameDb )
|
|
m_pLocaleNameDb->AddRef();
|
|
}
|
|
|
|
CLocaleClassBroker::CLocaleClassBroker( PERF_OBJECT_TYPE* pPerfObj,
|
|
BOOL bCostly,
|
|
IWbemClassObject* pBaseClass,
|
|
CPerfNameDb* pDefaultNameDb,
|
|
CPerfNameDb* pLocaleNameDb,
|
|
LANGID LangId,
|
|
WCHAR* pwcsServiceName )
|
|
: m_pLocaleNameDb( pLocaleNameDb ), m_LangId( LangId ),
|
|
CClassBroker( pPerfObj, bCostly, pBaseClass, pDefaultNameDb, pwcsServiceName )
|
|
{
|
|
if ( NULL != m_pLocaleNameDb )
|
|
m_pLocaleNameDb->AddRef();
|
|
}
|
|
|
|
CLocaleClassBroker::~CLocaleClassBroker()
|
|
{
|
|
if ( NULL != m_pLocaleNameDb )
|
|
m_pLocaleNameDb->Release();
|
|
}
|
|
|
|
HRESULT CLocaleClassBroker::SetClassQualifiers( IWbemClassObject* pClass, DWORD dwType, BOOL fIsDefault )
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Sets the class' qualifiers per the localized object rules. Note that the operations
|
|
// are performed directly on the IWbemClassObject
|
|
//
|
|
// The following qualifiers will be added:
|
|
// - Amendment
|
|
// - Locale(0x0409)
|
|
// - DisplayName (Amended flavor)
|
|
// - Genericperfctr (signals that this is a generic counter)
|
|
//
|
|
// Parameters:
|
|
// pClass - The object to be massaged
|
|
// fIsDefault - Indicator for the default object (not used in localized objects)
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
_variant_t var;
|
|
|
|
try
|
|
{
|
|
IWbemQualifierSet* pQualSet = NULL;
|
|
hr = pClass->GetQualifierSet( &pQualSet );
|
|
CReleaseMe rmQualSet( pQualSet );
|
|
|
|
// Amendment
|
|
// =========
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
var = (bool)true;
|
|
hr = pQualSet->Put( L"Amendment", &var, 0L );
|
|
}
|
|
|
|
// Locale
|
|
// ======
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
var.Clear();
|
|
V_VT(&var) = VT_I4;
|
|
V_I4(&var) = m_LangId;
|
|
hr = pQualSet->Put( L"locale", &var, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
}
|
|
|
|
// DisplayName
|
|
// ===========
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
LPCWSTR pwcsDisplayName = NULL;
|
|
|
|
var.Clear();
|
|
|
|
// Fetch the name from the Names' database
|
|
// =======================================
|
|
hr = m_pLocaleNameDb->GetDisplayName( m_pPerfObj->ObjectNameTitleIndex, &pwcsDisplayName );
|
|
|
|
// If this is a localized Db, this is a benign error. We will just pull the value
|
|
// from the default db (it must be there, we wouldn't have a class name if it didn't
|
|
// =================================================================================
|
|
if ( FAILED( hr ) )
|
|
{
|
|
hr = m_pDefaultNameDb->GetDisplayName( m_pPerfObj->ObjectNameTitleIndex, &pwcsDisplayName );
|
|
}
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
var = (LPWSTR) pwcsDisplayName ;
|
|
hr = pQualSet->Put( L"DisplayName", &var, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE | WBEM_FLAVOR_AMENDED );
|
|
}
|
|
}
|
|
|
|
// Genericperfctr
|
|
// ==============
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
var = (bool)true;
|
|
hr = pQualSet->Put( L"genericperfctr", &var, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
}
|
|
|
|
// Perfindex
|
|
// =========
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
var.Clear();
|
|
V_VT(&var) = VT_I4;
|
|
V_I4(&var) = m_pPerfObj->ObjectNameTitleIndex;
|
|
hr = pQualSet->Put( L"perfindex", (VARIANT*)&var, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
}
|
|
|
|
}
|
|
catch(...)
|
|
{
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
|
|
if ( FAILED( hr ) )
|
|
{
|
|
// Something whacky happened: log an event
|
|
// =======================================
|
|
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
|
|
WBEM_MC_ADAP_GENERAL_OBJECT_FAILURE,
|
|
(LPCWSTR)m_wstrClassName,
|
|
(LPCWSTR)m_wstrServiceName,
|
|
CHex( hr ) );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CLocaleClassBroker::AddDefaultProperties( IWbemClassObject* pObj )
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Ignored for localized classes
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
{
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
HRESULT CLocaleClassBroker::EnumProperties( DWORD dwType, IWbemClassObject* pObj )
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Ignored for localized classes
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
{
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
HRESULT CLocaleClassBroker::SetPropertyQualifiers( PERF_COUNTER_DEFINITION* pCtrDefinition,
|
|
DWORD dwType,
|
|
BOOL fIsDefault,
|
|
LPCWSTR pwcsPropertyName,
|
|
IWbemClassObject* pClass,
|
|
BOOL bBase )
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Adds localization qualifiers for the counter properties
|
|
//
|
|
// The following qualifiers will be added:
|
|
// - DisplayName (Amended flavor)
|
|
//
|
|
// Properties:
|
|
// pCtrDefinition - The portion of the performance blob related to the property
|
|
// fIsDefault - Flag identifying default property
|
|
// pwcsPropertyName - The name of the property
|
|
// pClass - The WMI class containing the property
|
|
// bBase - Base property identifier
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
_variant_t var;
|
|
_variant_t varHelp;
|
|
|
|
try
|
|
{
|
|
// DisplayName
|
|
// ===========
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
LPCWSTR pwcsDisplayName = NULL;
|
|
LPCWSTR pwcsHelpName = NULL;
|
|
|
|
// Fetch the name from the Names' database
|
|
// =======================================
|
|
if ( !bBase )
|
|
{
|
|
hr = m_pLocaleNameDb->GetDisplayName( pCtrDefinition->CounterNameTitleIndex, &pwcsDisplayName );
|
|
|
|
// If this is a localized Db, this is a benign error. We will just pull the value
|
|
// from the default db (it must be there, we wouldn't have a class name if it didn't
|
|
// =================================================================================
|
|
if ( FAILED( hr ) )
|
|
{
|
|
hr = m_pDefaultNameDb->GetDisplayName( pCtrDefinition->CounterNameTitleIndex, &pwcsDisplayName );
|
|
}
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
var = (LPWSTR) pwcsDisplayName ;
|
|
}
|
|
|
|
hr = m_pLocaleNameDb->GetHelpName( pCtrDefinition->CounterHelpTitleIndex, &pwcsHelpName );
|
|
|
|
// If this is a localized Db, this is a benign error. We will just pull the value
|
|
// from the default db (it must be there, we wouldn't have a class name if it didn't
|
|
// =================================================================================
|
|
if ( FAILED( hr ) )
|
|
{
|
|
hr = m_pDefaultNameDb->GetHelpName( pCtrDefinition->CounterHelpTitleIndex, &pwcsHelpName );
|
|
}
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
varHelp = (LPWSTR) pwcsHelpName ;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
var = L"";
|
|
varHelp = L"";
|
|
}
|
|
|
|
// Set the qualifier
|
|
// =================
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
IWbemQualifierSet* pQualSet = NULL;
|
|
hr = pClass->GetPropertyQualifierSet( pwcsPropertyName, &pQualSet );
|
|
CReleaseMe rmQualSet( pQualSet );
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = pQualSet->Put( L"DisplayName", &var,
|
|
WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE | WBEM_FLAVOR_AMENDED );
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pQualSet->Put( L"Description", &varHelp,
|
|
WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE | WBEM_FLAVOR_AMENDED );
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
|
|
if ( FAILED( hr ) )
|
|
{
|
|
// Something whacky happened: log an event
|
|
// =======================================
|
|
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
|
|
WBEM_MC_ADAP_GENERAL_OBJECT_FAILURE,
|
|
(LPCWSTR)m_wstrClassName,
|
|
(LPCWSTR)m_wstrServiceName,
|
|
CHex( hr ) );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CLocaleClassBroker::AddProperty( PERF_COUNTER_DEFINITION* pCtrDefinition,
|
|
DWORD dwType,
|
|
BOOL fIsDefault,
|
|
IWbemClassObject* pClass,
|
|
WString &wstrLastCtrName,
|
|
BOOL* pbLastCounterIsNotBase )
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Ignored for localized classes
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
{
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
HRESULT CLocaleClassBroker::GenPerfClass( PERF_OBJECT_TYPE* pPerfObj,
|
|
DWORD dwType,
|
|
BOOL bCostly,
|
|
IWbemClassObject* pBaseClass,
|
|
CPerfNameDb* pDefaultNameDb,
|
|
CPerfNameDb* pLocaleNameDb,
|
|
LANGID LangId,
|
|
WCHAR* pwcsServiceName,
|
|
IWbemClassObject** ppObj)
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// A static member of the broker. It generates a WMI class based on the
|
|
// object BLOB.
|
|
//
|
|
// Parameters:
|
|
// pPerfObj - The object BLOB
|
|
// bCostly - Costly object indicator
|
|
// pBaseClass - The new object's base class
|
|
// pDefaultNameDb - The default language names' database
|
|
// pLocaleNameDb - The localized language names' database
|
|
// LangId - The locale ID
|
|
// pwcsServiceName - The name of the perflib service
|
|
// ppObj - A pointer to the new class object interface pointer
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
IWbemClassObject* pObject = NULL;
|
|
CLocaleClassBroker Broker( pPerfObj, bCostly, pBaseClass, pDefaultNameDb, pLocaleNameDb, LangId, pwcsServiceName );
|
|
|
|
hr = Broker.Generate( dwType, &pObject );
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
*ppObj = pObject;
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CLocaleClassBroker::ConvertToLocale( IWbemClassObject* pDefaultClass,
|
|
CLocaleDefn* pLocaleDefn,
|
|
CLocaleDefn* pDefaultDefn,
|
|
IWbemClassObject** ppObject)
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// A static member of the broker. It generates a new localized class based
|
|
// on the default object
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
{
|
|
// TODO: Break this up into smaller methods
|
|
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
_variant_t var;
|
|
int nLocale = 0;
|
|
int nPerfIndex = 0;
|
|
int nHelpIndex = 0;
|
|
WString wstrClassName;
|
|
DWORD dwType = WMI_ADAP_RAW_CLASS;
|
|
|
|
CPerfNameDb* pLocaleNameDb = NULL;
|
|
CPerfNameDb* pDefaultNameDb = NULL;
|
|
|
|
// Get references to the localized name's databases
|
|
// ================================================
|
|
hr = pLocaleDefn->GetNameDb( &pLocaleNameDb );
|
|
CAdapReleaseMe armLocaleNameDb( pLocaleNameDb );
|
|
|
|
// Get references to the default name's databases
|
|
// ==============================================
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = pDefaultDefn->GetNameDb( &pDefaultNameDb );
|
|
}
|
|
|
|
CAdapReleaseMe armDefaultNameDb( pDefaultNameDb );
|
|
|
|
// Get the locale ID
|
|
// =================
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = pLocaleDefn->GetLID( &nLocale );
|
|
}
|
|
|
|
// Get the object's perf index
|
|
// ===========================
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
IWbemQualifierSet* pQualSet = NULL;
|
|
hr = pDefaultClass->GetQualifierSet( &pQualSet );
|
|
CReleaseMe rmQualSet( pQualSet );
|
|
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = pQualSet->Get( L"perfindex", 0L, &var, NULL );
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
nPerfIndex = V_I4(&var);
|
|
}
|
|
else
|
|
{
|
|
// see InitializeMembers
|
|
nPerfIndex = 0;
|
|
hr = WBEM_S_FALSE;
|
|
|
|
}
|
|
}
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = pQualSet->Get( L"helpindex", 0L, &var, NULL );
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
nHelpIndex = V_I4(&var);
|
|
}
|
|
else
|
|
{
|
|
// see InitializeMembers
|
|
nHelpIndex = 0;
|
|
hr = WBEM_S_FALSE;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = pQualSet->Get( L"Cooked", 0L, &var, NULL );
|
|
|
|
if ( SUCCEEDED( hr ) && ( V_BOOL(&var) == VARIANT_TRUE ) )
|
|
{
|
|
dwType = WMI_ADAP_COOKED_CLASS;
|
|
}
|
|
else
|
|
{
|
|
dwType = WMI_ADAP_RAW_CLASS;
|
|
hr = WBEM_S_FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Get the class name
|
|
// ==================
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
var.Clear();
|
|
hr = pDefaultClass->Get( L"__CLASS", 0L, &var, NULL, NULL );
|
|
|
|
wstrClassName = V_BSTR(&var);
|
|
|
|
}
|
|
|
|
// Create locaized class
|
|
// =====================
|
|
IWbemClassObject* pBaseClass = NULL;
|
|
IWbemClassObject* pLocaleClass = NULL;
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = pLocaleDefn->GetBaseClass( dwType, &pBaseClass );
|
|
CReleaseMe rmBaseClass( pBaseClass );
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = pBaseClass->SpawnDerivedClass( 0L, &pLocaleClass );
|
|
}
|
|
}
|
|
|
|
// Initialize the data
|
|
// ===================
|
|
|
|
// Set the name
|
|
// ============
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
var.Clear();
|
|
var = LPCWSTR(wstrClassName);
|
|
|
|
hr = pLocaleClass->Put( L"__CLASS", 0L, &var, CIM_STRING );
|
|
|
|
}
|
|
|
|
// Set Qualifiers
|
|
// ==============
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
IWbemQualifierSet* pQualSet = NULL;
|
|
hr = pLocaleClass->GetQualifierSet( &pQualSet );
|
|
CReleaseMe rmQualSet( pQualSet );
|
|
|
|
// Amendment
|
|
// =========
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
var.Clear();
|
|
|
|
var = bool(true);
|
|
hr = pQualSet->Put( L"Amendment", &var, 0L );
|
|
}
|
|
|
|
// Locale
|
|
// ======
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
var.Clear();
|
|
V_VT(&var) = VT_I4;
|
|
V_I4(&var) = nLocale;
|
|
hr = pQualSet->Put( L"locale", &var, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
}
|
|
|
|
|
|
// DisplayName
|
|
// ===========
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
LPCWSTR pwcsDisplayName = NULL;
|
|
|
|
hr = pLocaleNameDb->GetDisplayName( nPerfIndex, &pwcsDisplayName );
|
|
|
|
// If this is a localized Db, this is a benign error. We will just pull the value
|
|
// from the default db (it must be there, we wouldn't have a class name if it didn't
|
|
// =================================================================================
|
|
if ( FAILED( hr ) )
|
|
{
|
|
hr = pDefaultNameDb->GetDisplayName( nPerfIndex, &pwcsDisplayName );
|
|
}
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
var.Clear();
|
|
|
|
var = (WCHAR *)( pwcsDisplayName );
|
|
hr = pQualSet->Put( L"DisplayName", &var,
|
|
WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE | WBEM_FLAVOR_AMENDED );
|
|
|
|
}
|
|
else
|
|
{
|
|
// the nPerfInedx was bad
|
|
ERRORTRACE((LOG_WMIADAP,"class %S: DisplayName for counter %d not found\n",(WCHAR *)wstrClassName,nPerfIndex));
|
|
}
|
|
}
|
|
|
|
|
|
// Description
|
|
// ===========
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
LPCWSTR pwcsHelpName = NULL;
|
|
|
|
hr = pLocaleNameDb->GetHelpName( nHelpIndex, &pwcsHelpName );
|
|
|
|
// If this is a localized Db, this is a benign error. We will just pull the value
|
|
// from the default db (it must be there, we wouldn't have a class name if it didn't
|
|
// =================================================================================
|
|
if ( FAILED( hr ) )
|
|
{
|
|
hr = pDefaultNameDb->GetHelpName( nHelpIndex, &pwcsHelpName );
|
|
}
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
var.Clear();
|
|
|
|
var = (WCHAR *)( pwcsHelpName );
|
|
hr = pQualSet->Put( L"Description", &var,
|
|
WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE | WBEM_FLAVOR_AMENDED );
|
|
|
|
}
|
|
else
|
|
{
|
|
// the nPerfInedx was bad
|
|
ERRORTRACE((LOG_WMIADAP,"class %S: Description for counter %d not found\n",(WCHAR *)wstrClassName,nPerfIndex));
|
|
}
|
|
}
|
|
|
|
// Genericperfctr
|
|
// ==============
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
var.Clear();
|
|
var = bool(true);
|
|
hr = pQualSet->Put( L"genericperfctr", &var, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
}
|
|
}
|
|
|
|
// Set Properties
|
|
// ==============
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
|
|
BSTR bstrPropName;
|
|
|
|
pDefaultClass->BeginEnumeration( WBEM_FLAG_LOCAL_ONLY );
|
|
|
|
while ( WBEM_S_NO_ERROR == pDefaultClass->Next( 0, &bstrPropName, NULL, NULL, NULL ) )
|
|
{
|
|
var.Clear();
|
|
|
|
CIMTYPE ct;
|
|
int nCounterIndex = 0;
|
|
int nHelpIndex2 = 0;
|
|
WString wstrDefaultPropDisplayName;
|
|
|
|
// Create the property based upon the default property
|
|
// ===================================================
|
|
V_VT(&var) = VT_NULL;
|
|
V_I8(&var) = 0;
|
|
|
|
hr = pDefaultClass->Get( bstrPropName, 0L, NULL, &ct, NULL );
|
|
hr = pLocaleClass->Put( bstrPropName, 0L, (VARIANT*)&var, ct );
|
|
|
|
// Grab the default property qualifier set
|
|
// =======================================
|
|
IWbemQualifierSet* pQualSet = NULL;
|
|
hr = pDefaultClass->GetPropertyQualifierSet( bstrPropName, &pQualSet );
|
|
CReleaseMe rmQualSet( pQualSet );
|
|
|
|
|
|
// Get the default perfindex to be (used to retrieve the display
|
|
// name from the localized names' database)
|
|
// =============================================================
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = pQualSet->Get( L"perfindex", 0L, &var, NULL );
|
|
nCounterIndex = V_UI4(&var);
|
|
}
|
|
|
|
// DisplayName
|
|
// ===========
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
LPCWSTR pwcsDisplayName = NULL;
|
|
|
|
hr = pLocaleNameDb->GetDisplayName( nCounterIndex, &pwcsDisplayName );
|
|
|
|
// If this is a localized Db, this is a benign error. We will just pull the value
|
|
// from the default db (it must be there, we wouldn't have a class name if it didn't
|
|
// =================================================================================
|
|
if ( FAILED( hr ) )
|
|
{
|
|
hr = pDefaultNameDb->GetDisplayName( nCounterIndex, &pwcsDisplayName );
|
|
}
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
IWbemQualifierSet* pLocaleQualSet = NULL;
|
|
hr = pLocaleClass->GetPropertyQualifierSet( bstrPropName, &pLocaleQualSet );
|
|
CReleaseMe rmLocaleQualSet( pLocaleQualSet );
|
|
|
|
var = (WCHAR *)( pwcsDisplayName );
|
|
hr = pLocaleQualSet->Put( L"DisplayName", &var,
|
|
WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE | WBEM_FLAVOR_AMENDED );
|
|
|
|
}
|
|
else
|
|
{
|
|
ERRORTRACE((LOG_WMIADAP,"class %S: Display for counter %d not found\n",(WCHAR *)wstrClassName,nCounterIndex));
|
|
}
|
|
}
|
|
|
|
// HelpIndex
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
var.Clear();
|
|
hr = pQualSet->Get( L"helpindex", 0L, &var, NULL );
|
|
nHelpIndex2 = V_UI4(&var);
|
|
}
|
|
|
|
// Description
|
|
// ===========
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
LPCWSTR pwcsHelpName = NULL;
|
|
|
|
hr = pLocaleNameDb->GetHelpName( nHelpIndex2, &pwcsHelpName );
|
|
|
|
// If this is a localized Db, this is a benign error. We will just pull the value
|
|
// from the default db (it must be there, we wouldn't have a class name if it didn't
|
|
// =================================================================================
|
|
if ( FAILED( hr ) )
|
|
{
|
|
hr = pDefaultNameDb->GetHelpName( nHelpIndex2, &pwcsHelpName );
|
|
}
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
IWbemQualifierSet* pLocaleQualSet = NULL;
|
|
hr = pLocaleClass->GetPropertyQualifierSet( bstrPropName, &pLocaleQualSet );
|
|
CReleaseMe rmLocaleQualSet( pLocaleQualSet );
|
|
|
|
var = (WCHAR *)( pwcsHelpName );
|
|
hr = pLocaleQualSet->Put( L"Description", &var,
|
|
WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE | WBEM_FLAVOR_AMENDED );
|
|
|
|
}
|
|
else
|
|
{
|
|
ERRORTRACE((LOG_WMIADAP,"class %S: Description for counter %d not found\n",(WCHAR *)wstrClassName,nCounterIndex));
|
|
}
|
|
}
|
|
|
|
SysFreeString( bstrPropName );
|
|
}
|
|
|
|
pDefaultClass->EndEnumeration();
|
|
}
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
*ppObject = pLocaleClass;
|
|
|
|
if ( NULL != *ppObject )
|
|
(*ppObject)->AddRef();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CDefaultClassBroker
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
HRESULT CDefaultClassBroker::SetClassQualifiers( IWbemClassObject* pClass, DWORD dwType, BOOL fIsDefault )
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Sets the class' qualifiers. Note that the operations are performed directly on the
|
|
// IWbemClassObject.
|
|
//
|
|
// The following qualifiers will be added:
|
|
// - Dynamic
|
|
// - Provider("NT5_GenericPerfProvider_V1")
|
|
// - Registrykey
|
|
// - Locale(0x0409)
|
|
// - Perfindex
|
|
// - Helpindex
|
|
// - Perfdetail
|
|
// - Genericperfctr (signals that this is a generic counter)
|
|
// - Singleton (if applicable)
|
|
// - Costly (if applicable)
|
|
//
|
|
// Parameters:
|
|
// pClass - The object to be massaged
|
|
// fIsDefault - Indicator for the default object (not used in localized objects)
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
_variant_t var;
|
|
|
|
try
|
|
{
|
|
IWbemQualifierSet* pQualSet = NULL;
|
|
hr = pClass->GetQualifierSet( &pQualSet );
|
|
CReleaseMe rmQualSet( pQualSet );
|
|
|
|
switch ( dwType )
|
|
{
|
|
case WMI_ADAP_RAW_CLASS:
|
|
{
|
|
// Default
|
|
// =======
|
|
if ( SUCCEEDED( hr ) && fIsDefault )
|
|
{
|
|
var = bool(true);
|
|
hr = pQualSet->Put( L"perfdefault", &var, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
}
|
|
|
|
// Dynamic
|
|
// =======
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
var = bool(true);
|
|
hr = pQualSet->Put( L"dynamic", &var, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
}
|
|
|
|
// Provider
|
|
// ========
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
var = L"Nt5_GenericPerfProvider_V1";
|
|
hr = pQualSet->Put( L"provider", &var, 0L );
|
|
}
|
|
|
|
// Registrykey
|
|
// ===========
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
var = (WCHAR *)(m_wstrServiceName);
|
|
hr = pQualSet->Put( L"registrykey", &var, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
}
|
|
|
|
// Locale
|
|
// ======
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
var.Clear();
|
|
V_VT(&var) = VT_I4;
|
|
V_I4(&var) = 0x0409;
|
|
hr = pQualSet->Put( L"locale", &var, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
}
|
|
|
|
// Perfindex
|
|
// =========
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
V_VT(&var) = VT_I4;
|
|
V_I4(&var) = m_pPerfObj->ObjectNameTitleIndex;
|
|
hr = pQualSet->Put( L"perfindex", &var, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
}
|
|
|
|
// Helpindex
|
|
// =========
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
V_VT(&var) = VT_I4;
|
|
V_I4(&var) = m_pPerfObj->ObjectHelpTitleIndex;
|
|
hr = pQualSet->Put( L"helpindex", &var, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
}
|
|
|
|
#ifdef _PM_CHANGED_THEIR_MIND_
|
|
|
|
// Description
|
|
// ==========
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
HRESULT hr2;
|
|
LPCWSTR pwcsHelpName = NULL;
|
|
hr2 = m_pDefaultNameDb->GetHelpName( m_pPerfObj->ObjectHelpTitleIndex, &pwcsHelpName );
|
|
var = (WCHAR *)pwcsHelpName;
|
|
|
|
if (SUCCEEDED(hr2))
|
|
{
|
|
hr = pQualSet->Put( L"Description", &var, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
}
|
|
else
|
|
{
|
|
ERRORTRACE((LOG_WMIADAP,"class %S: Help for counter %d not found\n",(WCHAR *)m_wstrClassName,m_pPerfObj->ObjectHelpTitleIndex));
|
|
}
|
|
var.Clear();
|
|
}
|
|
#endif
|
|
// Perfdetail
|
|
// ==========
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
V_VT(&var) = VT_I4;
|
|
V_I4(&var) = m_pPerfObj->DetailLevel;
|
|
hr = pQualSet->Put( L"perfdetail", &var, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
}
|
|
|
|
// Genericperfctr
|
|
// ==============
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
var = bool(true);
|
|
hr = pQualSet->Put( L"genericperfctr", &var, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
}
|
|
|
|
// HiPerf
|
|
// ==============
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
var = bool(true);
|
|
hr = pQualSet->Put( L"hiperf", &var, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
}
|
|
|
|
// Singleton (set if the numinstances is PERF_NO_INSTANCES)
|
|
// ========================================================
|
|
if ( SUCCEEDED(hr) && IsSingleton( ) )
|
|
{
|
|
|
|
var = bool(true);
|
|
// This will have default flavors
|
|
hr = pQualSet->Put( L"singleton", &var, 0L );
|
|
}
|
|
|
|
// Costly
|
|
// ======
|
|
if ( SUCCEEDED(hr) && m_bCostly )
|
|
{
|
|
var = bool(true);
|
|
hr = pQualSet->Put( L"costly", &var, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
}
|
|
}break;
|
|
|
|
case WMI_ADAP_COOKED_CLASS:
|
|
{
|
|
var.Clear();
|
|
|
|
// Dynamic
|
|
// =======
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
var = bool(true);
|
|
hr = pQualSet->Put( L"dynamic", &var, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
}
|
|
|
|
// Provider
|
|
// ========
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
var = L"HiPerfCooker_v1";
|
|
hr = pQualSet->Put( L"provider", &var, 0L );
|
|
}
|
|
|
|
// Locale
|
|
// ======
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
var.Clear();
|
|
|
|
V_VT(&var) = VT_I4;
|
|
V_I4(&var) = 0x0409;
|
|
hr = pQualSet->Put( L"locale", &var, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
}
|
|
|
|
// Registrykey
|
|
// ===========
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
var.Clear();
|
|
var = (WCHAR *)( m_wstrServiceName );
|
|
hr = pQualSet->Put( L"registrykey", &var, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
}
|
|
|
|
// Cooked
|
|
// ======
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
var.Clear();
|
|
var = bool(true);
|
|
hr = pQualSet->Put( L"Cooked", &var, 0 );
|
|
}
|
|
|
|
// AutoCook
|
|
// ========
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
V_VT(&var) = VT_I4;
|
|
V_I4(&var) = 1 ;
|
|
hr = pQualSet->Put( L"AutoCook", &var, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
}
|
|
|
|
// Genericperfctr
|
|
// ==============
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
var = bool(true);
|
|
hr = pQualSet->Put( L"genericperfctr", &var, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
}
|
|
|
|
// HiPerf
|
|
// ==============
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
var = bool(true);
|
|
hr = pQualSet->Put( L"hiperf", &var, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
}
|
|
|
|
// AutoCook_RawClass
|
|
// =================
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
_variant_t varClassName;
|
|
hr = pClass->Get( L"__CLASS", 0, &varClassName, 0, 0 );
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
WCHAR* wszRawClass = NULL;
|
|
WCHAR* wszClassRoot = varClassName.bstrVal + wcslen ( ADAP_PERF_COOKED_BASE_CLASS );
|
|
|
|
wszRawClass = new WCHAR[ wcslen( wszClassRoot ) + wcslen( ADAP_PERF_RAW_BASE_CLASS ) + 1 ];
|
|
CDeleteMe<WCHAR> dmRawClass( wszRawClass );
|
|
|
|
swprintf( wszRawClass, L"%s%s", ADAP_PERF_RAW_BASE_CLASS, wszClassRoot );
|
|
|
|
var = wszRawClass;
|
|
hr = pQualSet->Put( L"AutoCook_RawClass",
|
|
&var,
|
|
WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
//WBEM_FLAVOR_FLAG_PROPAGATE_TO_DERIVED_CLASS
|
|
}
|
|
}
|
|
|
|
// Perfindex
|
|
// =========
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
var.Clear();
|
|
V_VT(&var) = VT_I4;
|
|
V_I4(&var) = m_pPerfObj->ObjectNameTitleIndex;
|
|
hr = pQualSet->Put( L"perfindex", (VARIANT*)&var, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
}
|
|
|
|
// Helpindex
|
|
// =========
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
V_VT(&var) = VT_I4;
|
|
V_I4(&var) = m_pPerfObj->ObjectHelpTitleIndex;
|
|
hr = pQualSet->Put( L"helpindex", &var, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
}
|
|
|
|
#ifdef _PM_CHANGED_THEIR_MIND_
|
|
// Description
|
|
// ==========
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
HRESULT hr2;
|
|
LPCWSTR pwcsHelpName = NULL;
|
|
hr2 = m_pDefaultNameDb->GetHelpName( m_pPerfObj->ObjectHelpTitleIndex, &pwcsHelpName );
|
|
var = (WCHAR *)pwcsHelpName;
|
|
if (SUCCEEDED(hr2))
|
|
{
|
|
hr = pQualSet->Put( L"Description", &var, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
}
|
|
else
|
|
{
|
|
ERRORTRACE((LOG_WMIADAP,"class %S: Help for counter %d not found\n",(WCHAR *)m_wstrClassName,m_pPerfObj->ObjectHelpTitleIndex));
|
|
}
|
|
var.Clear();
|
|
}
|
|
#endif
|
|
// Singleton (set if the numinstances is PERF_NO_INSTANCES)
|
|
// ========================================================
|
|
if ( SUCCEEDED(hr) && IsSingleton( ) )
|
|
{
|
|
var.Clear();
|
|
var = bool(true);
|
|
// This will have default flavors
|
|
hr = pQualSet->Put( L"singleton", (VARIANT*)&var, 0L );
|
|
}
|
|
|
|
|
|
}break;
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
|
|
if ( FAILED( hr ) )
|
|
{
|
|
// Something whacky happened: log an event
|
|
// =======================================
|
|
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
|
|
WBEM_MC_ADAP_GENERAL_OBJECT_FAILURE,
|
|
(LPCWSTR)m_wstrClassName,
|
|
(LPCWSTR)m_wstrServiceName,
|
|
CHex( hr ) );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CDefaultClassBroker::AddDefaultProperties( IWbemClassObject* pClass )
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Adds appropriate default properties.
|
|
//
|
|
// The following qualifiers will be added:
|
|
// - Name
|
|
//
|
|
// Parameters:
|
|
// pClass - The object to be massaged
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
// If we are not a singleton class, then we will
|
|
// need a name property that is marked as a key
|
|
// =============================================
|
|
if ( !IsSingleton() )
|
|
{
|
|
_variant_t var;
|
|
|
|
// Add the Name property
|
|
// =====================
|
|
|
|
V_VT(&var) = VT_NULL;
|
|
V_I8(&var) = 0;
|
|
hr = pClass->Put( L"Name", 0L, &var, CIM_STRING );
|
|
|
|
// Add the property qualifiers
|
|
// ===========================
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
IWbemQualifierSet* pQualSet = NULL;
|
|
hr = pClass->GetPropertyQualifierSet( L"Name", &pQualSet );
|
|
CReleaseMe rmQualSet( pQualSet );
|
|
|
|
// Dynamic
|
|
// =======
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
var.Clear();
|
|
var = bool(true);
|
|
hr = pQualSet->Put( L"key", (VARIANT*)&var, 0L );
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CDefaultClassBroker::EnumProperties( DWORD dwType, IWbemClassObject* pClass )
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Walks the counter definitions and generates corresponding properties
|
|
//
|
|
// Parameters:
|
|
// pClass - The object to be massaged
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
BOOL bLastCounterIsNotBase = FALSE;
|
|
WString wstrLastCtrName;
|
|
|
|
// Set to first counter definition
|
|
// ===============================
|
|
LPBYTE pbData = ((LPBYTE) m_pPerfObj) + m_pPerfObj->HeaderLength;
|
|
|
|
// Cast to a counter definition
|
|
// ============================
|
|
PERF_COUNTER_DEFINITION* pCounterDefinition = (PERF_COUNTER_DEFINITION*) pbData;
|
|
|
|
|
|
// For each counter definition, add a corresponding property
|
|
// =========================================================
|
|
for ( DWORD dwCtr = 0; SUCCEEDED( hr ) && dwCtr < m_pPerfObj->NumCounters; dwCtr++ )
|
|
{
|
|
hr = AddProperty( pCounterDefinition, dwType, ( dwCtr == (DWORD) m_pPerfObj->DefaultCounter),
|
|
pClass, wstrLastCtrName, &bLastCounterIsNotBase );
|
|
|
|
// Now go to the next counter definition
|
|
// =====================================
|
|
pbData = ((LPBYTE) pCounterDefinition) + pCounterDefinition->ByteLength;
|
|
pCounterDefinition = (PERF_COUNTER_DEFINITION*) pbData;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CDefaultClassBroker::AddProperty( PERF_COUNTER_DEFINITION* pCtrDefinition,
|
|
DWORD dwType,
|
|
BOOL fIsDefault,
|
|
IWbemClassObject* pClass,
|
|
WString &wstrLastCtrName,
|
|
BOOL* pbLastCounterIsNotBase )
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Adds a property defined by the counter definition
|
|
//
|
|
// Properties:
|
|
// pCtrDefinition - The counter BLOB
|
|
// dwType - Raw or Formatted object?
|
|
// fIsDefault - The default property flag
|
|
// pClass - The class containing the property
|
|
// wstrLastCtrName - The name of the last counter (required for base
|
|
// properties)
|
|
// pbLastCounterIsNotBase
|
|
// - An indicator for the previous counter's baseness
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
WString wstrPropertyName;
|
|
DWORD dwCounterTypeMask = PERF_SIZE_VARIABLE_LEN;
|
|
BOOL bBase = FALSE;
|
|
|
|
if ( PERF_COUNTER_BASE == ( pCtrDefinition->CounterType & 0x00070000 ) )
|
|
{
|
|
// It's a base property
|
|
// ====================
|
|
if ( *pbLastCounterIsNotBase )
|
|
{
|
|
try
|
|
{
|
|
// The property name is the same as the previous property,
|
|
// but with "_Base" appended to the end
|
|
// =======================================================
|
|
wstrPropertyName = wstrLastCtrName;
|
|
|
|
if ( WMI_ADAP_RAW_CLASS == dwType )
|
|
{
|
|
wstrPropertyName += "_Base";
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
|
|
bBase = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// Cannot have 2 consequtive bases
|
|
// ===============================
|
|
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE, WBEM_MC_ADAP_BAD_PERFLIB_INVALID_DATA, (LPCWSTR)m_wstrServiceName, CHex(0) );
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// It's not a base property so get the name from the names' database
|
|
// =================================================================
|
|
hr = m_pDefaultNameDb->GetDisplayName( pCtrDefinition->CounterNameTitleIndex, wstrPropertyName );
|
|
|
|
if ( FAILED( hr ) )
|
|
{
|
|
// Index does not exist in the Names' DB: log an event
|
|
// ===================================================
|
|
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
|
|
WBEM_MC_ADAP_MISSING_PROPERTY_INDEX,
|
|
(LPCWSTR)m_wstrClassName,
|
|
(LPCWSTR)m_wstrServiceName,
|
|
pCtrDefinition->CounterNameTitleIndex );
|
|
}
|
|
|
|
// Replace reserved characters with text
|
|
// =====================================
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = ReplaceReserved( wstrPropertyName );
|
|
}
|
|
|
|
// Remove restricted characters
|
|
// ============================
|
|
if ( SUCCEEDED ( hr ) )
|
|
{
|
|
hr = RemoveWhitespaceAndNonAlphaNum( wstrPropertyName );
|
|
}
|
|
}
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
_variant_t varTest;
|
|
DWORD dwBaseCtr = 1;
|
|
|
|
// Ensure that the property does not exist
|
|
// =======================================
|
|
if ( FAILED( pClass->Get( wstrPropertyName, 0L, &varTest, NULL, NULL ) ) )
|
|
{
|
|
// Now check the perf counter type to see if it's a DWORD or LARGE.
|
|
// If it's anything else, we will NOT support this object
|
|
// ================================================================
|
|
DWORD dwCtrType = pCtrDefinition->CounterType & dwCounterTypeMask;
|
|
|
|
if ( PERF_SIZE_DWORD == dwCtrType ||
|
|
PERF_SIZE_LARGE == dwCtrType )
|
|
{
|
|
_variant_t var;
|
|
CIMTYPE ct = ( PERF_SIZE_DWORD == dwCtrType ? CIM_UINT32 : CIM_UINT64 );
|
|
|
|
// Add the property
|
|
// ================
|
|
V_VT(&var) = VT_NULL;
|
|
V_I8(&var) = 0;
|
|
hr = pClass->Put( wstrPropertyName, 0L, &var, ct );
|
|
|
|
// Set the property qualifiers
|
|
// ===========================
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = SetPropertyQualifiers( pCtrDefinition,
|
|
dwType,
|
|
fIsDefault,
|
|
wstrPropertyName,
|
|
pClass,
|
|
bBase );
|
|
}
|
|
}
|
|
else if ( PERF_SIZE_ZERO == dwCtrType )
|
|
{
|
|
// Ignore zero size properties
|
|
// ===========================
|
|
}
|
|
else
|
|
{
|
|
// Illegal property type: log an event
|
|
// ===================================
|
|
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
|
|
WBEM_MC_ADAP_BAD_PERFLIB_BAD_PROPERTYTYPE,
|
|
(LPCWSTR)m_wstrClassName,
|
|
(LPCWSTR)m_wstrServiceName,
|
|
(LPCWSTR)wstrPropertyName);
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
}
|
|
else if ( ( WMI_ADAP_COOKED_CLASS == dwType ) && ( bBase ) )
|
|
{
|
|
hr = SetPropertyQualifiers( pCtrDefinition,
|
|
dwType,
|
|
fIsDefault,
|
|
wstrPropertyName,
|
|
pClass,
|
|
bBase );
|
|
}
|
|
else
|
|
{
|
|
// Raw Property already exists: log an event (
|
|
// =========================================
|
|
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
|
|
WBEM_MC_ADAP_DUPLICATE_PROPERTY,
|
|
(LPCWSTR)m_wstrClassName,
|
|
(LPCWSTR)m_wstrServiceName,
|
|
(LPCWSTR) wstrPropertyName );
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
}
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
*pbLastCounterIsNotBase = !bBase;
|
|
wstrLastCtrName = wstrPropertyName;
|
|
}
|
|
else
|
|
{
|
|
// Wierdness: log an event
|
|
// =======================
|
|
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
|
|
WBEM_MC_ADAP_GENERAL_OBJECT_FAILURE,
|
|
(LPCWSTR)m_wstrClassName,
|
|
(LPCWSTR)m_wstrServiceName,
|
|
CHex( hr ) );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CDefaultClassBroker::SetPropertyQualifiers( PERF_COUNTER_DEFINITION* pCtrDefinition,
|
|
DWORD dwType,
|
|
BOOL fIsDefault,
|
|
LPCWSTR pwcsPropertyName,
|
|
IWbemClassObject* pClass,
|
|
BOOL bBase )
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Sets the qualifier values of the properties defined by the counter
|
|
// definition.
|
|
//
|
|
// The following qualifiers will be added:
|
|
// - Perfdefault
|
|
// - Display
|
|
// - Countertype
|
|
// - Perfindex
|
|
// - Helpindex
|
|
// - Defaultscale
|
|
// - Perfdetail
|
|
//
|
|
// Properties:
|
|
// pCtrDefinition - The portion of the performance blob related to the property
|
|
// fIsDefault - Flag identifying default property
|
|
// pwcsPropertyName - The name of the property
|
|
// pClass - The WMI class containing the property
|
|
// bBase - Base property identifier
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
_variant_t var;
|
|
|
|
try
|
|
{
|
|
IWbemQualifierSet* pQualSet = NULL;
|
|
hr = pClass->GetPropertyQualifierSet( pwcsPropertyName, &pQualSet );
|
|
CReleaseMe rmQualSet( pQualSet );
|
|
|
|
switch ( dwType )
|
|
{
|
|
case WMI_ADAP_RAW_CLASS:
|
|
{
|
|
// Perfdefault
|
|
// ===========
|
|
if ( SUCCEEDED( hr ) && fIsDefault )
|
|
{
|
|
var = bool(true);
|
|
hr = pQualSet->Put( L"perfdefault", (VARIANT*)&var, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
}
|
|
|
|
// Display
|
|
// =======
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
LPCWSTR pwcsDisplayName = NULL;
|
|
|
|
var.Clear();
|
|
|
|
// Fetch the name from the Names' database
|
|
// =======================================
|
|
if ( !bBase )
|
|
{
|
|
hr = m_pDefaultNameDb->GetDisplayName( pCtrDefinition->CounterNameTitleIndex, &pwcsDisplayName );
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
var = pwcsDisplayName;
|
|
}
|
|
else
|
|
{
|
|
ERRORTRACE((LOG_WMIADAP,"class %S: DisplayName for counter %d not found\n",(WCHAR *)m_wstrClassName,pCtrDefinition->CounterNameTitleIndex));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var = L"";
|
|
}
|
|
|
|
// If this is a localized Db, this could be a benign error
|
|
// =======================================================
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = pQualSet->Put( L"DisplayName", &var, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
}
|
|
}
|
|
|
|
#ifdef _PM_CHANGED_THEIR_MIND_
|
|
// Description
|
|
// ===========
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
LPCWSTR pwcsHelpName = NULL;
|
|
|
|
var.Clear();
|
|
|
|
if ( !bBase )
|
|
{
|
|
hr = m_pDefaultNameDb->GetHelpName( pCtrDefinition->CounterHelpTitleIndex, &pwcsHelpName );
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
var = pwcsHelpName;
|
|
}
|
|
else
|
|
{
|
|
ERRORTRACE((LOG_WMIADAP,"class %S: Help for counter %d not found\n",(WCHAR *)m_wstrClassName,pCtrDefinition->CounterNameTitleIndex));
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
var = L"";
|
|
}
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = pQualSet->Put( L"Description", &var, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
// Countertype
|
|
// ===========
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
var.Clear();
|
|
V_VT(&var) = VT_I4;
|
|
V_I4(&var) = pCtrDefinition->CounterType ;
|
|
hr = pQualSet->Put( L"countertype", &var, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
}
|
|
|
|
// Perfindex
|
|
// =========
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
V_VT(&var) = VT_I4;
|
|
V_I4(&var) = pCtrDefinition->CounterNameTitleIndex ;
|
|
hr = pQualSet->Put( L"perfindex", &var, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
}
|
|
|
|
// Helpindex
|
|
// =========
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
V_VT(&var) = VT_I4;
|
|
V_I4(&var) = pCtrDefinition->CounterHelpTitleIndex ;
|
|
hr = pQualSet->Put( L"helpindex", &var, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
}
|
|
|
|
// Defaultscale
|
|
// ============
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
V_VT(&var) = VT_I4;
|
|
V_I4(&var) = pCtrDefinition->DefaultScale ;
|
|
hr = pQualSet->Put( L"defaultscale", &var, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
}
|
|
|
|
// Perfdetail
|
|
// ==========
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
V_VT(&var) = VT_I4;
|
|
V_I4(&var) = pCtrDefinition->DetailLevel ;
|
|
hr = pQualSet->Put( L"perfdetail", &var, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
}
|
|
}break;
|
|
case WMI_ADAP_COOKED_CLASS:
|
|
{
|
|
var.Clear();
|
|
|
|
#ifdef _PM_CHANGED_THEIR_MIND_
|
|
// Display
|
|
// =======
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
LPCWSTR pwcsDisplayName = NULL;
|
|
|
|
var.Clear();
|
|
|
|
// Fetch the name from the Names' database
|
|
// =======================================
|
|
if ( !bBase )
|
|
{
|
|
hr = m_pDefaultNameDb->GetDisplayName( pCtrDefinition->CounterNameTitleIndex, &pwcsDisplayName );
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
var = pwcsDisplayName;
|
|
}
|
|
else
|
|
{
|
|
ERRORTRACE((LOG_WMIADAP,"class %S: DisplayName for counter %d not found\n",(WCHAR *)m_wstrClassName,pCtrDefinition->CounterNameTitleIndex));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var = L"";
|
|
}
|
|
|
|
// If this is a localized Db, this could be a benign error
|
|
// =======================================================
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = pQualSet->Put( L"DisplayName", &var, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
}
|
|
}
|
|
|
|
// Description
|
|
// ===========
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
LPCWSTR pwcsHelpName = NULL;
|
|
|
|
var.Clear();
|
|
|
|
if ( !bBase )
|
|
{
|
|
hr = m_pDefaultNameDb->GetHelpName( pCtrDefinition->CounterHelpTitleIndex, &pwcsHelpName );
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
var = pwcsHelpName;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var = L"";
|
|
}
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = pQualSet->Put( L"Description", &var, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
if ( !bBase )
|
|
{
|
|
// CookingType
|
|
// ===========
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
WCHAR* wszCookingType = NULL;
|
|
hr = GetCounterTypeString( pCtrDefinition->CounterType, &wszCookingType );
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
var = wszCookingType;
|
|
hr = pQualSet->Put( L"CookingType", (VARIANT*)&var, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
}
|
|
}
|
|
|
|
// Counter
|
|
// =======
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
WString wstrPropertyName;
|
|
|
|
var.Clear();
|
|
|
|
// Fetch the name from the Names' database
|
|
// =======================================
|
|
hr = m_pDefaultNameDb->GetDisplayName( pCtrDefinition->CounterNameTitleIndex, wstrPropertyName );
|
|
|
|
// Replace reserved characters with proper names
|
|
// =============================================
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = ReplaceReserved( wstrPropertyName );
|
|
}
|
|
|
|
// Remove whitespace and extraneous characters
|
|
// ===========================================
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = RemoveWhitespaceAndNonAlphaNum( wstrPropertyName );
|
|
}
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
var = LPCWSTR(wstrPropertyName );
|
|
|
|
// If this is a localized Db, this could be a benign error
|
|
// =======================================================
|
|
hr = pQualSet->Put( L"Counter", &var, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
}
|
|
}
|
|
|
|
// PerfTimeStamp & PerfTimeFreq
|
|
// ============================
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
_variant_t varStamp;
|
|
_variant_t varFreq;
|
|
|
|
if ( pCtrDefinition->CounterType & PERF_TIMER_100NS )
|
|
{
|
|
varStamp = L"TimeStamp_Sys100NS";
|
|
varFreq = L"Frequency_Sys100NS";
|
|
}
|
|
else if ( pCtrDefinition->CounterType & PERF_OBJECT_TIMER )
|
|
{
|
|
varStamp = L"Timestamp_Object" ;
|
|
varFreq = L"Frequency_Object" ;
|
|
}
|
|
else
|
|
{
|
|
varStamp = L"Timestamp_PerfTime";
|
|
varFreq = L"Frequency_PerfTime";
|
|
}
|
|
|
|
hr = pQualSet->Put( L"PerfTimeStamp", &varStamp, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = pQualSet->Put( L"PerfTimeFreq", &varFreq, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
}
|
|
}
|
|
|
|
// Perfindex
|
|
// =========
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
var.Clear();
|
|
V_VT(&var) = VT_I4;
|
|
V_I4(&var) = pCtrDefinition->CounterNameTitleIndex;
|
|
hr = pQualSet->Put( L"perfindex", (VARIANT*)&var, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
}
|
|
|
|
// Helpindex
|
|
// =========
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
V_VT(&var) = VT_I4;
|
|
V_I4(&var) = pCtrDefinition->CounterHelpTitleIndex ;
|
|
hr = pQualSet->Put( L"helpindex", &var, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
}
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
// Base
|
|
// ====
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
WCHAR* wszCounterBase = NULL;
|
|
_variant_t varCounter;
|
|
hr = pQualSet->Get( L"Counter", 0L, &varCounter, NULL );
|
|
|
|
wszCounterBase = new WCHAR[ wcslen( varCounter.bstrVal ) + 5 + 1 ];
|
|
CDeleteMe<WCHAR> dmCounterBase( wszCounterBase );
|
|
|
|
if ( NULL == wszCounterBase )
|
|
{
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
else
|
|
{
|
|
swprintf( wszCounterBase, L"%s_Base", varCounter.bstrVal );
|
|
var = wszCounterBase;
|
|
hr = pQualSet->Put( L"Base", (VARIANT*)&var, WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE );
|
|
}
|
|
}
|
|
}
|
|
}break;
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
|
|
if ( FAILED( hr ) )
|
|
{
|
|
// Weirdness: log an event
|
|
// =======================
|
|
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
|
|
WBEM_MC_ADAP_GENERAL_OBJECT_FAILURE,
|
|
(LPCWSTR)m_wstrClassName,
|
|
(LPCWSTR)m_wstrServiceName,
|
|
CHex( hr ) );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CDefaultClassBroker::GenPerfClass( PERF_OBJECT_TYPE* pPerfObj,
|
|
DWORD dwType,
|
|
BOOL bCostly,
|
|
IWbemClassObject* pBaseClass,
|
|
CPerfNameDb* pDefaultNameDb,
|
|
WCHAR* pwcsServiceName,
|
|
IWbemClassObject** ppObj)
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// A static member of the broker. It generates a WMI class based on the
|
|
// object BLOB.
|
|
//
|
|
// Parameters:
|
|
// pPerfObj - The object BLOB
|
|
// bCostly - Costly object indicator
|
|
// pBaseClass - The new object's base class
|
|
// pDefaultNameDb - The default language names' database
|
|
// pwcsServiceName - The name of the perflib service
|
|
// ppObj - A pointer to the new class object interface pointer
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
IWbemClassObject* pObject = NULL;
|
|
CDefaultClassBroker Broker( pPerfObj, bCostly, pBaseClass, pDefaultNameDb, pwcsServiceName );
|
|
|
|
hr = Broker.Generate( dwType, &pObject );
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
*ppObj = pObject;
|
|
|
|
return hr;
|
|
}
|