|
|
/*++
Copyright (C) 1995-1999 Microsoft Corporation
Module Name:
wmi.c
Abstract:
WMI interface functions exported by PDH.DLL
--*/
#include <windows.h>
#include <winperf.h>
#include "mbctype.h"
#include <mbctype.h>
#include <pdh.h>
#include <pdhmsg.h>
#include <assert.h>
#include "wbemdef.h"
#include "pdhitype.h"
#include "pdhidef.h"
#include "strings.h"
#define PERF_TIMER_FIELD \
(PERF_TIMER_TICK | PERF_TIMER_100NS | PERF_OBJECT_TIMER)
__inline VOID PdhiSysFreeString( BSTR *x ) { if (x != NULL) { if (*x != NULL) { SysFreeString(*x); *x = NULL; } } }
// at this point, calling the refresher while adding items to the refresher
// doesn't work. so for the time being, we'll use this interlock to prevent
// a collision
static BOOL bDontRefresh = FALSE;
// Prototype
HRESULT WbemSetProxyBlanket( IUnknown *pInterface, DWORD dwAuthnSvc, DWORD dwAuthzSvc, OLECHAR *pServerPrincName, DWORD dwAuthLevel, DWORD dwImpLevel, RPC_AUTH_IDENTITY_HANDLE pAuthInfo, DWORD dwCapabilities );
HRESULT SetWbemSecurity( IUnknown *pInterface ) { return WbemSetProxyBlanket( pInterface, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE ); }
// This is the same timeout value the refresher uses so we can pretend
// we're doing the same thing.
#define WBEM_REFRESHER_TIMEOUT 10000
// This class is designed to encapsulate the IWbemRefresher functionality
// The definition and implementation are all in this source file
class CWbemRefresher : public IUnknown { protected: LONG m_lRefCount;
// The primitives that will control the multithreading stuff
HANDLE m_hQuitEvent; HANDLE m_hDoWorkEvent; HANDLE m_hWorkDoneEvent; HANDLE m_hRefrMutex; HANDLE m_hInitializedEvent; HANDLE m_hThread; DWORD m_dwThreadId; BOOL m_fThreadOk;
// These are the pass-thru variables we will use as placeholders
// as we perform our operations. Note that a couple are missing.
// This is because we are not really using them in our code, so
// no sense in adding anything we don't really need.
IStream* m_pNSStream; LPCWSTR m_wszPath; LPCWSTR m_wszClassName; long m_lFlags; IWbemClassObject** m_ppRefreshable; IWbemHiPerfEnum** m_ppEnum; long* m_plId; long m_lId; HRESULT m_hOperResult;
// This is what will be set to indicate to the thread which operation
// it is supposed to perform.
typedef enum { eRefrOpNone, eRefrOpRefresh, eRefrOpAddByPath, eRefrOpAddEnum, eRefrOpRemove, eRefrOpLast } tRefrOps;
tRefrOps m_eRefrOp;
// Thread ebtryt
class XRefresher : public IWbemRefresher { protected: CWbemRefresher* m_pOuter;
public: XRefresher( CWbemRefresher* pOuter ) : m_pOuter( pOuter ) {}; ~XRefresher() {};
STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID FAR* ppvObj); STDMETHOD_(ULONG, AddRef)(THIS); STDMETHOD_(ULONG, Release)(THIS); STDMETHOD(Refresh)(long lFlags);
} m_xRefresher;
class XConfigRefresher : public IWbemConfigureRefresher { protected: CWbemRefresher* m_pOuter;
public: XConfigRefresher( CWbemRefresher* pOuter ) : m_pOuter( pOuter ) {}; ~XConfigRefresher() {};
STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID FAR* ppvObj); STDMETHOD_(ULONG, AddRef)(THIS); STDMETHOD_(ULONG, Release)(THIS); STDMETHOD(AddObjectByPath)(IWbemServices* pNamespace, LPCWSTR wszPath, long lFlags, IWbemContext* pContext, IWbemClassObject** ppRefreshable, long* plId);
STDMETHOD(AddObjectByTemplate)(IWbemServices* pNamespace, IWbemClassObject* pTemplate, long lFlags, IWbemContext* pContext, IWbemClassObject** ppRefreshable, long* plId);
STDMETHOD(AddRefresher)(IWbemRefresher* pRefresher, long lFlags, long* plId);
STDMETHOD(Remove)(long lId, long lFlags);
STDMETHOD(AddEnum)( IWbemServices* pNamespace, LPCWSTR wscClassName, long lFlags, IWbemContext* pContext, IWbemHiPerfEnum** ppEnum, long* plId );
} m_xConfigRefresher;
protected:
void Initialize( void ); void Cleanup( void );
// Operation helpers
HRESULT SignalRefresher( void ); HRESULT SetRefresherParams( IWbemServices* pNamespace, tRefrOps eOp, LPCWSTR pwszPath, LPCWSTR pwszClassName, long lFlags, IWbemClassObject** ppRefreshable, IWbemHiPerfEnum** ppEnum, long* plId, long lId ); void ClearRefresherParams( void );
DWORD WINAPI RealEntry( void );
static DWORD WINAPI ThreadProc( void * pThis ) { return ((CWbemRefresher*) pThis)->RealEntry(); }
public: CWbemRefresher(); virtual ~CWbemRefresher();
STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID FAR* ppvObj); STDMETHOD_(ULONG, AddRef)(THIS); STDMETHOD_(ULONG, Release)(THIS);
// The real implementations
STDMETHOD(AddObjectByPath)(IWbemServices* pNamespace, LPCWSTR wszPath, long lFlags, IWbemContext* pContext, IWbemClassObject** ppRefreshable, long* plId);
STDMETHOD(AddObjectByTemplate)(IWbemServices* pNamespace, IWbemClassObject* pTemplate, long lFlags, IWbemContext* pContext, IWbemClassObject** ppRefreshable, long* plId);
STDMETHOD(AddRefresher)(IWbemRefresher* pRefresher, long lFlags, long* plId);
STDMETHOD(Remove)(long lId, long lFlags);
STDMETHOD(AddEnum)( IWbemServices* pNamespace, LPCWSTR wscClassName, long lFlags, IWbemContext* pContext, IWbemHiPerfEnum** ppEnum, long* plId );
STDMETHOD(Refresh)(long lFlags);
};
/*
** Begin CWbemRefresher Implementation */
#if _MSC_VER >= 1200
#pragma warning(push)
#endif
#pragma warning(disable:4355)
// CTor and DTor
CWbemRefresher::CWbemRefresher( void ) : m_lRefCount(0), m_xRefresher( this ), m_xConfigRefresher( this ), m_hQuitEvent( NULL ), m_hDoWorkEvent( NULL ), m_hRefrMutex( NULL ), m_hInitializedEvent( NULL ), m_hThread( NULL ), m_hWorkDoneEvent( NULL ), m_dwThreadId( 0 ), m_pNSStream( NULL ), m_wszPath( NULL ), m_wszClassName( NULL ), m_lFlags( 0L ), m_ppRefreshable( NULL ), m_ppEnum( NULL ), m_plId( NULL ), m_eRefrOp( eRefrOpRefresh ), m_hOperResult( WBEM_S_NO_ERROR ), m_fThreadOk( FALSE ), m_lId( 0 ) { Initialize(); }
#if _MSC_VER >= 1200
#pragma warning(pop)
#else
#pragma warning(default:4355)
#endif
CWbemRefresher::~CWbemRefresher( void ) { Cleanup(); }
void CWbemRefresher::Initialize( void ) { // Now create the events, mutexes and our pal, the MTA thread on which all of
// the operations will run
m_hQuitEvent = CreateEventW( NULL, FALSE, FALSE, NULL ); m_hDoWorkEvent = CreateEventW( NULL, FALSE, FALSE, NULL ); m_hInitializedEvent = CreateEventW( NULL, FALSE, FALSE, NULL ); m_hWorkDoneEvent = CreateEventW( NULL, FALSE, FALSE, NULL );
m_hRefrMutex = CreateMutexW( NULL, FALSE, NULL );
// If we don't have all these, something's gone south
if ( NULL == m_hQuitEvent || NULL == m_hDoWorkEvent || NULL == m_hInitializedEvent || NULL == m_hWorkDoneEvent || NULL == m_hRefrMutex ) { return; }
// Kick off the thread and wait for the initialized event signal (we'll give it
// 5 seconds...if it don't get signalled in that timeframe, something is most likely
// wrong, but we'll bounce out so whoever allocated us isn't left wondering what
// to do).
m_hThread = CreateThread( NULL, 0, CWbemRefresher::ThreadProc, (void*) this, 0, &m_dwThreadId );
if ( NULL == m_hThread ) { return; }
WaitForSingleObject( m_hInitializedEvent, 5000 );
}
void CWbemRefresher::Cleanup( void ) { // If we have a thread, tell it to go away
if ( NULL != m_hThread ) { // Signal the quit event and give the thread a 5 second grace period
// to shutdown. If it don't, don't worry, just close the handle and go away.
SetEvent( m_hQuitEvent ); WaitForSingleObject( m_hThread, 5000 );
CloseHandle( m_hThread ); m_hThread = NULL; }
// Cleanup the primitives
if ( NULL != m_hQuitEvent ) { CloseHandle( m_hQuitEvent ); m_hQuitEvent = NULL; }
if ( NULL != m_hDoWorkEvent ) { CloseHandle( m_hDoWorkEvent ); m_hDoWorkEvent = NULL; }
if ( NULL != m_hInitializedEvent ) { CloseHandle( m_hInitializedEvent ); m_hInitializedEvent = NULL; }
if ( NULL != m_hWorkDoneEvent ) { CloseHandle( m_hWorkDoneEvent ); m_hWorkDoneEvent = NULL; }
if ( NULL != m_hRefrMutex ) { CloseHandle( m_hRefrMutex ); m_hRefrMutex = NULL; }
}
DWORD CWbemRefresher::RealEntry( void ) { // Grab hold of all the things we may care about in case some evil timing
// problem occurs, so we don't get left trying to hit on member variables that
// don't exist anymore.
HANDLE hQuitEvent = m_hQuitEvent, hDoWorkEvent = m_hDoWorkEvent, hInitializedEvent = m_hInitializedEvent, hWorkDoneEvent = m_hWorkDoneEvent;
DWORD dwWait = 0;
HANDLE ahEvents[2];
ahEvents[0] = hDoWorkEvent; ahEvents[1] = hQuitEvent;
// Initialize this thread
HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); if (hr == S_FALSE) { // COM library is already initialized, we can continue;
//
hr = S_OK; }
// Now get the refresher and config refresher pointers.
IWbemRefresher* pWbemRefresher = NULL; IWbemConfigureRefresher* pWbemConfig = NULL;
if ( SUCCEEDED( hr ) ) { hr = CoCreateInstance (CLSID_WbemRefresher, 0, CLSCTX_SERVER, IID_IWbemRefresher, (LPVOID *)&pWbemRefresher);
if ( SUCCEEDED( hr ) ) { pWbemRefresher->QueryInterface( IID_IWbemConfigureRefresher, (LPVOID *) &pWbemConfig ); }
}
// Obviously we can't go any further if we don't have our pointers correctly
// setup.
m_fThreadOk = SUCCEEDED( hr );
// Ready to go --- Signal the Initialized Event
SetEvent( hInitializedEvent );
if ( m_fThreadOk ) {
while ( ( dwWait = WaitForMultipleObjects( 2, ahEvents, FALSE, INFINITE ) ) == WAIT_OBJECT_0 ) { // Don't continue if quit is signalled
if ( WaitForSingleObject( hQuitEvent, 0 ) == WAIT_OBJECT_0 ) { break; }
// This is where we'll do the real operation
switch( m_eRefrOp ) { case eRefrOpRefresh: { m_hOperResult = pWbemRefresher->Refresh( m_lFlags ); break; }
// For both of these ops, we will need to umarshal the
// namespace
case eRefrOpAddEnum: case eRefrOpAddByPath: { IWbemServices* pNamespace = NULL;
// Unmarshal the interface, then set security
m_hOperResult = CoGetInterfaceAndReleaseStream( m_pNSStream, IID_IWbemServices, (void**) &pNamespace ); m_pNSStream = NULL;
if ( SUCCEEDED( m_hOperResult ) ) { m_hOperResult = SetWbemSecurity( pNamespace );
if ( SUCCEEDED( m_hOperResult ) ) { if ( eRefrOpAddByPath == m_eRefrOp ) { m_hOperResult = pWbemConfig->AddObjectByPath( pNamespace, m_wszPath, m_lFlags, NULL, m_ppRefreshable, m_plId ); } else { m_hOperResult = pWbemConfig->AddEnum( pNamespace, m_wszClassName, m_lFlags, NULL, m_ppEnum, m_plId ); } }
pNamespace->Release(); }
break; }
case eRefrOpRemove: { m_hOperResult = pWbemConfig->Remove( m_lId, m_lFlags ); break; }
default: { m_hOperResult = WBEM_E_FAILED; } }
// Signal the event to let a waiting thread know we're done doing
// what it asked us to do.
SetEvent( hWorkDoneEvent ); }
}
// This means we're not processing anymore (for whatever reason)
m_fThreadOk = FALSE;
// Cleanup our pointers
if ( NULL != pWbemRefresher ) { pWbemRefresher->Release(); }
if ( NULL != pWbemConfig ) { pWbemConfig->Release(); }
CoUninitialize();
return 0; }
// CWbemRefresher class functions
SCODE CWbemRefresher::QueryInterface(REFIID riid, LPVOID FAR* ppvObj) { *ppvObj = 0;
if (IID_IUnknown==riid) { *ppvObj = (IUnknown*)this; AddRef(); return NOERROR; } else if ( IID_IWbemRefresher == riid ) { *ppvObj = (IWbemRefresher*) &m_xRefresher; AddRef(); return NOERROR; } else if ( IID_IWbemConfigureRefresher == riid ) { *ppvObj = (IWbemConfigureRefresher*) &m_xConfigRefresher; AddRef(); return NOERROR; }
return ResultFromScode(E_NOINTERFACE); }
ULONG CWbemRefresher::AddRef() { return InterlockedIncrement(&m_lRefCount); }
ULONG CWbemRefresher::Release() { long lRef = InterlockedDecrement(&m_lRefCount);
if (0 != lRef) return lRef;
delete this; return 0; }
HRESULT CWbemRefresher::SignalRefresher( void ) { HRESULT hr = WBEM_S_NO_ERROR;
if ( SetEvent( m_hDoWorkEvent ) ) { if ( WaitForSingleObject( m_hWorkDoneEvent, INFINITE ) == WAIT_OBJECT_0 ) { hr = m_hOperResult; } else { hr = WBEM_E_FAILED; } } else { hr = WBEM_E_FAILED; }
ClearRefresherParams();
return hr; }
HRESULT CWbemRefresher::SetRefresherParams( IWbemServices* pNamespace, tRefrOps eOp, LPCWSTR pwszPath, LPCWSTR pwszClassName, long lFlags, IWbemClassObject** ppRefreshable, IWbemHiPerfEnum** ppEnum, long* plId, long lId ) { HRESULT hr = WBEM_S_NO_ERROR;
if ( NULL != pNamespace ) { // Marshal the namespace pointer into the stream member
hr = CoMarshalInterThreadInterfaceInStream( IID_IWbemServices, pNamespace, &m_pNSStream ); } else { m_pNSStream = NULL; }
if ( SUCCEEDED( hr ) ) { m_eRefrOp = eOp; m_wszPath = pwszPath; m_wszClassName = pwszClassName, m_lFlags = lFlags; m_ppRefreshable = ppRefreshable; m_ppEnum = ppEnum; m_plId = plId; m_lId = lId; }
return hr; }
void CWbemRefresher::ClearRefresherParams( void ) { m_pNSStream = NULL; m_eRefrOp = eRefrOpNone; m_wszPath = NULL; m_wszClassName = NULL, m_lFlags = 0L; m_ppRefreshable = NULL; m_ppEnum = NULL; m_plId = NULL; m_lId = 0L; m_hOperResult = WBEM_S_NO_ERROR; }
// These are the real method implementations
STDMETHODIMP CWbemRefresher::AddObjectByPath( IWbemServices* pNamespace, LPCWSTR wszPath, long lFlags, IWbemContext* pContext, IWbemClassObject** ppRefreshable, long* plId) { HRESULT hr = WBEM_E_FAILED;
UNREFERENCED_PARAMETER (pContext);
if ( WaitForSingleObject( m_hRefrMutex, WBEM_REFRESHER_TIMEOUT ) == WAIT_OBJECT_0 ) { // Check that the thread is still running
if ( m_fThreadOk ) { // Setup the parameters and perform the operation
hr = SetRefresherParams( pNamespace, eRefrOpAddByPath, wszPath, NULL, lFlags, ppRefreshable, NULL, plId, 0L );
if ( SUCCEEDED( hr ) ) { // This is where we ask the thread to do the work
hr = SignalRefresher(); } } else { hr = WBEM_E_FAILED; }
ReleaseMutex( m_hRefrMutex ); } else { hr = WBEM_E_REFRESHER_BUSY; }
return hr; }
STDMETHODIMP CWbemRefresher::AddObjectByTemplate( IWbemServices* pNamespace, IWbemClassObject* pTemplate, long lFlags, IWbemContext* pContext, IWbemClassObject** ppRefreshable, long* plId) { UNREFERENCED_PARAMETER (pNamespace); UNREFERENCED_PARAMETER (pTemplate); UNREFERENCED_PARAMETER (lFlags); UNREFERENCED_PARAMETER (pContext); UNREFERENCED_PARAMETER (ppRefreshable); UNREFERENCED_PARAMETER (plId);
// We don't call this internally, so don't implement
return WBEM_E_METHOD_NOT_IMPLEMENTED; }
STDMETHODIMP CWbemRefresher::Remove(long lId, long lFlags) {
HRESULT hr = WBEM_E_FAILED;
UNREFERENCED_PARAMETER (lId); UNREFERENCED_PARAMETER (lFlags);
if ( WaitForSingleObject( m_hRefrMutex, WBEM_REFRESHER_TIMEOUT ) == WAIT_OBJECT_0 ) { // Check that the thread is still running
if ( m_fThreadOk ) { // Setup the parameters and perform the operation
hr = SetRefresherParams( NULL, eRefrOpRemove, NULL, NULL, lFlags, NULL, NULL, NULL, lId );
if ( SUCCEEDED( hr ) ) { // This is where we ask the thread to do the work
hr = SignalRefresher(); } } else { hr = WBEM_E_FAILED; }
ReleaseMutex( m_hRefrMutex ); } else { hr = WBEM_E_REFRESHER_BUSY; }
return hr;
}
STDMETHODIMP CWbemRefresher::AddRefresher( IWbemRefresher* pRefresher, long lFlags, long* plId) { UNREFERENCED_PARAMETER (lFlags); UNREFERENCED_PARAMETER (pRefresher); UNREFERENCED_PARAMETER (plId);
// We don't call this internally, so don't implement
return WBEM_E_METHOD_NOT_IMPLEMENTED; }
HRESULT CWbemRefresher::AddEnum( IWbemServices* pNamespace, LPCWSTR wszClassName, long lFlags, IWbemContext* pContext, IWbemHiPerfEnum** ppEnum, long* plId) {
HRESULT hr = WBEM_E_FAILED;
UNREFERENCED_PARAMETER (pContext);
if ( WaitForSingleObject( m_hRefrMutex, WBEM_REFRESHER_TIMEOUT ) == WAIT_OBJECT_0 ) { // Check that the thread is still running
if ( m_fThreadOk ) { // Setup the parameters and perform the operation
hr = SetRefresherParams( pNamespace, eRefrOpAddEnum, NULL, wszClassName, lFlags, NULL, ppEnum, plId, 0L );
if ( SUCCEEDED( hr ) ) { // This is where we ask the thread to do the work
hr = SignalRefresher(); } } else { hr = WBEM_E_FAILED; }
ReleaseMutex( m_hRefrMutex ); } else { hr = WBEM_E_REFRESHER_BUSY; }
return hr;
}
STDMETHODIMP CWbemRefresher::Refresh( long lFlags ) { HRESULT hr = WBEM_E_FAILED;
if ( WaitForSingleObject( m_hRefrMutex, WBEM_REFRESHER_TIMEOUT ) == WAIT_OBJECT_0 ) { // Check that the thread is still running
if ( m_fThreadOk ) { // Setup the parameters and perform the operation
hr = SetRefresherParams( NULL, eRefrOpRefresh, NULL, NULL, lFlags, NULL, NULL, NULL, 0L );
if ( SUCCEEDED( hr ) ) { // This is where we ask the thread to do the work
hr = SignalRefresher(); } } else { hr = WBEM_E_FAILED; }
ReleaseMutex( m_hRefrMutex ); } else { hr = WBEM_E_REFRESHER_BUSY; }
return hr; }
// XRefresher
SCODE CWbemRefresher::XRefresher::QueryInterface(REFIID riid, LPVOID FAR* ppvObj) { return m_pOuter->QueryInterface( riid, ppvObj ); }
ULONG CWbemRefresher::XRefresher::AddRef() { return m_pOuter->AddRef(); }
ULONG CWbemRefresher::XRefresher::Release() { return m_pOuter->Release(); }
STDMETHODIMP CWbemRefresher::XRefresher::Refresh( long lFlags ) { // Pass through
return m_pOuter->Refresh( lFlags ); }
// XConfigRefresher
SCODE CWbemRefresher::XConfigRefresher::QueryInterface(REFIID riid, LPVOID FAR* ppvObj) { return m_pOuter->QueryInterface( riid, ppvObj ); }
ULONG CWbemRefresher::XConfigRefresher::AddRef() { return m_pOuter->AddRef(); }
ULONG CWbemRefresher::XConfigRefresher::Release() { return m_pOuter->Release(); }
STDMETHODIMP CWbemRefresher::XConfigRefresher::AddObjectByPath( IWbemServices* pNamespace, LPCWSTR wszPath, long lFlags, IWbemContext* pContext, IWbemClassObject** ppRefreshable, long* plId) { // Pass through
return m_pOuter->AddObjectByPath( pNamespace, wszPath, lFlags, pContext, ppRefreshable, plId ); }
STDMETHODIMP CWbemRefresher::XConfigRefresher::AddObjectByTemplate( IWbemServices* pNamespace, IWbemClassObject* pTemplate, long lFlags, IWbemContext* pContext, IWbemClassObject** ppRefreshable, long* plId) { // Pass through
return m_pOuter->AddObjectByTemplate( pNamespace, pTemplate, lFlags, pContext, ppRefreshable, plId ); }
STDMETHODIMP CWbemRefresher::XConfigRefresher::Remove(long lId, long lFlags) { return m_pOuter->Remove( lId, lFlags ); }
STDMETHODIMP CWbemRefresher::XConfigRefresher::AddRefresher( IWbemRefresher* pRefresher, long lFlags, long* plId) { return m_pOuter->AddRefresher( pRefresher, lFlags, plId ); }
HRESULT CWbemRefresher::XConfigRefresher::AddEnum( IWbemServices* pNamespace, LPCWSTR wszClassName, long lFlags, IWbemContext* pContext, IWbemHiPerfEnum** ppEnum, long* plId) { return m_pOuter->AddEnum( pNamespace, wszClassName, lFlags, pContext, ppEnum, plId ); }
/*
** End CWbemRefresher Implementation! */
// HELPER Function to establish the CWbemRefresher Interface pass-thru
HRESULT CoCreateRefresher( IWbemRefresher** ppRefresher ) { HRESULT hr = WBEM_S_NO_ERROR;
// Allocate the pass-thru object then, if successful, get
// the interface pointer out of it
CWbemRefresher* pWbemRefresher = new CWbemRefresher;
if ( NULL != pWbemRefresher ) { hr = pWbemRefresher->QueryInterface( IID_IWbemRefresher, (LPVOID*) ppRefresher ); } else { hr = WBEM_E_OUT_OF_MEMORY; }
return hr; }
PPDHI_WBEM_SERVER_DEF pFirstWbemServer = NULL; //BOOL bWbemInitialized = FALSE;
BOOL bSecurityInitialized = FALSE; IGlobalInterfaceTable * gp_GIT = NULL;
BOOL PdhiCoInitialize( void ) { HRESULT sc = CoInitializeEx(NULL, COINIT_MULTITHREADED); if ( !bSecurityInitialized ) { // In case it hasn't been
HRESULT hr = CoInitializeSecurity( NULL, //Points to security descriptor
-1L, //Count of entries in asAuthSvc -1 means use default
NULL, //Array of names to register
NULL, //Reserved for future use
RPC_C_AUTHN_LEVEL_PKT, //The default authentication level
// for proxies
RPC_C_IMP_LEVEL_IMPERSONATE, //The default impersonation level
// for proxies
NULL, //Authentication information for
// each authentication service
EOAC_NONE, //Additional client and/or
// server-side capabilities
NULL //Reserved for future use
);
bSecurityInitialized = (hr == S_OK || hr == RPC_E_TOO_LATE); }
if (gp_GIT == NULL) { HRESULT hr1 = CoCreateInstance(CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, IID_IGlobalInterfaceTable, (void **) & gp_GIT); if (hr1 != ERROR_SUCCESS) { gp_GIT = NULL; } }
// We will only return that this succeeded if the call to CoInitializeEx
// returned S_FALSE. If it didn't, it either errored or returned S_OK.
// If S_OK, we will assume that the client isn't doing any COM stuff
// natively. If S_FALSE, the client already CoInitialized this thread
// so we just bumped up the ref count and should cleanup on the way
// out
return (S_FALSE == sc); }
void PdhiCoUninitialize( void ) { CoUninitialize(); }
PDH_FUNCTION PdhiCloseWbemServer (PPDHI_WBEM_SERVER_DEF pWbemServer);
PDH_FUNCTION PdhiDisconnectWbemServer ( PPDHI_WBEM_SERVER_DEF pWbemServer ) { PDH_STATUS pdhReturn = ERROR_SUCCESS; if (pWbemServer != NULL) { pWbemServer->lRefCount--; if (pWbemServer->lRefCount < 0) { pWbemServer->lRefCount = 0; } }
return pdhReturn; }
PDH_FUNCTION PdhiFreeWbemQuery ( PPDHI_QUERY pThisQuery ) { HRESULT hRes;
if (!bProcessIsDetaching) { if ((pThisQuery->pRefresherCfg) != NULL) { hRes = pThisQuery->pRefresherCfg->Release (); pThisQuery->pRefresherCfg = NULL; }
if ((pThisQuery->pRefresher) != NULL) { hRes = pThisQuery->pRefresher->Release (); pThisQuery->pRefresher = NULL; } } return ERROR_SUCCESS; }
PDH_FUNCTION PdhiCloseWbemCounter ( PPDHI_COUNTER pThisCounter ) { HRESULT hRes; BOOLEAN bRemoveRefresher = TRUE;
if (!bProcessIsDetaching) { if (pThisCounter->pOwner->pRefresherCfg != NULL) { PPDHI_QUERY pQuery = pThisCounter->pOwner; PPDHI_COUNTER pCounter = pQuery->pCounterListHead;
do { if (pCounter == NULL) { bRemoveRefresher = FALSE; } else if (pCounter != pThisCounter && pCounter->lWbemRefreshId == pThisCounter->lWbemRefreshId) { bRemoveRefresher = FALSE; } else { pCounter = pCounter->next.flink; } } while (bRemoveRefresher && pCounter != NULL && pCounter != pQuery->pCounterListHead);
if (bRemoveRefresher) { hRes = pThisCounter->pOwner->pRefresherCfg->Remove( pThisCounter->lWbemRefreshId, 0L); } // assert (hRes == S_OK); the function returns a BOOL even though it's defined as an HRESULT
// pThisCounter->pOwner->pRefresherCfg->Release();
// pThisCounter->pOwner->pRefresherCfg = NULL;
}
if (pThisCounter->pWbemAccess != NULL) { pThisCounter->pWbemAccess->Release(); pThisCounter->pWbemAccess = NULL; }
if (pThisCounter->pWbemObject != NULL) { pThisCounter->pWbemObject->Release(); pThisCounter->pWbemObject = NULL; } }
return ERROR_SUCCESS; }
PDH_FUNCTION PdhiBreakWbemMachineName ( LPCWSTR szMachineAndNamespace, LPWSTR szMachine, LPWSTR szNamespace ) /*
assumes szMachine and szPath are large enough to hold the result */ { LPWSTR szSrc = NULL; LPWSTR szDest = NULL;
assert (szMachine != NULL); assert (szNamespace != NULL);
szSrc = (LPWSTR)szMachineAndNamespace;
if (szSrc == NULL) { // then use local machine and default namespace
lstrcpyW (szMachine, szStaticLocalMachineName); // local machine
lstrcpyW (szNamespace, cszWbemDefaultPerfRoot); return ERROR_SUCCESS; } else { // break into components
if (*szSrc != NULL) { // there's a string, see if it's a machine or a namespace
if ((szSrc[0] == L'\\') && (szSrc[1] == L'\\')) { szDest = szMachine; // then there's a machine name
*szDest++ = *szSrc++; *szDest++ = *szSrc++; while ((*szSrc != 0) && (*szSrc != L'\\')){ *szDest++ = *szSrc++; } *szDest = 0; } else { // no machine so use default
// it must be just a namespace
} } else { // no machine so use default
}
if (szDest == NULL) { // nothing found yet, so insert local machine as default
szDest = szMachine; lstrcpyW (szDest, szStaticLocalMachineName); }
szDest = szNamespace;
if (*szSrc != 0) { // if there's a namespace then copy it
szSrc++; // move past backslash
while (*szSrc != 0) { *szDest++ = *szSrc++; } *szDest = 0; } else { // else return the default;
lstrcpyW (szDest, cszWbemDefaultPerfRoot); } return ERROR_SUCCESS; } }
PDH_FUNCTION PdhiMakeWbemInstancePath ( IN PDH_COUNTER_PATH_ELEMENTS_W *pCounterPathElements, IN LPWSTR szFullPathBuffer, IN BOOL bMakeRelativePath ) { WCHAR szMachine[MAX_PATH]; WCHAR szNamespace[MAX_PATH]; WCHAR szWbemInstance[MAX_PATH];
LPWSTR szSrc, szDest; // the function assumes that the path buffer is sufficiently large
// to hold the result
//
//
// the wbem class instance path consists of one of the following formats:
// for perf objects with one and only one instance (singleton classes in
// WBEM parlance) the format is
//
// <objectname>=@
//
// for object with instances, the format is
//
// <objectname>.Name="<instancename>"
//
if (!bMakeRelativePath) { PdhiBreakWbemMachineName ( pCounterPathElements->szMachineName, szMachine, szNamespace); lstrcpyW (szFullPathBuffer, szMachine); lstrcatW (szFullPathBuffer, cszBackSlash); lstrcatW (szFullPathBuffer, szNamespace); lstrcatW (szFullPathBuffer, cszColon); } else { *szFullPathBuffer = 0; }
if (pCounterPathElements->szInstanceName == NULL) { // then apply the singleton logic
lstrcatW (szFullPathBuffer, pCounterPathElements->szObjectName); lstrcatW (szFullPathBuffer, cszSingletonInstance); } else { // wbem will interpret the backslash character as an
// escape char (as "C" does) so we'll have to double each
// backslash in the string to make it come out OK
szDest = &szWbemInstance[0]; if (pCounterPathElements->szParentInstance != NULL) { szSrc = pCounterPathElements->szParentInstance; while (*szSrc != 0) { *szDest = *szSrc; if (*szSrc == BACKSLASH_L) { *++szDest = BACKSLASH_L; } szDest++; szSrc++; assert (szDest < &szWbemInstance[MAX_PATH]); } *szDest++ = '/'; // parent/child delimiter
} szSrc = pCounterPathElements->szInstanceName; while (*szSrc != 0) { *szDest = *szSrc; if (*szSrc == BACKSLASH_L) { *++szDest = BACKSLASH_L; } szDest++; szSrc++; assert (szDest < &szWbemInstance[MAX_PATH]); } *szDest = 0; // apply the instance name format
lstrcatW (szFullPathBuffer, pCounterPathElements->szObjectName); lstrcatW (szFullPathBuffer, cszNameParam); lstrcatW (szFullPathBuffer, szWbemInstance); lstrcatW (szFullPathBuffer, cszDoubleQuote); } return ERROR_SUCCESS; }
PDH_FUNCTION PdhiWbemGetCounterPropertyName ( IWbemClassObject *pThisClass, LPCWSTR szCounterDisplayName, LPWSTR szPropertyName, DWORD dwPropertyNameSize ) { HRESULT hResult; PDH_STATUS pdhStatus = PDH_CSTATUS_NO_COUNTER; SAFEARRAY *psaNames = NULL; long lLower; long lUpper = 0; long lCount; BSTR bsPropName = NULL; BSTR bsCountertype = NULL; BSTR bsDisplayname = NULL; VARIANT vName, vCountertype; IWbemQualifierSet *pQualSet = NULL;
VariantInit (&vName); VariantInit (&vCountertype);
// get the properties of this class as a Safe Array
hResult = pThisClass->GetNames (NULL, WBEM_FLAG_NONSYSTEM_ONLY, NULL, &psaNames); if (hResult == WBEM_NO_ERROR) { hResult = SafeArrayGetLBound (psaNames, 1, &lLower); if (hResult == S_OK) { hResult = SafeArrayGetUBound (psaNames, 1, &lUpper); } if (hResult == S_OK) { bsCountertype = SysAllocString (cszCountertype); bsDisplayname = SysAllocString (cszDisplayname); if (bsCountertype && bsDisplayname) { for (lCount = lLower; lCount <= lUpper; lCount++) { hResult = SafeArrayGetElement (psaNames, &lCount, &bsPropName); if (hResult == S_OK) { // this is the desired counter so
// get the qualifier set for this property
hResult = pThisClass->GetPropertyQualifierSet ( bsPropName, &pQualSet); if (hResult == WBEM_NO_ERROR) { LONG lCounterType; // make sure this is a perf counter property
hResult = pQualSet->Get (bsCountertype, 0, &vCountertype, NULL); if (hResult == WBEM_NO_ERROR) { lCounterType = V_I4(&vCountertype); // then see if this is a displayable counter
if (!(lCounterType & PERF_DISPLAY_NOSHOW) || (lCounterType == PERF_AVERAGE_BULK)) { // by testing for the counter type
// get the display name for this property
hResult = pQualSet->Get (bsDisplayname, 0, &vName, NULL); if (hResult == WBEM_NO_ERROR) { // display name found compare it
if (lstrcmpiW(szCounterDisplayName, V_BSTR(&vName)) == 0) { // then this is the correct property so return
if ((DWORD)lstrlenW(bsPropName) < dwPropertyNameSize) { lstrcpyW (szPropertyName, (LPWSTR)bsPropName); pdhStatus = ERROR_SUCCESS; pQualSet->Release(); pQualSet = NULL; break; } else { pdhStatus = PDH_MORE_DATA; } } else { //not this property so continue
} } } else { // this is a "don't show" counter so skip it
} } else { // unable to get the counter type so it's probably
// not a perf counter property, skip it and continue
} VariantClear (&vName); VariantClear (&vCountertype); pQualSet->Release(); pQualSet = NULL; } else { // unable to read qualifiers so skip
continue; } } else { // unable to read element in SafeArray
pdhStatus = PDH_WBEM_ERROR; SetLastError(hResult); } } // end for each element in SafeArray
} else { pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE; } PdhiSysFreeString (&bsCountertype); PdhiSysFreeString (&bsDisplayname); } else { // unable to get array boundries
pdhStatus = PDH_WBEM_ERROR; SetLastError (hResult); }
} else { // unable to get property strings
pdhStatus = PDH_WBEM_ERROR; SetLastError (hResult); }
VariantClear (&vName); VariantClear (&vCountertype);
if (psaNames != NULL) { // Clear the SafeArray if it exists
SafeArrayDestroy( psaNames ); }
// make sure it was released
assert (pQualSet == NULL);
return pdhStatus; }
PDH_FUNCTION PdhiWbemGetCounterDisplayName ( IWbemClassObject *pThisClass, LPCWSTR szCounterName, LPWSTR szDisplayName, DWORD dwDisplayNameSize ) { HRESULT hResult; PDH_STATUS pdhStatus = PDH_CSTATUS_NO_COUNTER; SAFEARRAY *psaNames = NULL; long lLower; long lUpper = 0; long lCount; BSTR bsPropName = NULL; BSTR bsCountertype = NULL; BSTR bsDisplayname = NULL; VARIANT vName, vCountertype; IWbemQualifierSet *pQualSet = NULL;
VariantInit (&vName); VariantInit (&vCountertype);
// get the properties of this class as a Safe Array
hResult = pThisClass->GetNames (NULL, WBEM_FLAG_NONSYSTEM_ONLY, NULL, &psaNames); if (hResult == WBEM_NO_ERROR) { hResult = SafeArrayGetLBound (psaNames, 1, &lLower); if (hResult == S_OK) { hResult = SafeArrayGetUBound (psaNames, 1, &lUpper); } if (hResult == S_OK) { bsCountertype = SysAllocString (cszCountertype); bsDisplayname = SysAllocString (cszDisplayname); if (bsCountertype && bsDisplayname) { for (lCount = lLower; lCount <= lUpper; lCount++) { hResult = SafeArrayGetElement (psaNames, &lCount, &bsPropName); if (hResult == S_OK) { if (lstrcmpiW ((LPWSTR)bsPropName, szCounterName) == 0) { // this is the desired counter so
// get the qualifier set for this property
hResult = pThisClass->GetPropertyQualifierSet ( bsPropName, &pQualSet); if (hResult == WBEM_NO_ERROR) { LONG lCounterType; // make sure this is a perf counter property
hResult = pQualSet->Get (bsCountertype, 0, &vCountertype, NULL); if (hResult == WBEM_NO_ERROR) { lCounterType = V_I4(&vCountertype); // then see if this is a displayable counter
if (!(lCounterType & PERF_DISPLAY_NOSHOW) || (lCounterType == PERF_AVERAGE_BULK)) { // by testing for the counter type
// get the display name for this property
hResult = pQualSet->Get (bsDisplayname, 0, &vName, NULL); if (hResult == WBEM_NO_ERROR) { // display name found so copy and break
if ((DWORD)lstrlenW(V_BSTR(&vName)) < dwDisplayNameSize) { lstrcpyW (szDisplayName, V_BSTR(&vName)); pdhStatus = ERROR_SUCCESS; pQualSet->Release(); pQualSet = NULL; break; } else { pdhStatus = PDH_MORE_DATA; } } } else { // this is a "don't show" counter so skip it
} } else { // unable to get the counter type so it's probably
// not a perf counter property, skip it and continue
} VariantClear (&vName); VariantClear (&vCountertype); pQualSet->Release(); pQualSet = NULL; } else { // unable to read qualifiers so skip
continue; } } else { // aren't interested in this property, so
continue; } } else { // unable to read element in SafeArray
pdhStatus = PDH_WBEM_ERROR; SetLastError(hResult); } } // end for each element in SafeArray
} else { pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE; } PdhiSysFreeString (&bsCountertype); PdhiSysFreeString (&bsDisplayname); } else { // unable to get array boundries
pdhStatus = PDH_WBEM_ERROR; SetLastError (hResult); }
} else { // unable to get property strings
pdhStatus = PDH_WBEM_ERROR; SetLastError (hResult); }
VariantClear (&vName); VariantClear (&vCountertype);
// Clear the SafeArray if it exists
if ( NULL != psaNames ) { SafeArrayDestroy( psaNames ); } // make sure it was released
assert (pQualSet == NULL);
return pdhStatus; }
PDH_FUNCTION PdhiWbemGetClassObjectByName ( PPDHI_WBEM_SERVER_DEF pThisServer, LPCWSTR szClassName, IWbemClassObject **pReturnClass ) { PDH_STATUS pdhStatus = ERROR_SUCCESS;
HRESULT hResult; BSTR bsClassName;
IWbemClassObject *pThisClass = NULL;
bsClassName = SysAllocString (szClassName);
if (bsClassName) { hResult = pThisServer->pSvc->GetObject ( bsClassName, // class name
WBEM_FLAG_USE_AMENDED_QUALIFIERS, NULL, &pThisClass, NULL); PdhiSysFreeString (&bsClassName);
if (hResult != WBEM_NO_ERROR) { pdhStatus = PDH_WBEM_ERROR; SetLastError (hResult); } else { *pReturnClass = pThisClass; } } else { pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE; }
return (pdhStatus); }
PDH_FUNCTION PdhiWbemGetClassDisplayName ( PPDHI_WBEM_SERVER_DEF pThisServer, LPCWSTR szClassName, LPWSTR szClassDisplayName, DWORD dwClassDisplayNameSize, IWbemClassObject **pReturnClass ) { PDH_STATUS pdhStatus = ERROR_SUCCESS;
HRESULT hResult; BSTR bsClassName; BSTR bsClass; BSTR bsDisplayName; VARIANT vName; LPWSTR szDisplayName;
IWbemClassObject *pThisClass = NULL; IWbemQualifierSet *pQualSet = NULL;
VariantInit (&vName);
bsClassName = SysAllocString (szClassName);
if (bsClassName) { hResult = pThisServer->pSvc->GetObject ( bsClassName, // class name
WBEM_FLAG_USE_AMENDED_QUALIFIERS, NULL, &pThisClass, NULL); if (hResult != WBEM_NO_ERROR) { pdhStatus = PDH_WBEM_ERROR; SetLastError (hResult); } PdhiSysFreeString (&bsClassName); } else { pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE; }
if (pdhStatus == ERROR_SUCCESS) { // get the display name property of this class
pThisClass->GetQualifierSet (&pQualSet); if (pQualSet != NULL) { bsDisplayName = SysAllocString (cszDisplayname); if (bsDisplayName) { hResult = pQualSet->Get (bsDisplayName, 0, &vName, 0);
if (hResult == WBEM_E_NOT_FOUND) { // then this has not display name so
// pull the class name
bsClass = SysAllocString (cszClass); if (bsClass) { hResult = pThisClass->Get (bsClass, 0, &vName, 0, 0); PdhiSysFreeString (&bsClass); } else { hResult = WBEM_E_OUT_OF_MEMORY; } } else { hResult = WBEM_E_OUT_OF_MEMORY; } pQualSet->Release(); } else { hResult = WBEM_E_OUT_OF_MEMORY; } } else { hResult = WBEM_E_NOT_FOUND; }
if (hResult == WBEM_E_NOT_FOUND) { //unable to look up a display name so nothing to return
pdhStatus = PDH_WBEM_ERROR; SetLastError (hResult); } else if (hResult == WBEM_E_OUT_OF_MEMORY) { pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE; SetLastError(hResult); } else if (hResult == S_OK) { // copy string to caller's buffers
szDisplayName = V_BSTR(&vName); if ((DWORD)lstrlenW(szDisplayName) < dwClassDisplayNameSize) { lstrcpyW (szClassDisplayName, szDisplayName); pdhStatus = ERROR_SUCCESS; } if (pReturnClass != NULL) { // return the class pointer, the caller will close it
*pReturnClass = pThisClass; } else { // close it
pThisClass->Release(); } } }
VariantClear (&vName);
return pdhStatus; } BOOL PdhiIsSingletonClass ( IWbemClassObject *pThisClass ) { HRESULT hResult; BOOL bReturnValue = FALSE; //
BSTR bsSingleton = NULL; VARIANT vValue; IWbemQualifierSet *pQualSet = NULL;
bsSingleton = SysAllocString (cszSingleton);
if (bsSingleton) { VariantInit (&vValue); // get the display name of this class
pThisClass->GetQualifierSet (&pQualSet); if (pQualSet != NULL) { hResult = pQualSet->Get (bsSingleton, 0, &vValue, 0); pQualSet->Release(); } else { hResult = WBEM_E_NOT_FOUND; }
if (hResult == ERROR_SUCCESS) { bReturnValue = TRUE; }
VariantClear (&vValue); PdhiSysFreeString (&bsSingleton); } else { bReturnValue = FALSE; }
return bReturnValue; }
#pragma warning ( disable : 4127 )
PDH_FUNCTION PdhiEnumWbemServerObjects( IN PPDHI_WBEM_SERVER_DEF pThisServer, IN LPVOID mszObjectList, IN LPDWORD pcchBufferSize, IN DWORD dwDetailLevel, IN BOOL bRefresh, IN BOOL bUnicode );
PDH_FUNCTION PdhiWbemGetObjectClassName ( PPDHI_WBEM_SERVER_DEF pThisServer, LPCWSTR szObjectName, LPWSTR szObjectClassName, DWORD dwObjectClassNameSize, IWbemClassObject **pReturnClass ) { PDH_STATUS pdhStatus = ERROR_SUCCESS; HRESULT hResult; LONG lResult;
assert(pThisServer != NULL); assert(szObjectName != NULL); assert(szObjectClassName != NULL); assert(dwObjectClassNameSize > 0);
if (pThisServer->pObjList == NULL) { DWORD dwSize = 0; pdhStatus = PdhiEnumWbemServerObjects( pThisServer, NULL, & dwSize, PERF_DETAIL_WIZARD | PERF_DETAIL_COSTLY, TRUE, TRUE); if (pThisServer->pObjList != NULL) { pdhStatus = ERROR_SUCCESS; } }
if (pThisServer->pObjList != NULL) { PPDHI_WBEM_OBJECT_DEF pObject = pThisServer->pObjList;
pdhStatus = PDH_CSTATUS_NO_OBJECT; while (pObject != NULL) { lResult = lstrcmpiW(pObject->szDisplay, szObjectName); if (lResult == 0) { if ( ((DWORD) lstrlenW(pObject->szObject)) < dwObjectClassNameSize) { pdhStatus = ERROR_SUCCESS; lstrcpyW(szObjectClassName, pObject->szObject); } else { pdhStatus = PDH_MORE_DATA; }
if (pObject->pClass == NULL) { BSTR bsClassName = SysAllocString(pObject->szObject); if (bsClassName) { hResult = pThisServer->pSvc->GetObject( bsClassName, WBEM_FLAG_USE_AMENDED_QUALIFIERS, NULL, & pObject->pClass, NULL); if (hResult != WBEM_NO_ERROR) { SetLastError(hResult); pdhStatus = PDH_WBEM_ERROR; } else if (pReturnClass != NULL) { * pReturnClass = pObject->pClass; } } else { pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE; } } else if (pReturnClass != NULL) { * pReturnClass = pObject->pClass; } break; } pObject = pObject->pNext; } }
return pdhStatus; } #pragma warning ( default : 4127 )
PDH_FUNCTION PdhiAddWbemServer ( LPCWSTR szMachineName, PPDHI_WBEM_SERVER_DEF *pWbemServer ) { IWbemLocator *pWbemLocator = 0; IWbemServices *pWbemServices = 0; PDH_STATUS pdhStatus = ERROR_SUCCESS; HRESULT hResult; DWORD dwResult; DWORD dwStrLen = 0; PPDHI_WBEM_SERVER_DEF pNewServer = NULL; WCHAR szLocalMachineName[MAX_PATH]; WCHAR szLocalServerPath[MAX_PATH]; WCHAR szLocalNameSpaceString[MAX_PATH]; WCHAR szLocale[32];
// szMachineName can be null,
// that means use the local machine and default namespace
assert (pWbemServer != NULL);
// connect to locator
dwResult = CoCreateInstance (CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *)&pWbemLocator); if (dwResult != S_OK) { SetLastError (dwResult); pdhStatus = PDH_CANNOT_CONNECT_MACHINE; }
if (pdhStatus == ERROR_SUCCESS) { PdhiBreakWbemMachineName ( szMachineName, szLocalMachineName, szLocalNameSpaceString); lstrcpyW (szLocalServerPath, szLocalMachineName); lstrcatW (szLocalServerPath, szLocalNameSpaceString);
// Create the locale
swprintf( szLocale, L"MS_%hX", GetUserDefaultUILanguage());
// try to connect to the service
hResult = pWbemLocator->ConnectServer ( szLocalServerPath, NULL, NULL, szLocale, 0L, 0,0, &pWbemServices); if (hResult) { SetLastError (hResult); pdhStatus = PDH_CANNOT_CONNECT_WMI_SERVER; } else { dwStrLen = lstrlenW (szLocalMachineName ) + 1;
} // free the locator
pWbemLocator->Release(); }
// If we succeeded, we need to set Interface Security on the proxy and its
// IUnknown in order for Impersonation to correctly work.
if ( pdhStatus == ERROR_SUCCESS ) { pdhStatus = SetWbemSecurity( pWbemServices ); }
if (pdhStatus == ERROR_SUCCESS) { // everything went ok so save this connection
if (*pWbemServer == NULL) { // then this is a new connection
pNewServer = (PPDHI_WBEM_SERVER_DEF)G_ALLOC (sizeof (PDHI_WBEM_SERVER_DEF) + (dwStrLen * sizeof (WCHAR))); if (pNewServer == NULL) { pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE; } else { // insert this at the head of the list
pNewServer->pNext = pFirstWbemServer; pFirstWbemServer = pNewServer; pNewServer->szMachine = (LPWSTR)&pNewServer[1]; lstrcpyW (pNewServer->szMachine, szLocalMachineName); pNewServer->lRefCount = 0; // it'll be incremented in the connect function
*pWbemServer = pNewServer; } } else { // we are reconnecting and reusing an old memory block
// so just update the pointer
pNewServer = *pWbemServer; } // if reconnecting or connecting for the first time, this should be NULL
assert (pNewServer->pSvc == NULL);
if (pdhStatus == ERROR_SUCCESS) { // update fields
// load the name fields
pNewServer->pSvc = pWbemServices; pNewServer->pObjList = NULL; pNewServer->dwCache = 0; if (gp_GIT != NULL) { HRESULT hrTmp = gp_GIT->RegisterInterfaceInGlobal( pWbemServices, IID_IWbemServices, & (pNewServer->dwCache)); DebugPrint((3,"RegisterInterfaceInGlobal(0x%08X,0x%08X,%d)\n", hrTmp, pNewServer->pSvc, pNewServer->dwCache)); if (! SUCCEEDED(hrTmp)) { pWbemServices->Release(); pNewServer->pSvc = NULL; pNewServer->dwCache = 0; pdhStatus = PDH_WBEM_ERROR; } } else { pWbemServices->Release(); pNewServer->pSvc = NULL; pNewServer->dwCache = 0; pdhStatus = PDH_WBEM_ERROR; } } else { // something failed so return a NULL for the server pointer
*pWbemServer = NULL; } } else { // unable to connect so return NULL
*pWbemServer = NULL; }
// if there was an eror, then free the new sever memory
if ((* pWbemServer) == NULL) G_FREE(pNewServer);
return pdhStatus; }
PDH_FUNCTION PdhiCloseWbemServer ( PPDHI_WBEM_SERVER_DEF pWbemServer ) { assert (pWbemServer != NULL);
if (!bProcessIsDetaching) { if (pWbemServer != NULL) { if (pWbemServer->pObjList != NULL) { PPDHI_WBEM_OBJECT_DEF pObject = pWbemServer->pObjList; PPDHI_WBEM_OBJECT_DEF pNext;
pWbemServer->pObjList = NULL; while (pObject != NULL) { pNext = pObject->pNext; if (pObject->pClass != NULL) pObject->pClass->Release(); G_FREE(pObject); pObject = pNext; } } if (pWbemServer->pSvc != NULL) { // this is about all that's currently required
pWbemServer->pSvc->Release(); pWbemServer->pSvc = NULL; } else { // no server is connected
} } else { // no structure exists
} }
return ERROR_SUCCESS; }
PDH_FUNCTION PdhiConnectWbemServer ( LPCWSTR szMachineName, PPDHI_WBEM_SERVER_DEF *pWbemServer ) { PDH_STATUS pdhStatus = PDH_CANNOT_CONNECT_MACHINE; PPDHI_WBEM_SERVER_DEF pThisServer = NULL;
LPWSTR szWideMachineName = NULL; LPWSTR szWideNamespace = NULL; LPWSTR szMachineNameArg = NULL;
// get the local machine name & default name space if the caller
// has passed in a NULL machine name
if (szMachineName == NULL) { szWideMachineName = (LPWSTR) G_ALLOC (2048 + 1024); // this should be long enough
if (szWideMachineName == NULL) { pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE; } else { szWideNamespace = (LPWSTR)((LPBYTE)szWideMachineName + 2048); }
if (pdhStatus != PDH_MEMORY_ALLOCATION_FAILURE) { pdhStatus = PdhiBreakWbemMachineName ( NULL, szWideMachineName, szWideNamespace); // lstrcatW (szWideMachineName, cszBackSlash);
// lstrcatW (szWideMachineName, szWideNamespace);
szMachineNameArg = szWideMachineName; } } else { szMachineNameArg = (LPWSTR)szMachineName; pdhStatus = ERROR_SUCCESS; }
if (pdhStatus == ERROR_SUCCESS) { // walk down list of connected servers and find the requested one
assert (pWbemServer != NULL);
for (pThisServer = pFirstWbemServer; pThisServer != NULL; pThisServer = pThisServer->pNext) { // machine name includes the namespace
if (lstrcmpiW(pThisServer->szMachine, szMachineNameArg) == 0) { pdhStatus = ERROR_SUCCESS; break; } }
if (pThisServer == NULL) { // then add it to the list and return it
pdhStatus = PdhiAddWbemServer ( szMachineNameArg, &pThisServer); } else { // make sure the server is really there
// this is just a dummy call to see if the server will respond
// with an error or RPC will respond with an error that there's
// no server anymore.
HRESULT hrTest;
if (gp_GIT != NULL) { IWbemServices * pSvc = NULL;
hrTest = gp_GIT->GetInterfaceFromGlobal( pThisServer->dwCache, IID_IWbemServices, (void **) & pSvc); if (SUCCEEDED(hrTest)) { if (pSvc != pThisServer->pSvc) { DebugPrint((3,"GetInterfaceFromGlobal(0x%08X,%d,0x%08X,0x%08X)\n", hrTest, pThisServer->dwCache, pThisServer->pSvc, pSvc)); pThisServer->pSvc = NULL; if (pThisServer->pObjList != NULL) { PPDHI_WBEM_OBJECT_DEF pObject; PPDHI_WBEM_OBJECT_DEF pNext; pObject = pThisServer->pObjList; pThisServer->pObjList = NULL; while (pObject != NULL) { pNext = pObject->pNext; G_FREE(pObject); pObject = pNext; } } } } else { DebugPrint((3,"GetInterfaceFromGlobal(0x%08X,%d,0x%08X,0x%08X)\n", hrTest, pThisServer->dwCache, pThisServer->pSvc, pSvc)); pThisServer->pSvc = NULL; if (pThisServer->pObjList != NULL) { PPDHI_WBEM_OBJECT_DEF pObject; PPDHI_WBEM_OBJECT_DEF pNext; pObject = pThisServer->pObjList; pThisServer->pObjList = NULL; while (pObject != NULL) { pNext = pObject->pNext; G_FREE(pObject); pObject = pNext; } } } } else { pThisServer->pSvc = NULL; if (pThisServer->pObjList != NULL) { PPDHI_WBEM_OBJECT_DEF pObject; PPDHI_WBEM_OBJECT_DEF pNext; pObject = pThisServer->pObjList; pThisServer->pObjList = NULL; while (pObject != NULL) { pNext = pObject->pNext; G_FREE(pObject); pObject = pNext; } } } if (pThisServer->pSvc != NULL) { hrTest = pThisServer->pSvc->CancelAsyncCall(NULL); } else { // there is no service connected so set the HRESULT to
// get the next block to try and reconnect
hrTest = 0x800706BF; // some bad status value thats NOT WBEM_E_INVALID_PARAMETER
}
// if the error is WBEM_E_INVALID_PARAMETER then the server is there
// so we can continue
// else if the error is something else then try to reconnect by closing and
// reopening this connection
if (hrTest != WBEM_E_INVALID_PARAMETER) { PdhiCloseWbemServer(pThisServer); pdhStatus = PdhiAddWbemServer ( szMachineNameArg, &pThisServer); } }
*pWbemServer = pThisServer;
if (pdhStatus == ERROR_SUCCESS) pThisServer->lRefCount++; }
if (szWideMachineName != NULL) G_FREE (szWideMachineName);
return pdhStatus; }
PDH_FUNCTION PdhiFreeAllWbemServers ( ) { PPDHI_WBEM_SERVER_DEF pThisServer; PPDHI_WBEM_SERVER_DEF pNextServer;
pThisServer = pFirstWbemServer; while (pThisServer != NULL) { pNextServer = pThisServer->pNext; PdhiCloseWbemServer (pThisServer); G_FREE(pThisServer); pThisServer = pNextServer; } pFirstWbemServer = NULL;
if (gp_GIT != NULL) { gp_GIT->Release(); gp_GIT = NULL; }
return ERROR_SUCCESS; }
PDH_FUNCTION PdhiGetWbemExplainText ( IN LPCWSTR szMachineName, IN LPCWSTR szObjectName, IN LPCWSTR szCounterName, IN LPWSTR szExplain, IN LPDWORD pdwExplain ) { PDH_STATUS Status = ERROR_SUCCESS; HRESULT hResult; BOOL bDisconnect = FALSE; VARIANT vsExplain; WCHAR szObjectClassName[MAX_PATH];
PPDHI_WBEM_SERVER_DEF pThisServer = NULL; IEnumWbemClassObject * pEnum = NULL; IWbemClassObject * pThisObject = NULL; IWbemQualifierSet * pQualSet = NULL; BOOL fCoInitialized = PdhiCoInitialize();
if (szMachineName == NULL || szObjectName == NULL) { Status = PDH_INVALID_ARGUMENT; } if (szExplain != NULL && * pdwExplain != 0) { ZeroMemory(szExplain, * pdwExplain); }
if (Status == ERROR_SUCCESS) { Status = PdhiConnectWbemServer(szMachineName, &pThisServer); } if (Status == ERROR_SUCCESS) { bDisconnect = TRUE; Status = PdhiWbemGetObjectClassName( pThisServer, szObjectName, szObjectClassName, MAX_PATH, & pThisObject); }
if (Status == ERROR_SUCCESS) { VariantInit(& vsExplain);
if (szCounterName != NULL) { SAFEARRAY * psaNames = NULL; LONG lLower = 0; LONG lUpper = 0; LONG lCount = 0; BSTR bsPropName = NULL; VARIANT vName; VARIANT vCountertype; LONG lCounterType;
VariantInit (& vName); VariantInit (& vCountertype);
hResult = pThisObject->GetNames( NULL, WBEM_FLAG_NONSYSTEM_ONLY, NULL, & psaNames); if (hResult == WBEM_NO_ERROR) { hResult = SafeArrayGetLBound(psaNames, 1, & lLower); if (hResult == S_OK) { hResult = SafeArrayGetUBound(psaNames, 1, & lUpper); } if (hResult == S_OK) { for (lCount = lLower; lCount <= lUpper; lCount++) { hResult = SafeArrayGetElement( psaNames, & lCount, & bsPropName); if (hResult == S_OK) { hResult = pThisObject->GetPropertyQualifierSet( bsPropName, & pQualSet); if (hResult == S_OK) { hResult = pQualSet->Get( cszCountertype, 0, & vCountertype, NULL); if (hResult == S_OK) { lCounterType = V_I4(& vCountertype); if ( ! (lCounterType & PERF_DISPLAY_NOSHOW) || (lCounterType == PERF_AVERAGE_BULK)) { hResult = pQualSet->Get( cszDisplayname, 0, & vName, NULL); if ( hResult == S_OK && vName.vt == VT_BSTR) { if (lstrcmpiW(szCounterName, V_BSTR(& vName)) == 0) { hResult = pQualSet->Get( cszExplainText, 0, & vsExplain, NULL); if ( hResult == S_OK && vsExplain.vt == VT_BSTR) { LPWSTR szResult = V_BSTR(& vsExplain); if (((DWORD) lstrlenW(szResult)) < (* pdwExplain)) { lstrcpyW(szExplain, szResult); Status = ERROR_SUCCESS; } else { * pdwExplain = (DWORD) lstrlenW(szResult); Status = PDH_MORE_DATA; } } pQualSet->Release(); break; } } } } pQualSet->Release(); } } else { SetLastError(hResult); Status = PDH_WBEM_ERROR; } } } else { SetLastError(hResult); Status = PDH_WBEM_ERROR; } } else { SetLastError(hResult); Status = PDH_WBEM_ERROR; } VariantClear(& vName); VariantClear(& vCountertype); } else { // get counter object explain text
//
pThisObject->GetQualifierSet(& pQualSet); if (pQualSet != NULL) { hResult = pQualSet->Get(cszExplainText, 0, & vsExplain, 0); if (hResult == S_OK) { LPWSTR szResult = V_BSTR(& vsExplain); if (((DWORD) lstrlenW(szResult)) < (* pdwExplain)) { lstrcpyW(szExplain, szResult); Status = ERROR_SUCCESS; } else { * pdwExplain = (DWORD) lstrlenW(szResult); Status = PDH_MORE_DATA; } } else { SetLastError(hResult); Status = PDH_WBEM_ERROR; } pQualSet->Release(); } else { SetLastError(WBEM_E_NOT_FOUND); Status = PDH_WBEM_ERROR; } } //pThisObject->Release();
VariantClear(& vsExplain); }
if (bDisconnect) { if (Status == ERROR_SUCCESS) { Status = PdhiDisconnectWbemServer(pThisServer); } else { PdhiDisconnectWbemServer(pThisServer); } }
if ( fCoInitialized ) { PdhiCoUninitialize(); } return Status; }
PDH_FUNCTION PdhiEnumWbemMachines ( IN LPVOID pMachineList, IN LPDWORD pcchBufferSize, IN BOOL bUnicode ) { PDH_STATUS pdhStatus; PPDHI_WBEM_SERVER_DEF pThisServer = NULL; DWORD dwCharsLeftInBuffer = *pcchBufferSize; DWORD dwBufferSize = 0; DWORD dwStrLen; DWORD dwResult;
assert (pcchBufferSize != NULL);
// CoInitialize() if we need to
BOOL fCoInitialized = PdhiCoInitialize();
// test to see if we've connected to the local machine yet, if not then do it
if (pFirstWbemServer == NULL) { // add local machine
pdhStatus = PdhiAddWbemServer ( NULL, &pThisServer); }
// walk down list of known machines and find the machines that are using
// the specified name space.
pThisServer = pFirstWbemServer; while (pThisServer != NULL) { dwStrLen = lstrlenW (pThisServer->szMachine) + 1; if ((pMachineList != NULL) && (dwCharsLeftInBuffer > dwStrLen)) { // then it will fit so add it
dwResult = AddUniqueWideStringToMultiSz ( pMachineList, pThisServer->szMachine, bUnicode); if (dwResult > 0) { dwBufferSize = dwResult; dwCharsLeftInBuffer = *pcchBufferSize - dwBufferSize; } // else
// this string is already in the list so
// nothing was added
} else { // just add the string length to estimate the buffer size
// required
dwCharsLeftInBuffer = 0; // to prevent any other strings from being added
dwBufferSize += dwStrLen; } pThisServer = pThisServer->pNext; }// end of while loop
if (dwBufferSize <= *pcchBufferSize) { // the buffer size includes both term nulls
pdhStatus = ERROR_SUCCESS; } else { // add terminating MSZ Null char size
dwBufferSize++; // there wasn't enough room. See if a buffer was passed in
pdhStatus = PDH_MORE_DATA; } // return the size used or required
*pcchBufferSize = dwBufferSize;
// CoUninitialize if necessary
if ( fCoInitialized ) { PdhiCoUninitialize(); }
return pdhStatus; }
#pragma warning ( disable : 4127 )
PDH_FUNCTION PdhiEnumWbemServerObjects( IN PPDHI_WBEM_SERVER_DEF pThisServer, IN LPVOID mszObjectList, IN LPDWORD pcchBufferSize, IN DWORD dwDetailLevel, IN BOOL bRefresh, // ignored
IN BOOL bUnicode) { // this function enumerates the classes that are subclassed
// from the Win32_PerfRawData Superclass
PDH_STATUS pdhStatus = ERROR_SUCCESS; HRESULT hResult; DWORD dwCharsLeftInBuffer = *pcchBufferSize; DWORD dwBufferSize = 0; DWORD dwStrLen; DWORD dwRtnCount; DWORD dwResult; DWORD dwDetailLevelDesired; DWORD dwItemDetailLevel = 0; LPWSTR szClassName; VARIANT vName; VARIANT vClass; VARIANT vDetailLevel; BOOL bPerfDefault = FALSE; BSTR bsTemp = NULL; BSTR bsDisplayName = NULL; BSTR bsClass = NULL; BSTR bsCostly = NULL; BSTR bsDetailLevel = NULL; BSTR bsPerfDefault = NULL;
BOOL bGetCostlyItems = FALSE; BOOL bIsCostlyItem = FALSE; BOOL bDisconnectServer = FALSE;
IEnumWbemClassObject * pEnum = NULL; IWbemClassObject * pThisClass = NULL; IWbemQualifierSet * pQualSet = NULL;
PPDHI_WBEM_OBJECT_DEF pHead = NULL; PPDHI_WBEM_OBJECT_DEF pObject = NULL;
DBG_UNREFERENCED_PARAMETER(bRefresh);
VariantInit(& vName); VariantInit(& vClass); VariantInit(& vDetailLevel);
if (pThisServer->pObjList != NULL) { PPDHI_WBEM_OBJECT_DEF pObject = pThisServer->pObjList; PPDHI_WBEM_OBJECT_DEF pNext;
pThisServer->pObjList = NULL; while (pObject != NULL) { pNext = pObject->pNext; if (pObject->pClass != NULL) pObject->pClass->Release(); G_FREE(pObject); pObject = pNext; } }
// create an enumerator of the PerfRawData class
bsTemp = SysAllocString (cszPerfRawData); if (bsTemp) { hResult = pThisServer->pSvc->CreateClassEnum ( bsTemp, WBEM_FLAG_DEEP | WBEM_FLAG_USE_AMENDED_QUALIFIERS, NULL, & pEnum); PdhiSysFreeString(&bsTemp);
bDisconnectServer = TRUE; // Set security on the proxy
if (SUCCEEDED(hResult)) { hResult = SetWbemSecurity(pEnum); }
if (hResult != WBEM_NO_ERROR) { pdhStatus = PDH_WBEM_ERROR; SetLastError (hResult); } } else { pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE; }
if (pdhStatus == ERROR_SUCCESS) { // set costly flag
bGetCostlyItems = ((dwDetailLevel & PERF_DETAIL_COSTLY) == PERF_DETAIL_COSTLY); dwDetailLevelDesired = (DWORD)(dwDetailLevel & PERF_DETAIL_STANDARD); bsCostly = SysAllocString (cszCostly); bsDisplayName = SysAllocString (cszDisplayname); bsClass = SysAllocString (cszClass); bsDetailLevel = SysAllocString (cszPerfdetail); bsPerfDefault = SysAllocString(cszPerfdefault);
if (bsCostly && bsDisplayName && bsClass && bsDetailLevel) { while (TRUE) { hResult = pEnum->Next ( WBEM_INFINITE, // timeout
1, // return only 1 object
&pThisClass, &dwRtnCount);
// no more classes
if ((pThisClass == NULL) || (dwRtnCount == 0)) break;
// get the display name of this class
bIsCostlyItem = FALSE; // assume it's not unless proven otherwise
bPerfDefault = FALSE; hResult = pThisClass->Get(bsClass, 0, & vClass, 0, 0);
pThisClass->GetQualifierSet (&pQualSet); if (pQualSet != NULL) { VariantClear (&vName); hResult = pQualSet->Get (bsCostly, 0, &vName, 0); if (hResult == S_OK) { bIsCostlyItem = TRUE; } hResult = pQualSet->Get (bsDetailLevel, 0, &vDetailLevel, 0); if (hResult == S_OK) { dwItemDetailLevel = (DWORD)V_I4(&vDetailLevel); } else { dwItemDetailLevel = 0; }
VariantClear(&vName); hResult = pQualSet->Get(bsPerfDefault, 0, & vName, 0); if (hResult != WBEM_E_NOT_FOUND) { bPerfDefault = (BOOL) V_BOOL(& vName); }
VariantClear(&vName); hResult = pQualSet->Get(bsDisplayName, 0, & vName, 0); pQualSet->Release(); } else { hResult = WBEM_E_NOT_FOUND; }
if (hResult == WBEM_E_NOT_FOUND) { // then this has not display name so
// pull the class name
hResult = pThisClass->Get(bsClass, 0, & vName, 0, 0); }
if (hResult == WBEM_E_NOT_FOUND) { szClassName = (LPWSTR) cszNotFound; } else { szClassName = (LPWSTR) V_BSTR(&vName); }
if (((bIsCostlyItem && bGetCostlyItems) || // if costly and we want them
(!bIsCostlyItem)) && (dwItemDetailLevel <= dwDetailLevelDesired)) { dwStrLen = lstrlenW (szClassName) + 1; if ((mszObjectList != NULL) && (dwCharsLeftInBuffer > dwStrLen)) { // then it will fit so add it
dwResult = AddUniqueWideStringToMultiSz ( mszObjectList, szClassName, bUnicode); if (dwResult > 0) { dwBufferSize = dwResult; dwCharsLeftInBuffer = *pcchBufferSize - dwBufferSize; } // else
} else { // just add the string length to estimate the buffer size
// required
dwCharsLeftInBuffer = 0; // to prevent any other strings from being added
dwBufferSize += dwStrLen; } }
if (lstrcmpiW(szClassName, cszNotFound) != 0) { LPWSTR szClass = (LPWSTR) V_BSTR(& vClass); DWORD dwSize = sizeof(PDHI_WBEM_OBJECT_DEF) + sizeof(WCHAR) * ( lstrlenW(szClassName) + lstrlenW(szClass) + 2); pObject = (PPDHI_WBEM_OBJECT_DEF) G_ALLOC(dwSize); if (pObject != NULL) { pObject->bDefault = bPerfDefault; pObject->szObject = (LPWSTR) (((LPBYTE) pObject) + sizeof(PDHI_WBEM_OBJECT_DEF)); lstrcpyW(pObject->szObject, szClass); pObject->szDisplay = (LPWSTR) (((LPBYTE) pObject) + sizeof(PDHI_WBEM_OBJECT_DEF) + sizeof(WCHAR) * (lstrlenW(szClass) + 1)); lstrcpyW(pObject->szDisplay, szClassName); pObject->pNext = pHead; pHead = pObject; } else { pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE; pThisClass->Release(); break; } }
// clear the variant
VariantClear(& vName); VariantClear(& vClass); VariantClear(& vDetailLevel);
// free this class
pThisClass->Release(); } dwBufferSize ++; // the final NULL
if (dwBufferSize <= *pcchBufferSize) { pdhStatus = ERROR_SUCCESS; } else { // there wasn't enough room. See if a buffer was passed in
pdhStatus = PDH_MORE_DATA; } // return the size used or required
*pcchBufferSize = dwBufferSize; } } else { pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE; }
PdhiSysFreeString(& bsDisplayName); PdhiSysFreeString(& bsClass); PdhiSysFreeString(& bsCostly); PdhiSysFreeString(& bsDetailLevel); PdhiSysFreeString(& bsPerfDefault);
VariantClear(& vName); VariantClear(& vClass); VariantClear(& vDetailLevel);
if (pEnum != NULL) pEnum->Release();
if (pdhStatus == ERROR_SUCCESS || pdhStatus == PDH_MORE_DATA) { pThisServer->pObjList = pHead; } else { pObject = pHead; while (pObject != NULL) { pHead = pObject->pNext; G_FREE(pObject); pObject = pHead; } }
if (bDisconnectServer) { if (pdhStatus == ERROR_SUCCESS) { pdhStatus = PdhiDisconnectWbemServer (pThisServer); } else { // keep error code from function body
PdhiDisconnectWbemServer (pThisServer); } }
return pdhStatus; }
PDH_FUNCTION PdhiEnumWbemObjects( IN LPCWSTR szWideMachineName, IN LPVOID mszObjectList, IN LPDWORD pcchBufferSize, IN DWORD dwDetailLevel, IN BOOL bRefresh, // ignored
IN BOOL bUnicode) { PDH_STATUS pdhStatus; PPDHI_WBEM_SERVER_DEF pThisServer; BOOL fCoInitialized = PdhiCoInitialize();
pdhStatus = PdhiConnectWbemServer(szWideMachineName, & pThisServer); if (pdhStatus == ERROR_SUCCESS) { pdhStatus = PdhiEnumWbemServerObjects(pThisServer, mszObjectList, pcchBufferSize, dwDetailLevel, bRefresh, bUnicode); }
if (fCoInitialized) { PdhiCoUninitialize(); }
return pdhStatus; }
PDH_FUNCTION PdhiGetDefaultWbemObject ( IN LPCWSTR szMachineName, IN LPVOID szDefaultObjectName, IN LPDWORD pcchBufferSize, IN BOOL bUnicode) { // walk down the list of WBEM perf classes and find the one with the
// default qualifier
PDH_STATUS pdhStatus; PPDHI_WBEM_SERVER_DEF pThisServer; HRESULT hResult; DWORD dwBufferSize = 0; DWORD dwStrLen; BOOL bDisconnectServer = FALSE;
// CoInitialize() if we need to
BOOL fCoInitialized = PdhiCoInitialize();
pdhStatus = PdhiConnectWbemServer ( szMachineName, &pThisServer);
if (pdhStatus == ERROR_SUCCESS) { bDisconnectServer = TRUE; if (pThisServer->pObjList == NULL) { DWORD dwSize = 0; pdhStatus = PdhiEnumWbemServerObjects( pThisServer, NULL, & dwSize, PERF_DETAIL_WIZARD | PERF_DETAIL_COSTLY, TRUE, TRUE); if (pThisServer->pObjList != NULL) { pdhStatus = ERROR_SUCCESS; } }
if (pThisServer->pObjList != NULL) { PPDHI_WBEM_OBJECT_DEF pObject = pThisServer->pObjList;
pdhStatus = PDH_CSTATUS_NO_OBJECT; while (pObject != NULL) { if (pObject->bDefault) { pdhStatus = ERROR_SUCCESS; if (bUnicode) { dwStrLen = lstrlenW(pObject->szDisplay); if ( szDefaultObjectName != NULL && dwStrLen < * pcchBufferSize) { lstrcpyW((LPWSTR) szDefaultObjectName, pObject->szDisplay); } else { pdhStatus = PDH_MORE_DATA; } dwBufferSize = dwStrLen + 1; } else { dwStrLen = * pcchBufferSize; pdhStatus = PdhiConvertUnicodeToAnsi( _getmbcp(), pObject->szDisplay, (LPSTR) szDefaultObjectName, & dwStrLen); dwBufferSize = dwStrLen; } } pObject = pObject->pNext; } } }
// return the size used or required
* pcchBufferSize = dwBufferSize;
if (bDisconnectServer) { if (pdhStatus == ERROR_SUCCESS) { pdhStatus = PdhiDisconnectWbemServer (pThisServer); } else { // keep error code from function body
PdhiDisconnectWbemServer (pThisServer); } }
// CoUninitialize if necessary
if ( fCoInitialized ) { PdhiCoUninitialize(); }
return pdhStatus; }
PDH_FUNCTION PdhiEnumWbemObjectItems ( IN LPCWSTR szWideMachineName, IN LPCWSTR szWideObjectName, IN LPVOID mszCounterList, IN LPDWORD pcchCounterListLength, IN LPVOID mszInstanceList, IN LPDWORD pcchInstanceListLength, IN DWORD dwDetailLevel, IN DWORD dwFlags, IN BOOL bUnicode ) { PDH_STATUS pdhStatus = ERROR_SUCCESS; PDH_STATUS CounterStatus = ERROR_SUCCESS; PDH_STATUS InstanceStatus = ERROR_SUCCESS; DWORD dwStrLen; PPDHI_WBEM_SERVER_DEF pThisServer; HRESULT hResult; DWORD dwReturnCount; DWORD dwCounterStringLen = 0; DWORD dwInstanceStringLen = 0; LPWSTR szNextWideString = NULL; LPSTR szNextAnsiString = NULL; WCHAR szObjectClassName[MAX_PATH]; BSTR bsName = NULL; BSTR bsClassName = NULL; BOOL bSingletonClass = FALSE; VARIANT vName; DWORD bDisconnectServer = FALSE;
IWbemClassObject *pThisClass = NULL; IWbemQualifierSet *pQualSet = NULL;
DBG_UNREFERENCED_PARAMETER (dwFlags);
assert (szWideObjectName != NULL); assert (pcchCounterListLength != NULL); assert (pcchInstanceListLength != NULL);
// CoInitialize() if we need to
BOOL fCoInitialized = PdhiCoInitialize();
pdhStatus = PdhiConnectWbemServer ( szWideMachineName, &pThisServer);
// enumerate the instances
if (pdhStatus == ERROR_SUCCESS) { pdhStatus = PdhiWbemGetObjectClassName ( pThisServer, szWideObjectName, &szObjectClassName[0], sizeof(szObjectClassName) / sizeof(szObjectClassName[0]), &pThisClass);
assert (pThisClass != NULL);
bDisconnectServer = TRUE;
if (pdhStatus == ERROR_SUCCESS) { bSingletonClass = PdhiIsSingletonClass (pThisClass); } else if (pThisClass == NULL) { pdhStatus = PDH_CSTATUS_NO_OBJECT; } else { // unable to find matching perf class
// return status returned by method
} }
//enumerate the counter properties
if (pdhStatus == ERROR_SUCCESS) { SAFEARRAY *psaNames = NULL; long lLower; long lUpper = 0; long lCount; BSTR bsPropName = NULL; BSTR bsCountertype = NULL; BSTR bsDisplayname = NULL; BSTR bsDetailLevel = NULL; VARIANT vCountertype; VARIANT vDetailLevel; DWORD dwItemDetailLevel;
VariantInit (&vName); VariantInit (&vCountertype); VariantInit (&vDetailLevel);
assert (pThisClass != NULL);
dwDetailLevel &= PERF_DETAIL_STANDARD; // mask off any inappropriate bits
// get the properties of this class as a Safe Array
hResult = pThisClass->GetNames (NULL, WBEM_FLAG_NONSYSTEM_ONLY, NULL, &psaNames); if (hResult == WBEM_NO_ERROR) { hResult = SafeArrayGetLBound (psaNames, 1, &lLower); if (hResult == S_OK) { hResult = SafeArrayGetUBound (psaNames, 1, &lUpper); } if (hResult == S_OK) { szNextAnsiString = (LPSTR)mszCounterList; szNextWideString = (LPWSTR)mszCounterList; bsCountertype = SysAllocString (cszCountertype); bsDisplayname = SysAllocString (cszDisplayname); bsDetailLevel = SysAllocString (cszPerfdetail); if (bsCountertype && bsDisplayname && bsDetailLevel) { for (lCount = lLower; lCount <= lUpper; lCount++) { hResult = SafeArrayGetElement (psaNames, &lCount, &bsPropName); if (hResult == S_OK) { // get the qualifier set for this property
hResult = pThisClass->GetPropertyQualifierSet ( bsPropName, &pQualSet); if (hResult == WBEM_NO_ERROR) { LONG lCounterType; hResult = pQualSet->Get (bsDetailLevel, 0, &vDetailLevel, 0); if (hResult == S_OK) { dwItemDetailLevel = (DWORD)V_I4(&vDetailLevel); } else { dwItemDetailLevel = 0; }
// make sure this is a perf counter property
hResult = pQualSet->Get (bsCountertype, 0, &vCountertype, NULL); if (hResult == WBEM_NO_ERROR) { lCounterType = V_I4(&vCountertype); // then see if this is a displayable counter
if ((!(lCounterType & PERF_DISPLAY_NOSHOW) || (lCounterType == PERF_AVERAGE_BULK)) && (dwItemDetailLevel <= dwDetailLevel)) { // by testing for the counter type
// get the display name for this property
hResult = pQualSet->Get (bsDisplayname, 0, &vName, NULL); if (hResult == WBEM_NO_ERROR && vName.vt == VT_BSTR) { // display name found
if (bUnicode) { dwStrLen = lstrlenW (V_BSTR(&vName)) + 1; if ( (mszCounterList != NULL) && ( (dwCounterStringLen + dwStrLen) <= (* pcchCounterListLength))) { lstrcpyW (szNextWideString, V_BSTR(&vName)); szNextWideString += dwStrLen; } else { pdhStatus = PDH_MORE_DATA; } } else { dwStrLen = (dwCounterStringLen < * pcchCounterListLength) ? (* pcchCounterListLength - dwCounterStringLen) : (0); pdhStatus = PdhiConvertUnicodeToAnsi(_getmbcp(), V_BSTR(& vName), szNextAnsiString, & dwStrLen); if (pdhStatus == ERROR_SUCCESS) { szNextAnsiString += dwStrLen; } } dwCounterStringLen += dwStrLen; } } else { // this is a "don't show" counter so skip it
} } else { // unable to get the counter type so it's probably
// not a perf counter property, skip it and continue
} VariantClear (&vName); VariantClear (&vCountertype); VariantClear (&vDetailLevel);
pQualSet->Release(); } else { // no properties so continue with the next one
} } else { // unable to read element in SafeArray
pdhStatus = PDH_WBEM_ERROR; SetLastError(hResult); } } // end for each element in SafeArray
} else { pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE; } PdhiSysFreeString (&bsCountertype); PdhiSysFreeString (&bsDisplayname); PdhiSysFreeString (&bsDetailLevel); } else { // unable to get array boundries
pdhStatus = PDH_WBEM_ERROR; SetLastError (hResult); } } else { // unable to get property strings
pdhStatus = PDH_WBEM_ERROR; SetLastError (hResult); }
dwCounterStringLen ++; // final NULL for MSZ
if (dwCounterStringLen > * pcchCounterListLength) { pdhStatus = PDH_MORE_DATA; }
if (pdhStatus == ERROR_SUCCESS) { if (bUnicode) { if (szNextWideString != NULL) { if (szNextWideString != (LPWSTR)mszCounterList) { *szNextWideString++ = 0; } else { // nothing returned
dwCounterStringLen = 0; } } else { // then this is just a length query so return
// include the the MSZ term null char
CounterStatus = PDH_MORE_DATA; } } else { if (szNextAnsiString != NULL) { if (szNextAnsiString != (LPSTR)mszCounterList) { *szNextAnsiString ++ = 0; } else { dwCounterStringLen = 0; } } else { // then this is just a length query so return
// include the the MSZ term null char
CounterStatus = PDH_MORE_DATA; } } } else { CounterStatus = pdhStatus; }
VariantClear (&vName); VariantClear (&vCountertype); VariantClear (&vDetailLevel);
// Clear the SafeArray if it exists
if ( NULL != psaNames ) { SafeArrayDestroy( psaNames ); psaNames = NULL; }
*pcchCounterListLength = dwCounterStringLen;
//pThisClass->Release();
}
// Get instance strings if necessary
if (pdhStatus == ERROR_SUCCESS || pdhStatus == PDH_MORE_DATA) { szNextAnsiString = (LPSTR) mszInstanceList; szNextWideString = (LPWSTR) mszInstanceList;
if (!bSingletonClass) { IWbemRefresher * pRefresher = NULL; IWbemConfigureRefresher * pConfig = NULL; IWbemHiPerfEnum * pEnum = NULL; LONG lID; DWORD dwNumReturned = 1; DWORD dwNumObjects = 0; DWORD i; IWbemObjectAccess ** apEnumAccess = NULL; CIMTYPE cimType; WCHAR szName[SMALL_BUFFER_SIZE]; LONG lNameHandle = -1; LONG lSize1 = SMALL_BUFFER_SIZE; LONG lSize2 = 0;
hResult = CoCreateInstance(CLSID_WbemRefresher, NULL, CLSCTX_INPROC_SERVER, IID_IWbemRefresher, (void **) & pRefresher); if (SUCCEEDED(hResult)) { hResult = pRefresher->QueryInterface( IID_IWbemConfigureRefresher, (void **) & pConfig); if (SUCCEEDED(hResult)) { hResult = pConfig->AddEnum(pThisServer->pSvc, szObjectClassName, 0, NULL, & pEnum, & lID); if (SUCCEEDED(hResult)) { hResult = pRefresher->Refresh(0L); if (SUCCEEDED(hResult)) { hResult = pEnum->GetObjects(0L, dwNumObjects, apEnumAccess, & dwNumReturned); if (hResult == WBEM_E_BUFFER_TOO_SMALL) { apEnumAccess = (IWbemObjectAccess **) G_ALLOC(dwNumReturned * sizeof(IWbemObjectAccess *)); if (apEnumAccess != NULL) { ZeroMemory(apEnumAccess, dwNumReturned * sizeof(IWbemObjectAccess *)); dwNumObjects = dwNumReturned; hResult = pEnum->GetObjects(0L, dwNumObjects, apEnumAccess, & dwNumReturned); } else { hResult = WBEM_E_OUT_OF_MEMORY; } } if (SUCCEEDED(hResult)) { for (i = 0; i < dwNumReturned; i ++) { hResult = apEnumAccess[i]->GetPropertyHandle( cszName, & cimType, & lNameHandle); if (SUCCEEDED(hResult) && lNameHandle != -1) { ZeroMemory(szName, SMALL_BUFFER_SIZE * sizeof(WCHAR)); hResult = apEnumAccess[i]->ReadPropertyValue( lNameHandle, lSize1, & lSize2, (LPBYTE) szName); if (SUCCEEDED(hResult) && lstrlenW(szName) > 0) { if (bUnicode) { dwStrLen = lstrlenW(szName) + 1; if ( (mszInstanceList != NULL) && ( (dwInstanceStringLen + dwStrLen) < (* pcchInstanceListLength))) { lstrcpyW (szNextWideString, szName); szNextWideString += dwStrLen; } else { pdhStatus = PDH_MORE_DATA; } } else { dwStrLen = (dwInstanceStringLen <= * pcchInstanceListLength) ? (* pcchInstanceListLength - dwInstanceStringLen) : (0); pdhStatus = PdhiConvertUnicodeToAnsi( _getmbcp(), szName, szNextAnsiString, & dwStrLen); if (pdhStatus == ERROR_SUCCESS) { szNextAnsiString += dwStrLen; } } dwInstanceStringLen += dwStrLen; } } apEnumAccess[i]->Release(); } } } } } }
if (! SUCCEEDED(hResult)) { SetLastError(hResult); pdhStatus = PDH_WBEM_ERROR; } else if (dwInstanceStringLen == 0) { dwInstanceStringLen = 2; if ( szNextWideString != NULL && dwInstanceStringLen <= * pcchInstanceListLength) { * szNextWideString = L'\0'; szNextWideString ++; } if ( szNextAnsiString != NULL && dwInstanceStringLen <= * pcchInstanceListLength) { * szNextAnsiString = '\0'; szNextAnsiString ++; } } else { dwInstanceStringLen ++; }
if (apEnumAccess != NULL) G_FREE(apEnumAccess); if (pEnum != NULL) pEnum->Release(); if (pConfig != NULL) pConfig->Release(); if (pRefresher != NULL) pRefresher->Release(); }
if (dwInstanceStringLen > * pcchInstanceListLength) { pdhStatus = PDH_MORE_DATA; } if (pdhStatus == ERROR_SUCCESS) { if (bUnicode) { if (szNextWideString != NULL) { if (szNextWideString != (LPWSTR)mszInstanceList) { *szNextWideString++ = 0; } else { dwInstanceStringLen = 0; } } else if (dwInstanceStringLen > 0) { // then this is just a length query so return
// include the the MSZ term null char
InstanceStatus = PDH_MORE_DATA; } } else { if (szNextAnsiString != NULL) { if (szNextAnsiString != (LPSTR)mszInstanceList) { *szNextAnsiString++ = 0; } else { dwInstanceStringLen = 0; } } else if (dwInstanceStringLen > 0) { // then this is just a length query so return
// include the the MSZ term null char
InstanceStatus = PDH_MORE_DATA; } } } else { InstanceStatus = pdhStatus; } *pcchInstanceListLength = dwInstanceStringLen; }
VariantClear (&vName);
if (bDisconnectServer) { if (pdhStatus == ERROR_SUCCESS) { pdhStatus = PdhiDisconnectWbemServer (pThisServer); } else { // keep error code from function body
PdhiDisconnectWbemServer (pThisServer); } }
// CoUninitialize if necessary
if ( fCoInitialized ) { PdhiCoUninitialize(); }
if (pdhStatus == ERROR_SUCCESS) { pdhStatus = (CounterStatus == ERROR_SUCCESS) ? (InstanceStatus) : (CounterStatus); }
return pdhStatus; } #pragma warning ( default : 4127 )
PDH_FUNCTION PdhiGetDefaultWbemProperty ( IN LPCWSTR szMachineName, IN LPCWSTR szObjectName, IN LPVOID szDefaultCounterName, IN LPDWORD pcchBufferSize, IN BOOL bUnicode ) { PDH_STATUS pdhStatus = ERROR_SUCCESS; DWORD dwStrLen; PPDHI_WBEM_SERVER_DEF pThisServer; HRESULT hResult; DWORD dwCounterStringLen = 0; WCHAR szObjectClassName[MAX_PATH]; DWORD bDisconnectServer = FALSE; BOOL bFound = FALSE;
IWbemClassObject *pThisClass = NULL; IWbemQualifierSet *pQualSet = NULL;
assert (szMachineName != NULL); assert (szObjectName != NULL); assert (pcchBufferSize != NULL);
// CoInitialize() if we need to
BOOL fCoInitialized = PdhiCoInitialize();
pdhStatus = PdhiConnectWbemServer ( szMachineName, &pThisServer);
// enumerate the instances
if (pdhStatus == ERROR_SUCCESS) { pdhStatus = PdhiWbemGetObjectClassName ( pThisServer, szObjectName, &szObjectClassName[0], sizeof(szObjectClassName) / sizeof(szObjectClassName[0]), &pThisClass); bDisconnectServer = TRUE; }
//enumerate the counter properties
if (pdhStatus == ERROR_SUCCESS) { SAFEARRAY *psaNames = NULL; long lLower; long lUpper = 0; long lCount; BSTR bsPropName = NULL; BSTR bsDisplayname = NULL; BSTR bsPerfDefault = NULL; VARIANT vName, vCountertype;
VariantInit (&vName); VariantInit (&vCountertype);
// get the properties of this class as a Safe Array
hResult = pThisClass->GetNames (NULL, WBEM_FLAG_NONSYSTEM_ONLY, NULL, &psaNames); if (hResult == WBEM_NO_ERROR) { hResult = SafeArrayGetLBound (psaNames, 1, &lLower); if (hResult == S_OK) { hResult = SafeArrayGetUBound (psaNames, 1, &lUpper); } if (hResult == S_OK) { bsDisplayname = SysAllocString (cszDisplayname); bsPerfDefault = SysAllocString (cszPerfdefault); if (bsDisplayname && bsPerfDefault) { for (lCount = lLower; lCount <= lUpper; lCount++) { hResult = SafeArrayGetElement (psaNames, &lCount, &bsPropName); if (hResult == S_OK) { // get the qualifier set for this property
hResult = pThisClass->GetPropertyQualifierSet ( bsPropName, &pQualSet); if (hResult == WBEM_NO_ERROR) { // make sure this is a perf counter property
hResult = pQualSet->Get (bsPerfDefault, 0, &vCountertype, NULL); if (hResult == WBEM_NO_ERROR) { if ((BOOL)V_BOOL(&vCountertype)) { // found the default property so load it and return
hResult = pQualSet->Get (bsDisplayname, 0, &vName, NULL); if (hResult == WBEM_NO_ERROR) { // display name found
bFound = TRUE; if (bUnicode) { dwStrLen = lstrlenW (V_BSTR(&vName)) + 1; if ( (szDefaultCounterName != NULL) && (dwStrLen <= * pcchBufferSize)) { lstrcpyW ((LPWSTR)szDefaultCounterName, (LPWSTR)V_BSTR(&vName)); } else { pdhStatus = PDH_MORE_DATA; } } else { dwStrLen = * pcchBufferSize; pdhStatus = PdhiConvertUnicodeToAnsi(_getmbcp(), (LPWSTR) V_BSTR(& vName), (LPSTR) szDefaultCounterName, & dwStrLen); } // this is either the amount used or the amount needed
dwCounterStringLen = dwStrLen; // free qualifier set
pQualSet->Release(); // now leave
break; } else { // no qualifier so assume FALSE
} } else { // value found but is FALSE
} } // free the qualifier set
pQualSet->Release(); // clear variants
VariantClear (&vName); VariantClear (&vCountertype); } else { // no Qualifiers so continue with the next one
} } else { // unable to read element in SafeArray
pdhStatus = PDH_WBEM_ERROR; SetLastError(hResult); } } // end for each element in SafeArray
} else { pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE; } // no default defined for this object
if ((pdhStatus == ERROR_SUCCESS) && !bFound) pdhStatus = PDH_CSTATUS_NO_COUNTER;
PdhiSysFreeString (&bsPerfDefault); PdhiSysFreeString (&bsDisplayname); } else { // unable to get array boundries
pdhStatus = PDH_WBEM_ERROR; SetLastError (hResult); } } else { // unable to get property strings
pdhStatus = PDH_WBEM_ERROR; SetLastError (hResult); }
if ( NULL != psaNames ) { SafeArrayDestroy( psaNames ); }
VariantClear (&vName); VariantClear (&vCountertype);
//pThisClass->Release();
} *pcchBufferSize = dwCounterStringLen;
if (bDisconnectServer) { if (pdhStatus == ERROR_SUCCESS) { pdhStatus = PdhiDisconnectWbemServer (pThisServer); } else { // keep error code from function body
PdhiDisconnectWbemServer (pThisServer); } }
// CoUninitialize if necessary
if ( fCoInitialized ) { PdhiCoUninitialize(); }
return pdhStatus; }
PDH_FUNCTION PdhiEncodeWbemPathW ( IN PDH_COUNTER_PATH_ELEMENTS_W *pCounterPathElements, IN LPWSTR szFullPathBuffer, IN LPDWORD pcchBufferSize, IN LANGID LangId, IN DWORD dwFlags ) /*++
converts a set of path elements in either Registry or WBEM format to a path in either Registry or WBEM format as defined by the flags.
--*/ { PDH_STATUS pdhStatus = ERROR_SUCCESS; DWORD dwBuffSize; LPWSTR szTempPath = NULL; DWORD dwCurSize = 0;
LPWSTR szThisChar; IWbemClassObject *pWbemClass = NULL; PPDHI_WBEM_SERVER_DEF pWbemServer = NULL; DWORD bDisconnectServer = FALSE;
DBG_UNREFERENCED_PARAMETER (LangId);
assert (pCounterPathElements != NULL); // this is not allowed
assert (dwFlags != 0); // this should be caught by the calling fn.
assert (pcchBufferSize != NULL); // this is required
// CoInitialize() if we need to
BOOL fCoInitialized = PdhiCoInitialize();
// create a working buffer the same size as the one passed in
if (*pcchBufferSize == 0L) { dwBuffSize = *pcchBufferSize * sizeof(WCHAR); } else { dwBuffSize = 1024 * sizeof(WCHAR); // just something to work with
}
szTempPath = (LPWSTR) G_ALLOC(dwBuffSize);
if (szTempPath == NULL) { pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE; } else if (pdhStatus == ERROR_SUCCESS) { szTempPath[0] = L'\0'; // start by adding the machine name to the path
if (pCounterPathElements->szMachineName != NULL) { lstrcpyW (szTempPath, pCounterPathElements->szMachineName); if (dwFlags == (PDH_PATH_WBEM_INPUT)) { // if this is a wbem element in to a registry path out,
// then remove the namespace which occurs starting at the
// second backslash
for (szThisChar = &szTempPath[2]; (*szThisChar != 0) && (*szThisChar != L'\\'); szThisChar++); if (*szThisChar != 0) *szThisChar = 0; } else if (dwFlags == (PDH_PATH_WBEM_RESULT)) { // if this is a registry element in to a WBEM out, then
// append the default namespace to the machine name
//NAMEFIX lstrcatW (szTempPath, cszWbemDefaultPerfRoot);
} } else { // no machine name specified so add the default machine
// and default namespace for a wbem output path
if (dwFlags == (PDH_PATH_WBEM_RESULT)) { lstrcpyW (szTempPath, cszDoubleBackSlashDot); // default machine
//NAMEFIX lstrcatW (szTempPath, cszWbemDefaultPerfRoot);
} else { // no entry required for the registry path
} } dwCurSize = lstrlenW(szTempPath);
// now add the object or class name
if (pdhStatus == ERROR_SUCCESS) { if (pCounterPathElements->szObjectName != NULL) { DWORD dwSize; WCHAR szTempObjectString[1024]; dwSize = 1024; ZeroMemory(szTempObjectString, sizeof(WCHAR) * 1024); // then the input is different from the output
// so convert from one to the other
// and default name space since perf counters won't be
// found elsewhere
pdhStatus = PdhiConnectWbemServer ( NULL, // use local machine
&pWbemServer); if (pdhStatus == ERROR_SUCCESS) { bDisconnectServer = TRUE; if (dwFlags & PDH_PATH_WBEM_INPUT) { // convert the WBEM Class to the display name
pdhStatus = PdhiWbemGetClassDisplayName ( pWbemServer, pCounterPathElements->szObjectName, &szTempObjectString[0], dwSize, &pWbemClass); // add a backslash path separator for registry output
if (pdhStatus == ERROR_SUCCESS) { if (dwFlags & PDH_PATH_WBEM_RESULT) { lstrcatW(szTempPath, cszColon); // just copy the string, but save
lstrcpyW (szTempObjectString, pCounterPathElements->szObjectName); } else { lstrcatW(szTempPath, cszBackSlash); // copy the retrieved string
} } } else { // convert the display name to a Wbem class name
pdhStatus = PdhiWbemGetObjectClassName ( pWbemServer, pCounterPathElements->szObjectName, &szTempObjectString[0], dwSize, &pWbemClass); // add a colon path separator
lstrcatW(szTempPath, cszColon); } if (pdhStatus == ERROR_SUCCESS) { //then add the string
lstrcatW(szTempPath, szTempObjectString); dwCurSize += lstrlenW(szTempObjectString) + 1; // includes delimiter
}
if (bDisconnectServer) { if (pdhStatus == ERROR_SUCCESS) { pdhStatus = PdhiDisconnectWbemServer (pWbemServer); } else { // keep error code from function body
PdhiDisconnectWbemServer (pWbemServer); } } } } else { // no object name, so bad structure
pdhStatus = PDH_CSTATUS_NO_OBJECT; }
}
// check for instance entries to add before adding the counter.
if (pdhStatus == ERROR_SUCCESS) { if (pCounterPathElements->szInstanceName != NULL) { lstrcatW (szTempPath, cszLeftParen); dwCurSize += 1; if (pCounterPathElements->szParentInstance != NULL) { lstrcatW (szTempPath, pCounterPathElements->szParentInstance); lstrcatW (szTempPath, cszSlash); dwCurSize += lstrlenW( pCounterPathElements->szParentInstance ) + 1; } lstrcatW (szTempPath, pCounterPathElements->szInstanceName); lstrcatW (szTempPath, cszRightParen); dwCurSize += lstrlenW( pCounterPathElements->szInstanceName ) + 1; } else { // this is OK
assert (pCounterPathElements->szParentInstance == NULL); assert (pCounterPathElements->dwInstanceIndex == 0); } }
// add counter name
if (pdhStatus == ERROR_SUCCESS) { if (pCounterPathElements->szCounterName != NULL) { DWORD dwSize; WCHAR szTempCounterString[1024];
dwSize = 1024; // then the input is different from the output
// so convert from one to the other
// and default name space since perf counters won't be
// found elsewhere
assert (pWbemServer != NULL); if (pdhStatus == ERROR_SUCCESS) { // add a backslash path separator
lstrcatW(szTempPath, cszBackSlash); if (dwFlags & PDH_PATH_WBEM_INPUT) { // convert the WBEM Class to the display name
pdhStatus = PdhiWbemGetCounterDisplayName ( pWbemClass, pCounterPathElements->szCounterName, &szTempCounterString[0], dwSize); if (dwFlags & PDH_PATH_WBEM_RESULT) { // just copy the string, but save
// the class pointer
lstrcpyW (szTempCounterString, pCounterPathElements->szCounterName); } else { // copy the retrieved string
} } else { // convert the display name to a Wbem class name
pdhStatus = PdhiWbemGetCounterPropertyName ( pWbemClass, pCounterPathElements->szCounterName, &szTempCounterString[0], dwSize); } if (pdhStatus == ERROR_SUCCESS) { //then add the string
lstrcatW(szTempPath, szTempCounterString); dwCurSize += lstrlenW(szTempCounterString) + 1; // includes delimiter
} } } else { // no object name, so bad structure
pdhStatus = PDH_CSTATUS_NO_COUNTER; } }
assert (dwCurSize == (DWORD)lstrlenW(szTempPath)); }
if (pdhStatus == ERROR_SUCCESS) { // copy path to the caller's buffer if it will fit
assert (dwCurSize == (DWORD)lstrlenW(szTempPath)); if (dwCurSize < *pcchBufferSize) { if (szFullPathBuffer != NULL) { lstrcpyW (szFullPathBuffer, szTempPath); } } else { if (szFullPathBuffer != NULL) { // the buffer passed in is too small
pdhStatus = PDH_MORE_DATA; } } *pcchBufferSize = dwCurSize; }
//if (pWbemClass != NULL) pWbemClass->Release();
// CoUninitialize if necessary
if ( fCoInitialized ) { PdhiCoUninitialize(); } if (szTempPath != NULL) G_FREE(szTempPath);
return pdhStatus; }
PDH_FUNCTION PdhiEncodeWbemPathA ( PDH_COUNTER_PATH_ELEMENTS_A *pCounterPathElements, LPSTR szFullPathBuffer, LPDWORD pcchBufferSize, LANGID LangId, DWORD dwFlags ) { PDH_STATUS pdhStatus = ERROR_SUCCESS; LPWSTR wszNextString; LPWSTR wszReturnBuffer; PDH_COUNTER_PATH_ELEMENTS_W *pWideCounterPathElements; DWORD dwcchBufferSize; DWORD dwBuffSize; DWORD dwDest;
// get required buffer size...
dwBuffSize = sizeof (PDH_COUNTER_PATH_ELEMENTS_W);
if (pCounterPathElements->szMachineName != NULL) { dwBuffSize += (lstrlenA(pCounterPathElements->szMachineName) + 1) * sizeof(WCHAR); }
if (pCounterPathElements->szObjectName != NULL) { dwBuffSize += (lstrlenA(pCounterPathElements->szObjectName) + 1) * sizeof(WCHAR); }
if (pCounterPathElements->szInstanceName != NULL) { dwBuffSize += (lstrlenA(pCounterPathElements->szInstanceName) + 1) * sizeof(WCHAR); }
if (pCounterPathElements->szParentInstance != NULL) { dwBuffSize += (lstrlenA(pCounterPathElements->szParentInstance) + 1) * sizeof(WCHAR); }
if (pCounterPathElements->szCounterName != NULL) { dwBuffSize += (lstrlenA(pCounterPathElements->szCounterName) + 1) * sizeof(WCHAR); }
// add in room for the return buffer
dwcchBufferSize = * pcchBufferSize; dwBuffSize += dwcchBufferSize * sizeof(WCHAR);
pWideCounterPathElements = (PDH_COUNTER_PATH_ELEMENTS_W *)G_ALLOC(dwBuffSize);
if (pWideCounterPathElements != NULL) { // populate the fields
wszNextString = (LPWSTR)&pWideCounterPathElements[1];
if (pCounterPathElements->szMachineName != NULL) { dwDest = MultiByteToWideChar(_getmbcp(), 0, pCounterPathElements->szMachineName, lstrlenA(pCounterPathElements->szMachineName), wszNextString, (lstrlenA(pCounterPathElements->szMachineName) + 1)); if (dwDest > 0) { pWideCounterPathElements->szMachineName = wszNextString; wszNextString += dwDest + 1; } else { pWideCounterPathElements->szMachineName = NULL; } } else { pWideCounterPathElements->szMachineName = NULL; }
if (pCounterPathElements->szObjectName != NULL) { pWideCounterPathElements->szObjectName = wszNextString; dwDest = MultiByteToWideChar(_getmbcp(), 0, pCounterPathElements->szObjectName, lstrlenA(pCounterPathElements->szObjectName), wszNextString, (lstrlenA(pCounterPathElements->szObjectName) + 1)); if (dwDest > 0) { pWideCounterPathElements->szObjectName = wszNextString; wszNextString += dwDest + 1; } else { pWideCounterPathElements->szObjectName = NULL; } } else { pWideCounterPathElements->szObjectName = NULL; }
if (pCounterPathElements->szInstanceName != NULL) { dwDest = MultiByteToWideChar(_getmbcp(), 0, pCounterPathElements->szInstanceName, lstrlenA(pCounterPathElements->szInstanceName), wszNextString, (lstrlenA(pCounterPathElements->szInstanceName) + 1)); if (dwDest > 0) { pWideCounterPathElements->szInstanceName = wszNextString; wszNextString += dwDest + 1; } else { pWideCounterPathElements->szInstanceName = NULL; } } else { pWideCounterPathElements->szInstanceName = NULL; }
if (pCounterPathElements->szParentInstance != NULL) { dwDest = MultiByteToWideChar(_getmbcp(), 0, pCounterPathElements->szParentInstance, lstrlenA(pCounterPathElements->szParentInstance), wszNextString, (lstrlenA(pCounterPathElements->szParentInstance) + 1)); if (dwDest > 0) { pWideCounterPathElements->szParentInstance = wszNextString; wszNextString += dwDest + 1; } else { pWideCounterPathElements->szParentInstance = NULL; } } else { pWideCounterPathElements->szParentInstance = NULL; }
if (pCounterPathElements->szCounterName != NULL) { dwDest = MultiByteToWideChar(_getmbcp(), 0, pCounterPathElements->szCounterName, lstrlenA(pCounterPathElements->szCounterName), wszNextString, (lstrlenA(pCounterPathElements->szCounterName) + 1)); if (dwDest > 0) { pWideCounterPathElements->szCounterName = wszNextString; wszNextString += dwDest + 1; } else { pWideCounterPathElements->szCounterName = NULL; } } else { pWideCounterPathElements->szCounterName = NULL; }
pWideCounterPathElements->dwInstanceIndex = pCounterPathElements->dwInstanceIndex;
if (szFullPathBuffer != NULL) { wszReturnBuffer = wszNextString; } else { wszReturnBuffer = NULL; }
// call wide function
pdhStatus = PdhiEncodeWbemPathW ( pWideCounterPathElements, wszReturnBuffer, & dwcchBufferSize, LangId, dwFlags);
if ((pdhStatus == ERROR_SUCCESS) && (szFullPathBuffer != NULL)) { // convert the wide path back to ANSI
pdhStatus = PdhiConvertUnicodeToAnsi(_getmbcp(), wszReturnBuffer, szFullPathBuffer, pcchBufferSize); }
G_FREE (pWideCounterPathElements); } else { pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE; }
return pdhStatus;
}
PDH_FUNCTION PdhiDecodeWbemPathW ( IN LPCWSTR szFullPathBuffer, IN PDH_COUNTER_PATH_ELEMENTS_W *pCounterPathElements, IN LPDWORD pdwBufferSize, IN LANGID LangId, IN DWORD dwFlags ) { PPDHI_COUNTER_PATH pLocalCounterPath; PDH_STATUS pdhStatus = ERROR_SUCCESS; DWORD dwSize; LPWSTR szString = NULL; WCHAR wszTempBuffer[MAX_PATH]; LPWSTR szSrc = NULL;
PPDHI_WBEM_SERVER_DEF pThisServer = NULL; IWbemClassObject *pThisClass = NULL;
DBG_UNREFERENCED_PARAMETER (LangId);
// CoInitialize() if we need to
BOOL fCoInitialized = PdhiCoInitialize();
// allocate a temporary work buffer
pLocalCounterPath = (PPDHI_COUNTER_PATH) G_ALLOC( sizeof(PDHI_COUNTER_PATH) + sizeof(WCHAR) * 2 * ( lstrlenW(szStaticLocalMachineName) + lstrlenW(szFullPathBuffer) + 3));
if (pLocalCounterPath != NULL) { dwSize = (DWORD)G_SIZE (pLocalCounterPath); assert (dwSize != NULL);
if (pdhStatus == ERROR_SUCCESS) { // get WBEM server since we'll probably need it later
if (ParseFullPathNameW (szFullPathBuffer, &dwSize, pLocalCounterPath, (dwFlags & PDH_PATH_WBEM_INPUT ? TRUE : FALSE))) { // parsed successfully so load into user's buffer
if (*pdwBufferSize != 0) { if (pCounterPathElements != NULL) { // see if there's enough room
if (*pdwBufferSize >= dwSize) { // there's room so copy / translate the data
szString = (LPWSTR)&pCounterPathElements[1]; if (pLocalCounterPath->szMachineName != NULL) { pCounterPathElements->szMachineName = szString; lstrcpyW (szString, pLocalCounterPath->szMachineName); szString += lstrlenW (szString) + 1; szString = (LPWSTR)ALIGN_ON_DWORD (szString); } else { pCounterPathElements->szMachineName = NULL; } dwSize = (DWORD)((LPBYTE)szString - (LPBYTE)pCounterPathElements); }
// Now that we have the proper machine name,
// connect to the server if we need to
if (dwFlags != (PDH_PATH_WBEM_INPUT | PDH_PATH_WBEM_RESULT)) { pdhStatus = PdhiConnectWbemServer ( pCounterPathElements->szMachineName, &pThisServer); } else { // this will just be a copy operation
pdhStatus = ERROR_SUCCESS; }
if ( pdhStatus == ERROR_SUCCESS ) {
if (pLocalCounterPath->szObjectName != NULL) { pCounterPathElements->szObjectName = szString; if (dwFlags & PDH_PATH_WBEM_RESULT) { if (dwFlags & PDH_PATH_WBEM_INPUT) { // just copy
szSrc = pLocalCounterPath->szObjectName; } else { // interpret the display name to a class name
pdhStatus = PdhiWbemGetObjectClassName ( pThisServer, pLocalCounterPath->szObjectName, wszTempBuffer, sizeof(wszTempBuffer) / sizeof(wszTempBuffer[0]), &pThisClass); if (pdhStatus == ERROR_SUCCESS) { szSrc = wszTempBuffer; } } } else { if (dwFlags & PDH_PATH_WBEM_INPUT) { // translate class name to a display name
pdhStatus = PdhiWbemGetClassDisplayName ( pThisServer, pLocalCounterPath->szObjectName, wszTempBuffer, sizeof(wszTempBuffer) / sizeof(wszTempBuffer[0]), &pThisClass); if (pdhStatus == ERROR_SUCCESS) { szSrc = wszTempBuffer; } } else { assert (dwFlags != 0); // this should be caught earlier
} }
if (pdhStatus == ERROR_SUCCESS) { dwSize += (lstrlenW(szSrc) +1) * sizeof(WCHAR); if (*pdwBufferSize >= dwSize) { lstrcpyW (szString, szSrc); szString += lstrlenW (szString) + 1; szString = (LPWSTR)ALIGN_ON_DWORD (szString); dwSize = (DWORD)((LPBYTE)szString - (LPBYTE)pCounterPathElements); } else { // not enough room
pdhStatus = PDH_INSUFFICIENT_BUFFER; } } } else { pCounterPathElements->szObjectName = NULL; }
if (pdhStatus == ERROR_SUCCESS) { if (pLocalCounterPath->szInstanceName != NULL) { pCounterPathElements->szInstanceName = szString; szSrc = pLocalCounterPath->szInstanceName; dwSize += (lstrlenW(szSrc) +1) * sizeof(WCHAR); if (*pdwBufferSize >= dwSize) { lstrcpyW (szString, szSrc); szString += lstrlenW (szString) + 1; szString = (LPWSTR)ALIGN_ON_DWORD (szString); dwSize = (DWORD)((LPBYTE)szString - (LPBYTE)pCounterPathElements); } else { // not enough room
pdhStatus = PDH_INSUFFICIENT_BUFFER; }
if (pLocalCounterPath->szParentName != NULL) { pCounterPathElements->szParentInstance = szString; szSrc = pLocalCounterPath->szParentName; dwSize += (lstrlenW(szSrc) +1) * sizeof(WCHAR); if (*pdwBufferSize >= dwSize) { lstrcpyW (szString, szSrc); szString += lstrlenW (szString) + 1; szString = (LPWSTR)ALIGN_ON_DWORD (szString); dwSize = (DWORD)((LPBYTE)szString - (LPBYTE)pCounterPathElements); } else { // not enough room
pdhStatus = PDH_INSUFFICIENT_BUFFER; } } else { pCounterPathElements->szParentInstance = NULL; }
pCounterPathElements->dwInstanceIndex = pLocalCounterPath->dwIndex;
} else { pCounterPathElements->szInstanceName = NULL; pCounterPathElements->szParentInstance = NULL; pCounterPathElements->dwInstanceIndex = (DWORD)-1; } }
if (pdhStatus == ERROR_SUCCESS) { if (pLocalCounterPath->szCounterName != NULL) { pCounterPathElements->szCounterName = szString; if (dwFlags & PDH_PATH_WBEM_RESULT) { if (dwFlags & PDH_PATH_WBEM_INPUT) { // just copy
szSrc = pLocalCounterPath->szCounterName; } else { // interpret the display name to a property name
pdhStatus = PdhiWbemGetCounterPropertyName ( pThisClass, pLocalCounterPath->szCounterName, wszTempBuffer, sizeof(wszTempBuffer) / sizeof(wszTempBuffer[0])); if (pdhStatus == ERROR_SUCCESS) { szSrc = wszTempBuffer; } } } else { if (dwFlags & PDH_PATH_WBEM_INPUT) { // translate class name to a display name
pdhStatus = PdhiWbemGetCounterDisplayName ( pThisClass, pLocalCounterPath->szCounterName, wszTempBuffer, sizeof(wszTempBuffer) / sizeof(wszTempBuffer[0])); if (pdhStatus == ERROR_SUCCESS) { szSrc = wszTempBuffer; } } else { assert (dwFlags != 0); // this should be caught earlier
} } dwSize += (lstrlenW(szSrc) +1) * sizeof(WCHAR); if (*pdwBufferSize >= dwSize) { lstrcpyW (szString, szSrc); szString += lstrlenW (szString) + 1; szString = (LPWSTR)ALIGN_ON_DWORD (szString); dwSize = (DWORD)((LPBYTE)szString - (LPBYTE)pCounterPathElements); } else { // not enough room
pdhStatus = PDH_INSUFFICIENT_BUFFER; } } else { pCounterPathElements->szCounterName = NULL; } } } // If pdhStatus == ERROR_SUCCESS
if (pdhStatus == ERROR_SUCCESS) { dwSize = (DWORD)((LPBYTE)szString - (LPBYTE)pCounterPathElements);
*pdwBufferSize = dwSize; } } else { // a null buffer pointer was passed int
pdhStatus = PDH_INVALID_ARGUMENT; } } else { // this is just a size check so return size required
*pdwBufferSize = dwSize * 2; // doubled to insure room for path expansions
pdhStatus = ERROR_SUCCESS; } } else { // unable to read path
pdhStatus = PDH_INVALID_PATH; } // release class object if used
//if (pThisClass != NULL) pThisClass->Release();
// Cleanup pThisServer if used
if ( NULL != pThisServer ) { if (pdhStatus == ERROR_SUCCESS) { pdhStatus = PdhiDisconnectWbemServer (pThisServer); } else { // don't trash the return status
PdhiDisconnectWbemServer (pThisServer); } }
} G_FREE (pLocalCounterPath); } else { pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE; }
// CoUninitialize if necessary
if ( fCoInitialized ) { PdhiCoUninitialize(); }
return pdhStatus; }
PDH_FUNCTION PdhiDecodeWbemPathA ( IN LPCSTR szFullPathBuffer, IN PDH_COUNTER_PATH_ELEMENTS_A *pCounterPathElements, IN LPDWORD pdwBufferSize, IN LANGID LangId, IN DWORD dwFlags ) { PDH_STATUS pdhStatus = ERROR_SUCCESS; LPWSTR wszWidePath = NULL; PDH_COUNTER_PATH_ELEMENTS_W *pWideElements = NULL; DWORD dwSize; DWORD dwDest = 0; LONG lSizeRemaining; LPSTR szNextString;
wszWidePath = (LPWSTR)G_ALLOC((lstrlenA(szFullPathBuffer) + 1) * sizeof(WCHAR));
if (wszWidePath == NULL) { pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE; }
if (pdhStatus == ERROR_SUCCESS) { // compute size of temp element buffer
lSizeRemaining = * pdwBufferSize - sizeof(PDH_COUNTER_PATH_ELEMENTS_A); dwSize = * pdwBufferSize - sizeof(PDH_COUNTER_PATH_ELEMENTS_A); // dwSize now has the size of the buffer AFTER the structure so
// adjust this for the longer char length to make it a fair comparison
dwSize *= sizeof(WCHAR)/sizeof(CHAR); // and add back in the structure
dwSize += sizeof(PDH_COUNTER_PATH_ELEMENTS_W);
if (pCounterPathElements != NULL) { pWideElements = (PDH_COUNTER_PATH_ELEMENTS_W *) G_ALLOC(dwSize); if (pWideElements == NULL) { pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE; } } else { pWideElements = NULL; pdhStatus = ERROR_SUCCESS; } }
if (pdhStatus == ERROR_SUCCESS) { // convert path to Wide
MultiByteToWideChar(_getmbcp(), 0, szFullPathBuffer, lstrlenA(szFullPathBuffer), wszWidePath, lstrlenA(szFullPathBuffer) + 1); pdhStatus = PdhiDecodeWbemPathW ( wszWidePath, pWideElements, & dwSize, LangId, dwFlags);
if (pdhStatus == ERROR_SUCCESS) { if (pCounterPathElements != NULL) { // populate the fields of the caller's buffer
szNextString = (LPSTR)&pCounterPathElements[1];
if ( pWideElements->szMachineName != NULL && lSizeRemaining > 0) { dwDest = lSizeRemaining; pdhStatus = PdhiConvertUnicodeToAnsi(_getmbcp(), pWideElements->szMachineName, szNextString, & dwDest); if (pdhStatus == ERROR_SUCCESS) { pCounterPathElements->szMachineName = szNextString; szNextString += dwDest + 1; } else { pCounterPathElements->szMachineName = NULL; } lSizeRemaining -= dwDest + 1; } else { pCounterPathElements->szMachineName = NULL; }
if ( pWideElements->szObjectName != NULL && lSizeRemaining > 0) { dwDest = lSizeRemaining; pdhStatus = PdhiConvertUnicodeToAnsi(_getmbcp(), pWideElements->szObjectName, szNextString, & dwDest); if (pdhStatus == ERROR_SUCCESS) { pCounterPathElements->szObjectName = szNextString; szNextString += dwDest + 1; } else { pCounterPathElements->szObjectName = NULL; } lSizeRemaining -= dwDest + 1; } else { pCounterPathElements->szObjectName = NULL; }
if ( pWideElements->szInstanceName != NULL && lSizeRemaining > 0) { dwDest = lSizeRemaining; pdhStatus = PdhiConvertUnicodeToAnsi(_getmbcp(), pWideElements->szInstanceName, szNextString, & dwDest); if (pdhStatus == ERROR_SUCCESS) { pCounterPathElements->szInstanceName = szNextString; szNextString += dwDest + 1; } else { pCounterPathElements->szInstanceName = NULL; } lSizeRemaining -= dwDest + 1; } else { pCounterPathElements->szInstanceName = NULL; }
if ( pWideElements->szParentInstance != NULL && lSizeRemaining > 0) { dwDest = lSizeRemaining; pdhStatus = PdhiConvertUnicodeToAnsi(_getmbcp(), pWideElements->szParentInstance, szNextString, & dwDest); if (pdhStatus == ERROR_SUCCESS) { pCounterPathElements->szParentInstance = szNextString; szNextString += dwDest + 1; } else { pCounterPathElements->szParentInstance = NULL; } lSizeRemaining -= dwDest + 1; } else { pCounterPathElements->szParentInstance = NULL; }
if ( pWideElements->szCounterName != NULL && lSizeRemaining > 0) { dwDest = lSizeRemaining; pdhStatus = PdhiConvertUnicodeToAnsi(_getmbcp(), pWideElements->szObjectName, szNextString, & dwDest); if (pdhStatus == ERROR_SUCCESS) { pCounterPathElements->szCounterName = szNextString; szNextString += dwDest + 1; } else { pCounterPathElements->szCounterName = NULL; } lSizeRemaining -= dwDest + 1; } else { pCounterPathElements->szCounterName = NULL; }
pCounterPathElements->dwInstanceIndex = pWideElements->dwInstanceIndex;
*pdwBufferSize = (DWORD)((LPBYTE)szNextString - (LPBYTE)pCounterPathElements); } else { // just return the size required adjusted for wide/ansi characters
*pdwBufferSize = sizeof(PDH_COUNTER_PATH_ELEMENTS_A); dwSize -= sizeof(PDH_COUNTER_PATH_ELEMENTS_W); dwSize /= sizeof(WCHAR)/sizeof(CHAR); *pdwBufferSize += dwSize; } } else { // call to wide function failed so just return error
} } else { // memory allocation failed so return error
}
if (pWideElements != NULL) G_FREE(pWideElements); if (wszWidePath != NULL) G_FREE(wszWidePath);
return pdhStatus; }
BOOL WbemInitCounter ( IN PPDHI_COUNTER pCounter ) /*++
Routine Description:
Initialized the counter data structure by: Allocating the memory block to contain the counter structure and all the associated data fields. If this allocation is successful, then the fields are initialized by verifying the counter is valid.
Arguments:
IN PPDHI_COUNTER pCounter pointer of the counter to initialize using the system data
Return Value:
TRUE if the counter was successfully initialized FALSE if a problem was encountered
In either case, the CStatus field of the structure is updated to indicate the status of the operation.
--*/ { DWORD dwResult; PDH_STATUS pdhStatus = ERROR_SUCCESS; PPDHI_WBEM_SERVER_DEF pWbemServer = NULL; DWORD dwLastError = ERROR_SUCCESS; HRESULT hRes = S_OK; VARIANT vCountertype; WCHAR szBasePropertyName[MAX_PATH]; WCHAR szFreqPropertyName[MAX_PATH]; WCHAR szWbemItemPath[MAX_PATH]; ULONGLONG llValue; LONG lOffset;
PPDH_COUNTER_PATH_ELEMENTS_W pPathElem = NULL; BOOL bReturn = TRUE; DWORD dwBufferSize = 0; BSTR bsPropName = NULL; BSTR bsCountertype = NULL; IWbemQualifierSet *pQualSet = NULL; PPDHI_COUNTER pCounterInList = NULL; PPDHI_COUNTER_PATH pPdhiCtrPath = NULL; BOOL bMatchFound; DWORD bDisconnectServer = FALSE;
// CoInitialize() if we need to
BOOL fCoInitialized = PdhiCoInitialize();
VariantInit (&vCountertype);
pCounter->dwFlags |= PDHIC_WBEM_COUNTER; // make sure WBEM flag is set
// make sure the query has a refresher started already
if (pCounter->pOwner->pRefresher == NULL) { // it hasn't been started so start now
dwResult = CoCreateRefresher( &pCounter->pOwner->pRefresher ); if ((dwResult != S_OK) || (pCounter->pOwner->pRefresher == NULL)) { pCounter->pOwner->pRefresher = NULL; dwLastError = PDH_WBEM_ERROR; bReturn = FALSE; } else { // open config interface
dwResult = pCounter->pOwner->pRefresher->QueryInterface ( IID_IWbemConfigureRefresher, (LPVOID *)&pCounter->pOwner->pRefresherCfg); if (dwResult != S_OK) { pCounter->pOwner->pRefresherCfg = NULL; pCounter->pOwner->pRefresher->Release(); pCounter->pOwner->pRefresher = NULL; dwLastError = PDH_WBEM_ERROR; bReturn = FALSE; } } }
if (bReturn) { // so far so good, now figure out the WBEM path to add it to the
// refresher
dwBufferSize = lstrlenW(pCounter->szFullName) * sizeof(WCHAR) * 10; dwBufferSize += sizeof (PDH_COUNTER_PATH_ELEMENTS_W);
pPathElem = (PPDH_COUNTER_PATH_ELEMENTS_W) G_ALLOC (dwBufferSize); // the path is display names, so convert to WBEM class names first
if (pPathElem == NULL) { dwLastError = PDH_MEMORY_ALLOCATION_FAILURE; bReturn = FALSE; } else { pdhStatus = PdhiDecodeWbemPathW ( pCounter->szFullName, pPathElem, &dwBufferSize, pCounter->pOwner->LangID, PDH_PATH_WBEM_RESULT); if (pdhStatus == ERROR_SUCCESS) { // continue
} else { dwLastError = PDH_INVALID_PATH; bReturn = FALSE; } } }
if (bReturn) { dwBufferSize *= 8; // just to be safe
pPdhiCtrPath = (PPDHI_COUNTER_PATH) G_ALLOC (dwBufferSize); if (pPdhiCtrPath == NULL) { dwLastError = PDH_MEMORY_ALLOCATION_FAILURE; bReturn = FALSE; } else { // break path into display elements
bReturn = ParseFullPathNameW ( pCounter->szFullName, &dwBufferSize, pPdhiCtrPath, FALSE); if (bReturn) { // realloc to use only the memory needed
pCounter->pCounterPath = (PPDHI_COUNTER_PATH) G_REALLOC (pPdhiCtrPath, dwBufferSize); if ((pPdhiCtrPath != pCounter->pCounterPath) && (pCounter->pCounterPath != NULL)){ // the memory block moved so
// correct addresses inside structure
lOffset = (LONG)((ULONG_PTR)pCounter->pCounterPath - (ULONG_PTR)pPdhiCtrPath); if (pCounter->pCounterPath->szMachineName) { pCounter->pCounterPath->szMachineName = (LPWSTR)( (LPBYTE)pCounter->pCounterPath->szMachineName + lOffset); } if (pCounter->pCounterPath->szObjectName) { pCounter->pCounterPath->szObjectName = (LPWSTR)( (LPBYTE)pCounter->pCounterPath->szObjectName + lOffset); } if (pCounter->pCounterPath->szInstanceName) { pCounter->pCounterPath->szInstanceName = (LPWSTR)( (LPBYTE)pCounter->pCounterPath->szInstanceName + lOffset); } if (pCounter->pCounterPath->szParentName) { pCounter->pCounterPath->szParentName = (LPWSTR)( (LPBYTE)pCounter->pCounterPath->szParentName + lOffset); } if (pCounter->pCounterPath->szCounterName) { pCounter->pCounterPath->szCounterName = (LPWSTR)( (LPBYTE)pCounter->pCounterPath->szCounterName + lOffset); } } } else { // free the buffer
G_FREE (pPdhiCtrPath); dwLastError = PDH_WBEM_ERROR; } } }
// connect to the WBEM Server on that machine
if (bReturn) { pdhStatus = PdhiConnectWbemServer ( pCounter->pCounterPath->szMachineName, &pWbemServer); if (pdhStatus != ERROR_SUCCESS) { dwLastError = pdhStatus; bReturn = FALSE; } else { bDisconnectServer = TRUE; } }
if (bReturn) { // make WBEM Instance path out of path elements
pdhStatus = PdhiMakeWbemInstancePath ( pPathElem, szWbemItemPath, TRUE);
// check for an object/class of this type that has already been added
// walk down counter list to find a matching:
// machine\namespace
// object
// instance name
if (pdhStatus != ERROR_SUCCESS) { dwLastError = pdhStatus; bReturn = FALSE; } }
if (bReturn) { assert (pCounter->pWbemObject == NULL); assert (pCounter->lWbemRefreshId == 0);
pCounterInList = pCounter->pOwner->pCounterListHead; if (pCounterInList == NULL) { // then there are no entries to search so continue
} else { do { // check for matching machine name
bMatchFound = FALSE; if (lstrcmpiW(pCounterInList->pCounterPath->szMachineName, pCounter->pCounterPath->szMachineName) == 0) { // then the machine name matches
if (lstrcmpiW (pCounterInList->pCounterPath->szObjectName, pCounter->pCounterPath->szObjectName) == 0) { // then the object name matches
// see if the instance matches
if (lstrcmpiW (pCounterInList->pCounterPath->szInstanceName, pCounter->pCounterPath->szInstanceName) == 0) { if (pCounter->pCounterPath->szParentName != 0) { if (lstrcmpiW (pCounterInList->pCounterPath->szParentName, pCounter->pCounterPath->szParentName) == 0) { // then this is a match
bMatchFound = TRUE; } else { // not a match
} } else { // this is a match
bMatchFound = TRUE; }
if (bMatchFound) { if ((pCounter->pCounterPath->szInstanceName != NULL) && (*pCounter->pCounterPath->szInstanceName == SPLAT_L)) { // then this is a Wild Card or multiple instance path
// see if an enumerator for this object has already been created
// if so, then AddRef it
if (pCounterInList->pWbemEnum != NULL) { pCounter->pWbemObject = pCounterInList->pWbemObject; pCounter->pWbemEnum = pCounterInList->pWbemEnum; // bump the ref counts on this object so it
// doesn't disapper from us
pCounter->pWbemObject->AddRef(); pCounter->pWbemEnum->AddRef(); pCounter->lWbemEnumId = pCounterInList->lWbemEnumId; pCounter->dwFlags |= PDHIC_MULTI_INSTANCE; } // and exit loop
hRes = S_OK; break; } else { // then it's a regular instance the instance name matches
// so get the Object pointer
pCounter->pWbemObject = pCounterInList->pWbemObject; pCounter->pWbemAccess = pCounterInList->pWbemAccess; // bump the ref counts on this object so it
// doesn't disapper from us
pCounter->pWbemObject->AddRef(); pCounter->pWbemAccess->AddRef(); pCounter->lWbemRefreshId = pCounterInList->lWbemRefreshId; // and exit loop
hRes = S_OK; break; } } else { // no match so go to next one
} } else { // no match so go to next one
} } else { // no match so go to next one
} } else { // no match so go to next counter
} pCounterInList = pCounterInList->next.flink; } while (pCounterInList != pCounter->pOwner->pCounterListHead); }
bDontRefresh = TRUE;
// determine if we should and an object or an enumerator
if ((pCounter->pCounterPath->szInstanceName != NULL) && (*pCounter->pCounterPath->szInstanceName == SPLAT_L)) { // then this is an enum type so see if there's already one assigned
// if not, then create one
if (pCounter->pWbemEnum == NULL) { if (pCounter->pOwner->pRefresherCfg != NULL) { hRes = pCounter->pOwner->pRefresherCfg->AddEnum( pWbemServer->pSvc, pPathElem->szObjectName, WBEM_FLAG_USE_AMENDED_QUALIFIERS, 0, &pCounter->pWbemEnum, &pCounter->lWbemEnumId); } else { hRes = WBEM_E_INITIALIZATION_FAILURE; }
if (hRes != S_OK) { bReturn = FALSE; dwLastError = PDH_WBEM_ERROR; } else { pdhStatus = PdhiWbemGetClassObjectByName ( pWbemServer, pPathElem->szObjectName, &pCounter->pWbemObject); } // set multi instance flag
pCounter->dwFlags |= PDHIC_MULTI_INSTANCE; } else { // we must have copied another one so continue
}
} else { // this is a single counter
if (pCounter->pWbemObject == NULL) { // and it hasn't been added yet, so just add one object
if (pCounter->pOwner->pRefresherCfg != NULL) { hRes = pCounter->pOwner->pRefresherCfg->AddObjectByPath ( pWbemServer->pSvc, szWbemItemPath, WBEM_FLAG_USE_AMENDED_QUALIFIERS, 0, &pCounter->pWbemObject, &pCounter->lWbemRefreshId); } else { hRes = WBEM_E_INITIALIZATION_FAILURE; }
if (hRes != S_OK) { bReturn = FALSE; dwLastError = PDH_WBEM_ERROR; } } else { // it must have been copied from another
} }
if (hRes == S_OK) { // get handles for subsequent data collection from this object
hRes = pCounter->pWbemObject->QueryInterface (IID_IWbemObjectAccess, (LPVOID *)&pCounter->pWbemAccess); if (hRes == S_OK) { if (!PdhiIsSingletonClass (pCounter->pWbemObject)) { CIMTYPE cimType = 0; bsPropName = SysAllocString(cszName); if (bsPropName) { // get handle to the name property for this counter
hRes = pCounter->pWbemAccess->GetPropertyHandle ( bsPropName, &cimType, &pCounter->lNameHandle); if (hRes != S_OK) { dwLastError = PDH_WBEM_ERROR; } assert (cimType == CIM_STRING); } else { dwLastError = PDH_MEMORY_ALLOCATION_FAILURE; hRes = WBEM_E_OUT_OF_MEMORY; } } else { pCounter->lNameHandle = -1; } if (hRes == S_OK) { // get handle to the data property for this counter
hRes = pCounter->pWbemAccess->GetPropertyHandle ( pPathElem->szCounterName, &pCounter->lNumItemType, &pCounter->lNumItemHandle); assert (hRes == S_OK);
// get counter type field
// first get the property qualifiers
PdhiSysFreeString (&bsPropName); bsPropName = SysAllocString (pPathElem->szCounterName); if (bsPropName) { hRes = pCounter->pWbemObject->GetPropertyQualifierSet ( bsPropName, &pQualSet); } else { hRes = WBEM_E_OUT_OF_MEMORY; }
if (hRes == WBEM_NO_ERROR) { // now get the specific value
VariantClear (&vCountertype); bsCountertype = SysAllocString (cszCountertype); if (bsCountertype) { hRes = pQualSet->Get (bsCountertype, 0, &vCountertype, NULL); if (hRes == WBEM_NO_ERROR) { pCounter->plCounterInfo.dwCounterType = (DWORD)V_I4(&vCountertype); } else { pCounter->plCounterInfo.dwCounterType = 0; } PdhiSysFreeString (&bsCountertype); } else { hRes = WBEM_E_OUT_OF_MEMORY; }
if (hRes == WBEM_NO_ERROR) { // if this is a fraction counter that has a "base" value
// then look it up by appending the "base" string to the
// property name
if ((pCounter->plCounterInfo.dwCounterType == PERF_SAMPLE_FRACTION) || (pCounter->plCounterInfo.dwCounterType == PERF_AVERAGE_TIMER) || (pCounter->plCounterInfo.dwCounterType == PERF_AVERAGE_BULK) || (pCounter->plCounterInfo.dwCounterType == PERF_LARGE_RAW_FRACTION) || (pCounter->plCounterInfo.dwCounterType == PERF_RAW_FRACTION)) {
// make sure we have room for the "_Base" string
assert (lstrlenW(pPathElem->szCounterName) < (MAX_PATH - 6)); lstrcpyW (szBasePropertyName, pPathElem->szCounterName); lstrcatW (szBasePropertyName, cszBaseSuffix);
// get the handle to the denominator
hRes = pCounter->pWbemAccess->GetPropertyHandle ( szBasePropertyName, &pCounter->lDenItemType, &pCounter->lDenItemHandle); assert (hRes == S_OK);
} else { // the denominator is a time field
if ((pCounter->plCounterInfo.dwCounterType & PERF_TIMER_FIELD) == PERF_TIMER_TICK) { // use the system perf time timestamp as the denominator
lstrcpyW (szBasePropertyName, cszTimestampPerfTime); lstrcpyW (szFreqPropertyName, cszFrequencyPerfTime); } else if ((pCounter->plCounterInfo.dwCounterType & PERF_TIMER_FIELD) == PERF_TIMER_100NS) { lstrcpyW (szBasePropertyName, cszTimestampSys100Ns); lstrcpyW (szFreqPropertyName, cszFrequencySys100Ns); } else if ((pCounter->plCounterInfo.dwCounterType & PERF_TIMER_FIELD) == PERF_OBJECT_TIMER) { lstrcpyW (szBasePropertyName, cszTimestampObject); lstrcpyW (szFreqPropertyName, cszFrequencyObject); } else { assert (FALSE); // this should never happen
}
// get the handle to the denominator
hRes = pCounter->pWbemAccess->GetPropertyHandle ( szBasePropertyName, &pCounter->lDenItemType, &pCounter->lDenItemHandle); assert (hRes == S_OK);
// get the handle to the frequency
hRes = pCounter->pWbemAccess->GetPropertyHandle ( szFreqPropertyName, &pCounter->lFreqItemType, &pCounter->lFreqItemHandle); assert (hRes == S_OK); }
// get the default scale value of this counter
VariantClear (&vCountertype); PdhiSysFreeString (&bsCountertype); bsCountertype = SysAllocString (cszDefaultscale); if (bsCountertype) { hRes = pQualSet->Get (bsCountertype, 0, &vCountertype, NULL); if (hRes == WBEM_NO_ERROR) { pCounter->lScale = 0; pCounter->plCounterInfo.lDefaultScale = (DWORD)V_I4(&vCountertype); } else { pCounter->plCounterInfo.lDefaultScale = 0; pCounter->lScale = 0; }
// this may not be initialized but we try anyway
if ((pCounter->lFreqItemType == VT_I8) || (pCounter->lFreqItemType == VT_UI8)) { pCounter->pWbemAccess->ReadQWORD ( pCounter->lFreqItemHandle, &llValue); } else { llValue = 0; } // the timebase is a 64 bit integer
pCounter->TimeBase = llValue; } else { hRes = WBEM_E_OUT_OF_MEMORY; } } PdhiSysFreeString (&bsCountertype); pQualSet->Release(); } else { if (hRes == WBEM_E_OUT_OF_MEMORY) { dwLastError = PDH_MEMORY_ALLOCATION_FAILURE; } else { dwLastError = PDH_WBEM_ERROR; } bReturn = FALSE; } } // else an error has ocurred
PdhiSysFreeString (&bsPropName); } else { dwLastError = PDH_WBEM_ERROR; bReturn = FALSE; } } else { dwLastError = PDH_WBEM_ERROR; bReturn = FALSE; }
if (bReturn) { // clear the not init'd flag to say it's ok to use now
pCounter->dwFlags &= ~PDHIC_COUNTER_NOT_INIT; }
bDontRefresh = FALSE; }
if (bReturn) { if (!AssignCalcFunction ( pCounter->plCounterInfo.dwCounterType, &pCounter->CalcFunc, &pCounter->StatFunc)) { dwLastError = PDH_FUNCTION_NOT_FOUND; bReturn = FALSE; } }
if (pPathElem != NULL) G_FREE(pPathElem); VariantClear (&vCountertype);
if (bDisconnectServer) { if (pdhStatus == ERROR_SUCCESS) { pdhStatus = PdhiDisconnectWbemServer (pWbemServer); } else { // keep error code from function body
PdhiDisconnectWbemServer (pWbemServer); } }
if (!bReturn) SetLastError (dwLastError);
// CoUninitialize if necessary
if ( fCoInitialized ) { PdhiCoUninitialize(); }
return bReturn; }
BOOL UpdateWbemCounterValue ( IN PPDHI_COUNTER pCounter, IN FILETIME *pTimeStamp ) { DWORD LocalCStatus = 0; DWORD LocalCType = 0; ULONGLONG llValue; DWORD dwValue;
BOOL bReturn = FALSE;
// move current value to last value buffer
pCounter->LastValue = pCounter->ThisValue;
// and clear the old value
pCounter->ThisValue.MultiCount = 1; pCounter->ThisValue.FirstValue = pCounter->ThisValue.SecondValue = 0; pCounter->ThisValue.TimeStamp = *pTimeStamp;
// get the counter's machine status first. There's no point in
// contuning if the machine is offline
// UpdateWbemCounterValue() will be called only if WBEM refresher succeeds
// in GetQueryWbemData(); that is, all remote machines should be on-line
LocalCStatus = ERROR_SUCCESS;
if (IsSuccessSeverity(LocalCStatus)) { // get the pointer to the counter data
LocalCType = pCounter->plCounterInfo.dwCounterType; switch (LocalCType) { //
// these counter types are loaded as:
// Numerator = Counter data from perf data block
// Denominator = Perf Time from perf data block
// (the time base is the PerfFreq)
//
case PERF_COUNTER_COUNTER: case PERF_COUNTER_QUEUELEN_TYPE: case PERF_SAMPLE_COUNTER: // this should be a DWORD counter
assert ((pCounter->lNumItemType == VT_I4) || (pCounter->lNumItemType == VT_UI4)); pCounter->pWbemAccess->ReadDWORD ( pCounter->lNumItemHandle, &dwValue); pCounter->ThisValue.FirstValue = (LONGLONG)(dwValue);
assert ((pCounter->lDenItemType == VT_I8) || (pCounter->lDenItemType == VT_UI8)); pCounter->pWbemAccess->ReadQWORD ( pCounter->lDenItemHandle, &llValue); // the denominator should be a 64-bit timestamp
pCounter->ThisValue.SecondValue = llValue;
// look up the timebase freq if necessary
if (pCounter->TimeBase == 0) { assert ((pCounter->lFreqItemType == VT_I8) || (pCounter->lFreqItemType == VT_UI8)); pCounter->pWbemAccess->ReadQWORD ( pCounter->lFreqItemHandle, &llValue); // the timebase is a 64 bit integer
pCounter->TimeBase = llValue; }
break;
case PERF_ELAPSED_TIME: case PERF_100NSEC_TIMER: case PERF_100NSEC_TIMER_INV: case PERF_COUNTER_TIMER: case PERF_COUNTER_TIMER_INV: case PERF_COUNTER_BULK_COUNT: case PERF_COUNTER_MULTI_TIMER: case PERF_COUNTER_MULTI_TIMER_INV: case PERF_COUNTER_LARGE_QUEUELEN_TYPE: case PERF_OBJ_TIME_TIMER: case PERF_COUNTER_100NS_QUEUELEN_TYPE: case PERF_COUNTER_OBJ_TIME_QUEUELEN_TYPE: case PERF_PRECISION_SYSTEM_TIMER: case PERF_PRECISION_100NS_TIMER: case PERF_PRECISION_OBJECT_TIMER: // this should be a QWORD counter
assert ((pCounter->lNumItemType == VT_I8) || (pCounter->lNumItemType == VT_UI8)); pCounter->pWbemAccess->ReadQWORD ( pCounter->lNumItemHandle, &llValue); pCounter->ThisValue.FirstValue = (LONGLONG)(llValue);
assert ((pCounter->lDenItemType == VT_I8) || (pCounter->lDenItemType == VT_UI8)); pCounter->pWbemAccess->ReadQWORD ( pCounter->lDenItemHandle, &llValue); // the denominator should be a 64-bit timestamp
pCounter->ThisValue.SecondValue = llValue;
// look up the timebase freq if necessary
if (pCounter->TimeBase == 0) { assert ((pCounter->lFreqItemType == VT_I8) || (pCounter->lFreqItemType == VT_UI8)); pCounter->pWbemAccess->ReadQWORD ( pCounter->lFreqItemHandle, &llValue); // the timebase is a 64 bit integer
pCounter->TimeBase = llValue; }
break; //
// These counters do not use any time reference
//
case PERF_COUNTER_RAWCOUNT: case PERF_COUNTER_RAWCOUNT_HEX: case PERF_COUNTER_DELTA: // this should be a DWORD counter
assert ((pCounter->lNumItemType == VT_I4) || (pCounter->lNumItemType == VT_UI4)); pCounter->pWbemAccess->ReadDWORD ( pCounter->lNumItemHandle, &dwValue); pCounter->ThisValue.FirstValue = (LONGLONG)(dwValue); pCounter->ThisValue.SecondValue = 0; break;
case PERF_COUNTER_LARGE_RAWCOUNT: case PERF_COUNTER_LARGE_RAWCOUNT_HEX: case PERF_COUNTER_LARGE_DELTA: // this should be a DWORD counter
assert ((pCounter->lNumItemType == VT_I8) || (pCounter->lNumItemType == VT_UI8)); pCounter->pWbemAccess->ReadQWORD ( pCounter->lNumItemHandle, &llValue); pCounter->ThisValue.FirstValue = (LONGLONG)(llValue); pCounter->ThisValue.SecondValue = 0; break;
//
// These counters use two data points, the one pointed to by
// pData and the one immediately after
//
case PERF_SAMPLE_FRACTION: case PERF_RAW_FRACTION: // this should be a DWORD counter
assert ((pCounter->lNumItemType == VT_I4) || (pCounter->lNumItemType == VT_UI4)); pCounter->pWbemAccess->ReadDWORD ( pCounter->lNumItemHandle, &dwValue); pCounter->ThisValue.FirstValue = (LONGLONG)dwValue;
assert ((pCounter->lDenItemType == VT_I4) || (pCounter->lDenItemType == VT_UI4)); pCounter->pWbemAccess->ReadDWORD ( pCounter->lDenItemHandle, &dwValue); // the denominator should be a 32-bit value
pCounter->ThisValue.SecondValue = (LONGLONG)dwValue; break;
case PERF_LARGE_RAW_FRACTION: // this should be a DWORD counter
assert ((pCounter->lNumItemType == VT_I8) || (pCounter->lNumItemType == VT_UI8)); pCounter->pWbemAccess->ReadQWORD ( pCounter->lNumItemHandle, & llValue); pCounter->ThisValue.FirstValue = (LONGLONG) llValue;
assert ((pCounter->lDenItemType == VT_I8) || (pCounter->lDenItemType == VT_UI8)); pCounter->pWbemAccess->ReadQWORD ( pCounter->lDenItemHandle, & llValue); // the denominator should be a 32-bit value
pCounter->ThisValue.SecondValue = (LONGLONG) llValue; break;
case PERF_AVERAGE_TIMER: case PERF_AVERAGE_BULK: // counter (numerator) is a LONGLONG, while the
// denominator is just a DWORD
// this should be a DWORD counter
assert ((pCounter->lNumItemType == VT_I8) || (pCounter->lNumItemType == VT_UI8)); pCounter->pWbemAccess->ReadQWORD ( pCounter->lNumItemHandle, &llValue); pCounter->ThisValue.FirstValue = (LONGLONG)llValue;
assert ((pCounter->lDenItemType == VT_I4) || (pCounter->lDenItemType == VT_UI4)); pCounter->pWbemAccess->ReadDWORD ( pCounter->lDenItemHandle, &dwValue); // the denominator should be a 32-bit value
pCounter->ThisValue.SecondValue = (LONGLONG)dwValue;
// look up the timebase freq if necessary
if (pCounter->TimeBase == 0) { assert ((pCounter->lFreqItemType == VT_I8) || (pCounter->lFreqItemType == VT_UI8)); pCounter->pWbemAccess->ReadQWORD ( pCounter->lFreqItemHandle, &llValue); // the timebase is a 64 bit integer
pCounter->TimeBase = llValue; } break; //
// These counters are used as the part of another counter
// and as such should not be used, but in case they are
// they'll be handled here.
//
case PERF_SAMPLE_BASE: case PERF_AVERAGE_BASE: case PERF_COUNTER_MULTI_BASE: case PERF_RAW_BASE: case PERF_LARGE_RAW_BASE: pCounter->ThisValue.FirstValue = 0; pCounter->ThisValue.SecondValue = 0; break;
//
// These counters are not supported by this function (yet)
//
case PERF_COUNTER_TEXT: case PERF_COUNTER_NODATA: case PERF_COUNTER_HISTOGRAM_TYPE: pCounter->ThisValue.FirstValue = 0; pCounter->ThisValue.SecondValue = 0; break;
case PERF_100NSEC_MULTI_TIMER: case PERF_100NSEC_MULTI_TIMER_INV: default: // an unidentified or unsupported
// counter was returned so
pCounter->ThisValue.FirstValue = 0; pCounter->ThisValue.SecondValue = 0; bReturn = FALSE; break; } } else { // else this counter is not valid so this value == 0
pCounter->ThisValue.CStatus = LocalCStatus; pCounter->ThisValue.FirstValue = 0; pCounter->ThisValue.SecondValue = 0; bReturn = FALSE; }
return bReturn; }
BOOL UpdateWbemMultiInstanceCounterValue ( IN PPDHI_COUNTER pCounter, IN FILETIME *pTimestamp ) { IWbemObjectAccess *pWbemAccess; HRESULT hRes;
DWORD LocalCStatus = 0; DWORD LocalCType = 0; DWORD dwValue; ULONGLONG llValue; DWORD dwSize; DWORD dwFinalSize; LONG lAvailableSize; LONG lReturnSize; LONG lThisInstanceIndex; LONG lNumInstances;
LPWSTR szNextNameString; PPDHI_RAW_COUNTER_ITEM pThisItem;
BOOL bReturn = FALSE;
if (pCounter->pThisRawItemList != NULL) { // free old counter buffer list
G_FREE(pCounter->pLastRawItemList); pCounter->pLastRawItemList = pCounter->pThisRawItemList; pCounter->pThisRawItemList = NULL; }
// get the counter's machine status first. There's no point in
// contuning if the machine is offline
// UpdateWbemCounterValue() will be called only if WBEM refresher succeeds
// in GetQueryWbemData(); that is, all remote machines should be on-line
LocalCStatus = ERROR_SUCCESS;
if (IsSuccessSeverity(LocalCStatus)) { IWbemObjectAccess **pWbemInstances = NULL; // get count of instances in enumerator
assert (pCounter->pWbemEnum != NULL); hRes = pCounter->pWbemEnum->GetObjects(0, 0, NULL, (LPDWORD)&lNumInstances); if (hRes == WBEM_E_BUFFER_TOO_SMALL) { // then we should know how many have been returned so allocate an
// array of pointers
pWbemInstances = new IWbemObjectAccess * [lNumInstances]; assert (pWbemInstances != NULL); if (pWbemInstances == NULL) { SetLastError(ERROR_OUTOFMEMORY); hRes = ERROR_OUTOFMEMORY; bReturn = FALSE; } else { hRes = pCounter->pWbemEnum->GetObjects(0, lNumInstances, pWbemInstances, (LPDWORD)&lNumInstances); }
if (hRes == S_OK && lNumInstances > 0) { // then we have a table of instances
// estimate the size required for the new data block
dwSize = sizeof (PDHI_RAW_COUNTER_ITEM_BLOCK) - sizeof (PDHI_RAW_COUNTER_ITEM); dwSize += lNumInstances * (sizeof(PDH_RAW_COUNTER_ITEM_W) + (MAX_PATH * 2 * sizeof(WCHAR)));
pCounter->pThisRawItemList = (PPDHI_RAW_COUNTER_ITEM_BLOCK)G_ALLOC (dwSize);
if (pCounter->pThisRawItemList != NULL) { dwFinalSize = lNumInstances * sizeof(PDH_RAW_COUNTER_ITEM_W); szNextNameString = (LPWSTR)((PBYTE)pCounter->pThisRawItemList + dwFinalSize);
for (lThisInstanceIndex = 0; lThisInstanceIndex < lNumInstances; lThisInstanceIndex++) { // get pointer to this raw data block in the array
pThisItem = &pCounter->pThisRawItemList->pItemArray[lThisInstanceIndex]; // get pointer to this IWbemObjectAccess pointer
pWbemAccess = pWbemInstances[lThisInstanceIndex]; // compute the remaining size of the buffer
lAvailableSize = (long)(dwSize - dwFinalSize);
assert (lAvailableSize > 0);
if (pCounter->lNameHandle != -1) { hRes = pWbemAccess->ReadPropertyValue( pCounter->lNameHandle, lAvailableSize, &lReturnSize, (LPBYTE)szNextNameString); assert(hRes == S_OK); } else { szNextNameString[0] = ATSIGN_L; szNextNameString[1] = 0; lReturnSize = 2; } pThisItem->szName = (DWORD) ( ((LPBYTE) szNextNameString) - ((LPBYTE) pCounter->pThisRawItemList)); szNextNameString = (LPWSTR)((LPBYTE)szNextNameString + lReturnSize); dwFinalSize += lReturnSize; dwFinalSize = DWORD_MULTIPLE(dwFinalSize);
LocalCType = pCounter->plCounterInfo.dwCounterType; switch (LocalCType) { //
// these counter types are loaded as:
// Numerator = Counter data from perf data block
// Denominator = Perf Time from perf data block
// (the time base is the PerfFreq)
//
case PERF_COUNTER_COUNTER: case PERF_COUNTER_QUEUELEN_TYPE: case PERF_SAMPLE_COUNTER: // this should be a DWORD counter
assert ((pCounter->lNumItemType == VT_I4) || (pCounter->lNumItemType == VT_UI4)); pWbemAccess->ReadDWORD ( pCounter->lNumItemHandle, &dwValue); pThisItem->FirstValue = (LONGLONG)(dwValue);
assert ((pCounter->lDenItemType == VT_I8) || (pCounter->lDenItemType == VT_UI8)); pWbemAccess->ReadQWORD ( pCounter->lDenItemHandle, &llValue); // the denominator should be a 64-bit timestamp
pThisItem->SecondValue = llValue;
// look up the timebase freq if necessary
if (pCounter->TimeBase == 0) { assert ((pCounter->lFreqItemType == VT_I8) || (pCounter->lFreqItemType == VT_UI8)); pWbemAccess->ReadQWORD ( pCounter->lFreqItemHandle, &llValue); // the timebase is a 64 bit integer
pCounter->TimeBase = llValue; } break;
case PERF_ELAPSED_TIME: case PERF_100NSEC_TIMER: case PERF_100NSEC_TIMER_INV: case PERF_COUNTER_TIMER: case PERF_COUNTER_TIMER_INV: case PERF_COUNTER_BULK_COUNT: case PERF_COUNTER_MULTI_TIMER: case PERF_COUNTER_MULTI_TIMER_INV: case PERF_COUNTER_LARGE_QUEUELEN_TYPE: case PERF_OBJ_TIME_TIMER: case PERF_COUNTER_100NS_QUEUELEN_TYPE: case PERF_COUNTER_OBJ_TIME_QUEUELEN_TYPE: case PERF_PRECISION_SYSTEM_TIMER: case PERF_PRECISION_100NS_TIMER: case PERF_PRECISION_OBJECT_TIMER: // this should be a QWORD counter
assert ((pCounter->lNumItemType == VT_I8) || (pCounter->lNumItemType == VT_UI8)); pWbemAccess->ReadQWORD ( pCounter->lNumItemHandle, &llValue); pThisItem->FirstValue = (LONGLONG)(llValue);
assert ((pCounter->lDenItemType == VT_I8) || (pCounter->lDenItemType == VT_UI8)); pWbemAccess->ReadQWORD ( pCounter->lDenItemHandle, &llValue); // the denominator should be a 64-bit timestamp
pThisItem->SecondValue = llValue;
// look up the timebase freq if necessary
if (pCounter->TimeBase == 0) { assert ((pCounter->lFreqItemType == VT_I8) || (pCounter->lFreqItemType == VT_UI8)); pWbemAccess->ReadQWORD ( pCounter->lFreqItemHandle, &llValue); // the timebase is a 64 bit integer
pCounter->TimeBase = llValue; } break; //
// These counters do not use any time reference
//
case PERF_COUNTER_RAWCOUNT: case PERF_COUNTER_RAWCOUNT_HEX: case PERF_COUNTER_DELTA: // this should be a DWORD counter
assert ((pCounter->lNumItemType == VT_I4) || (pCounter->lNumItemType == VT_UI4)); pWbemAccess->ReadDWORD ( pCounter->lNumItemHandle, &dwValue); pThisItem->FirstValue = (LONGLONG)(dwValue); pThisItem->SecondValue = 0; break;
case PERF_COUNTER_LARGE_RAWCOUNT: case PERF_COUNTER_LARGE_RAWCOUNT_HEX: case PERF_COUNTER_LARGE_DELTA: // this should be a DWORD counter
assert ((pCounter->lNumItemType == VT_I8) || (pCounter->lNumItemType == VT_UI8)); pWbemAccess->ReadQWORD ( pCounter->lNumItemHandle, &llValue); pThisItem->FirstValue = (LONGLONG)(llValue); pThisItem->SecondValue = 0; break;
//
// These counters use two data points, the one pointed to by
// pData and the one immediately after
//
case PERF_SAMPLE_FRACTION: case PERF_RAW_FRACTION: // this should be a DWORD counter
assert ((pCounter->lNumItemType == VT_I4) || (pCounter->lNumItemType == VT_UI4)); pWbemAccess->ReadDWORD ( pCounter->lNumItemHandle, &dwValue); pThisItem->FirstValue = (LONGLONG)dwValue;
assert ((pCounter->lDenItemType == VT_I4) || (pCounter->lDenItemType == VT_UI4)); pWbemAccess->ReadDWORD ( pCounter->lDenItemHandle, &dwValue); // the denominator should be a 32-bit value
pThisItem->SecondValue = (LONGLONG)dwValue; break;
case PERF_LARGE_RAW_FRACTION: // this should be a DWORD counter
assert ((pCounter->lNumItemType == VT_I8) || (pCounter->lNumItemType == VT_UI8)); pCounter->pWbemAccess->ReadQWORD ( pCounter->lNumItemHandle, & llValue); pCounter->ThisValue.FirstValue = (LONGLONG) llValue;
assert ((pCounter->lDenItemType == VT_I8) || (pCounter->lDenItemType == VT_UI8)); pCounter->pWbemAccess->ReadQWORD ( pCounter->lDenItemHandle, & llValue); // the denominator should be a 32-bit value
pCounter->ThisValue.SecondValue = (LONGLONG) llValue; break;
case PERF_AVERAGE_TIMER: case PERF_AVERAGE_BULK: // counter (numerator) is a LONGLONG, while the
// denominator is just a DWORD
// this should be a DWORD counter
assert ((pCounter->lNumItemType == VT_I8) || (pCounter->lNumItemType == VT_UI8)); pWbemAccess->ReadQWORD ( pCounter->lNumItemHandle, &llValue); pThisItem->FirstValue = (LONGLONG)llValue;
assert ((pCounter->lDenItemType == VT_I4) || (pCounter->lDenItemType == VT_UI4)); pWbemAccess->ReadDWORD ( pCounter->lDenItemHandle, &dwValue); // the denominator should be a 32-bit value
pThisItem->SecondValue = (LONGLONG)dwValue;
// look up the timebase freq if necessary
if (pCounter->TimeBase == 0) { assert ((pCounter->lFreqItemType == VT_I8) || (pCounter->lFreqItemType == VT_UI8)); pWbemAccess->ReadQWORD ( pCounter->lFreqItemHandle, &llValue); // the timebase is a 64 bit integer
pCounter->TimeBase = llValue; } break; //
// These counters are used as the part of another counter
// and as such should not be used, but in case they are
// they'll be handled here.
//
case PERF_SAMPLE_BASE: case PERF_AVERAGE_BASE: case PERF_COUNTER_MULTI_BASE: case PERF_RAW_BASE: case PERF_LARGE_RAW_BASE: pThisItem->FirstValue = 0; pThisItem->SecondValue = 0; break;
//
// These counters are not supported by this function (yet)
//
case PERF_COUNTER_TEXT: case PERF_COUNTER_NODATA: case PERF_COUNTER_HISTOGRAM_TYPE: pThisItem->FirstValue = 0; pThisItem->SecondValue = 0; break;
case PERF_100NSEC_MULTI_TIMER: case PERF_100NSEC_MULTI_TIMER_INV: default: // an unidentified or unsupported
// counter was returned so
pThisItem->FirstValue = 0; pThisItem->SecondValue = 0; bReturn = FALSE; break; } // we're done with this one so release it
pWbemAccess->Release(); } // measure the memory block used
assert (dwFinalSize == (DWORD)((LPBYTE)szNextNameString - (LPBYTE)(pCounter->pThisRawItemList)));
pCounter->pThisRawItemList->dwLength = dwFinalSize; pCounter->pThisRawItemList->dwItemCount = lNumInstances; pCounter->pThisRawItemList->dwReserved = 0; pCounter->pThisRawItemList->CStatus = ERROR_SUCCESS;
pCounter->pThisRawItemList->TimeStamp = *pTimestamp;
} else { // unable to allocate a new buffer so return error
SetLastError (ERROR_OUTOFMEMORY); bReturn = FALSE; } } } } return bReturn; }
LONG GetQueryWbemData ( IN PPDHI_QUERY pQuery, IN LONGLONG *pllTimeStamp ) { FILETIME GmtFileTime; FILETIME LocFileTime; LONGLONG llTimeStamp = 0; HRESULT hRes; LONG lRetStatus = ERROR_SUCCESS;\
PPDHI_COUNTER pCounter; PDH_STATUS pdhStatus;
// refresh Wbem Refresher
if (bDontRefresh) return ERROR_BUSY;
if (pQuery->pRefresher != NULL) { hRes = pQuery->pRefresher->Refresh(0); } else { hRes = WBEM_E_INITIALIZATION_FAILURE; }
// If multiple objects are being refreshed, some objects may succeed and
// others may fail, in which case WBEM_S_PARTIAL_RESULTS is returned.
if ( FAILED( hRes ) ) { SetLastError (hRes); lRetStatus = PDH_WBEM_ERROR; }
if (lRetStatus == ERROR_SUCCESS) { // get timestamp for this counter
GetSystemTimeAsFileTime(& GmtFileTime); FileTimeToLocalFileTime(& GmtFileTime, & LocFileTime); llTimeStamp = MAKELONGLONG(LocFileTime.dwLowDateTime, LocFileTime.dwHighDateTime);
// now update the counters using this new data
if ((pCounter = pQuery->pCounterListHead) != NULL) { do { if (pCounter->dwFlags & PDHIC_MULTI_INSTANCE) { pdhStatus = UpdateWbemMultiInstanceCounterValue ( pCounter, (FILETIME *)&llTimeStamp); } else { // update single instance counter values
pdhStatus = UpdateWbemCounterValue (pCounter, (FILETIME *)&llTimeStamp); } pCounter = pCounter->next.flink; } while (pCounter != pQuery->pCounterListHead); pdhStatus = ERROR_SUCCESS; } else { // no counters in the query (?!)
pdhStatus = PDH_NO_DATA; } lRetStatus = pdhStatus; } *pllTimeStamp = llTimeStamp;
return lRetStatus; }
HRESULT WbemSetProxyBlanket( IUnknown *pInterface, DWORD dwAuthnSvc, DWORD dwAuthzSvc, OLECHAR *pServerPrincName, DWORD dwAuthLevel, DWORD dwImpLevel, RPC_AUTH_IDENTITY_HANDLE pAuthInfo, DWORD dwCapabilities ) { // Security MUST be set on both the Proxy and it's IUnknown!
IUnknown * pUnk = NULL; IClientSecurity * pCliSec = NULL; HRESULT sc = pInterface->QueryInterface(IID_IUnknown, (void **) &pUnk); if(sc != S_OK) return sc; sc = pInterface->QueryInterface(IID_IClientSecurity, (void **) &pCliSec); if(sc != S_OK) { pUnk->Release(); return sc; } sc = pCliSec->SetBlanket(pInterface, dwAuthnSvc, dwAuthzSvc, pServerPrincName, dwAuthLevel, dwImpLevel, pAuthInfo, dwCapabilities); pCliSec->Release(); pCliSec = NULL; sc = pUnk->QueryInterface(IID_IClientSecurity, (void **) &pCliSec); if(sc == S_OK) { sc = pCliSec->SetBlanket(pUnk, dwAuthnSvc, dwAuthzSvc, pServerPrincName, dwAuthLevel, dwImpLevel, pAuthInfo, dwCapabilities); pCliSec->Release(); } else if (sc == 0x80004002) sc = S_OK; pUnk->Release(); return sc; }
|