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

5343 lines
222 KiB

/*++
Copyright (C) 1995-1999 Microsoft Corporation
Module Name:
wmi.c
Abstract:
WMI interface functions exported by PDH.DLL
--*/
#include <windows.h>
#include <winperf.h>
#define SECURITY_WIN32
#include "security.h"
#include "ntsecapi.h"
#include <mbctype.h>
#include "strsafe.h"
#include <pdh.h>
#include <pdhmsg.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)
#define PDH_WMI_STR_SIZE 1024
__inline
VOID
PdhiSysFreeString(
BSTR * x
)
{
if (x != NULL) {
if (* x != NULL) {
if (SysStringLen(* x) > 0) {
SysFreeString(* x);
}
* x = NULL;
}
}
}
void
PdhWbemWhoAmI(LPCWSTR szTitle)
{
BOOL bReturn;
ULONG dwSize;
WCHAR wszName[1024];
dwSize = 1024;
ZeroMemory(wszName, dwSize * sizeof(WCHAR));
bReturn = GetUserNameExW(NameSamCompatible, wszName, & dwSize);
DebugPrint((1,"\"%ws\"::GetUserNameEx(%c,NameSamCompatible,%d,\"%ws\")\n",
szTitle, bReturn ? 'T' : 'F', dwSize, wszName));
}
// 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_DEFAULT,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
EOAC_DYNAMIC_CLOAKING);
}
// 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;
HANDLE m_hThreadToken;
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_hThreadToken(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
BOOL bReturn;
BOOL bRevert;
HANDLE hCurrentThread = GetCurrentThread();
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).
if (m_hThreadToken != NULL) CloseHandle(m_hThreadToken);
bReturn = OpenThreadToken(hCurrentThread, TOKEN_ALL_ACCESS, TRUE, & m_hThreadToken);
bRevert = RevertToSelf();
m_hThread = CreateThread(NULL, 0, CWbemRefresher::ThreadProc, (void *) this, 0, & m_dwThreadId);
if (bRevert) {
bRevert = SetThreadToken(& hCurrentThread, m_hThreadToken);
}
if (NULL != m_hThread) {
DWORD dwStatus;
dwStatus = WaitForSingleObject(m_hInitializedEvent, 5000);
if (bReturn) {
bReturn = SetThreadToken(& m_hThread, m_hThreadToken);
}
SetEvent(m_hDoWorkEvent);
dwStatus = 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;
}
if (NULL != m_hThreadToken) {
CloseHandle(m_hThreadToken);
m_hThreadToken = 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];
IWbemRefresher * pWbemRefresher = NULL;
IWbemConfigureRefresher * pWbemConfig = NULL;
HRESULT hr = S_OK;
ahEvents[0] = hDoWorkEvent;
ahEvents[1] = hQuitEvent;
// Initialize this thread
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.
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);
SetEvent(hInitializedEvent);
dwWait = WaitForSingleObject(hDoWorkEvent, 5000);
// 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;
break;
}
// 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)
{
SCODE sCode = NOERROR;
* ppvObj = 0;
if (IID_IUnknown==riid) {
* ppvObj = (IUnknown *) this;
AddRef();
}
else if (IID_IWbemRefresher == riid) {
* ppvObj = (IWbemRefresher *) & m_xRefresher;
AddRef();
}
else if (IID_IWbemConfigureRefresher == riid) {
* ppvObj = (IWbemConfigureRefresher *) & m_xConfigRefresher;
AddRef();
}
else {
sCode = ResultFromScode(E_NOINTERFACE);
}
return sCode;
}
ULONG CWbemRefresher::AddRef()
{
return InterlockedIncrement(& m_lRefCount);
}
ULONG CWbemRefresher::Release()
{
long lRef = InterlockedDecrement(& m_lRefCount);
if (lRef == 0) {
delete this;
}
return lRef;
}
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 (m_pNSStream != NULL) {
LPVOID pInterface = NULL;
CoGetInterfaceAndReleaseStream(m_pNSStream, IID_IWbemServices, & pInterface);
m_pNSStream = NULL;
}
if (NULL != pNamespace) {
// Marshal the namespace pointer into the stream member
hr = CoMarshalInterThreadInterfaceInStream(IID_IWbemServices, pNamespace, & m_pNSStream);
}
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)
{
if (m_pNSStream != NULL) {
LPVOID pInterface = NULL;
CoGetInterfaceAndReleaseStream(m_pNSStream, IID_IWbemServices, & pInterface);
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 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_DEFAULT, // 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
PdhiDisconnectWbemServer(
PPDHI_WBEM_SERVER_DEF pWbemServer
)
{
PDH_STATUS pdhReturn = ERROR_SUCCESS;
if (pWbemServer != NULL) {
TRACE((PDH_DBG_TRACE_INFO),
(__LINE__,
PDH_WBEM,
ARG_DEF(ARG_TYPE_WSTR, 1),
pdhReturn,
TRACE_WSTR(pWbemServer->szMachine),
TRACE_DWORD(pWbemServer->lRefCount),
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);
}
}
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
*/
{
PDH_STATUS Status = ERROR_SUCCESS;
DWORD dwSize;
LPWSTR szSrc = NULL;
LPWSTR szDest = NULL;
LPWSTR szLocMachine = NULL;
LPWSTR szLocNamespace = NULL;
if (szMachineAndNamespace == NULL) {
// then use local machine and default namespace
szLocMachine = (LPWSTR) G_ALLOC((lstrlenW(szStaticLocalMachineName) + 1) * sizeof(WCHAR));
szLocNamespace = (LPWSTR) G_ALLOC((lstrlenW(cszWbemDefaultPerfRoot) + 1) * sizeof(WCHAR));
if (szLocMachine != NULL && szLocNamespace != NULL) {
StringCchCopyW(szLocMachine, lstrlenW(szStaticLocalMachineName) + 1, szStaticLocalMachineName);
StringCchCopyW(szLocNamespace, lstrlenW(cszWbemDefaultPerfRoot) + 1, cszWbemDefaultPerfRoot);
}
else {
Status = PDH_MEMORY_ALLOCATION_FAILURE;
}
TRACE((PDH_DBG_TRACE_INFO),
(__LINE__,
PDH_WBEM,
ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
Status,
TRACE_WSTR(szStaticLocalMachineName),
TRACE_WSTR(cszWbemDefaultPerfRoot),
NULL));
}
else {
dwSize = lstrlenW(szMachineAndNamespace) + lstrlenW(cszWbemDefaultPerfRoot) + 1;
szLocMachine = (LPWSTR) G_ALLOC(dwSize * sizeof(WCHAR));
szLocNamespace = (LPWSTR) G_ALLOC(dwSize * sizeof(WCHAR));
if (szLocMachine != NULL && szLocNamespace != NULL) {
szSrc = (LPWSTR) szMachineAndNamespace;
// break into components
if (* szSrc != L'\0') {
// there's a string, see if it's a machine or a namespace
if ((szSrc[0] == L'\\') && (szSrc[1] == L'\\')) {
szDest = szLocMachine;
// then there's a machine name
* szDest ++ = * szSrc ++;
* szDest ++ = * szSrc ++;
while ((* szSrc != L'\0') && (* szSrc != L'\\')) {
* szDest ++ = * szSrc ++;
}
* szDest = L'\0';
}
else {
// no machine so use default
// it must be just a namespace
}
}
if (szDest == NULL) {
// nothing found yet, so insert local machine as default
StringCchCopyW(szLocMachine, dwSize, szStaticLocalMachineName);
}
szDest = szLocNamespace;
if (* szSrc != L'\0') {
// if there's a namespace then copy it
szSrc ++; // move past backslash
while (* szSrc != L'\0') {
* szDest ++ = * szSrc ++;
}
* szDest = L'\0';
}
else {
// else return the default;
StringCchCopyW(szLocNamespace, dwSize, cszWbemDefaultPerfRoot);
}
}
else {
Status = PDH_MEMORY_ALLOCATION_FAILURE;
}
TRACE((PDH_DBG_TRACE_INFO),
(__LINE__,
PDH_WBEM,
ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
ERROR_SUCCESS,
TRACE_WSTR(szLocMachine),
TRACE_WSTR(szLocNamespace),
NULL));
}
if (Status == ERROR_SUCCESS) {
* szMachine = szLocMachine;
* szNamespace = szLocNamespace;
}
else {
G_FREE(szLocMachine);
G_FREE(szLocNamespace);
}
return Status;
}
PDH_FUNCTION
PdhiMakeWbemInstancePath(
PPDH_COUNTER_PATH_ELEMENTS_W pCounterPathElements,
LPWSTR * szFullPathBuffer,
BOOL bMakeRelativePath
)
{
PDH_STATUS Status = ERROR_SUCCESS;
LPWSTR szMachine = NULL;
LPWSTR szNamespace = NULL;
LPWSTR szFullPath = NULL;
LPWSTR szWbemInstance = NULL;
DWORD dwSize;
LPWSTR szSrc, szDest;
if (pCounterPathElements->szMachineName != NULL) {
dwSize = 2 * lstrlenW(pCounterPathElements->szMachineName) + lstrlenW(cszBackSlash) + lstrlenW(cszColon);
}
else {
dwSize = lstrlenW(szStaticLocalMachineName)
+ lstrlenW(cszWbemDefaultPerfRoot) + lstrlenW(cszBackSlash) + lstrlenW(cszColon);
}
dwSize += lstrlenW(pCounterPathElements->szObjectName);
if (pCounterPathElements->szInstanceName != NULL) {
dwSize += (lstrlenW(cszNameParam) + 2 * lstrlenW(pCounterPathElements->szInstanceName)
+ lstrlenW(cszDoubleQuote) + 20);
if (pCounterPathElements->szParentInstance != NULL) {
dwSize += (2 * lstrlenW(pCounterPathElements->szParentInstance) + 1);
}
}
else {
dwSize += (lstrlenW(cszSingletonInstance) + 1);
}
szFullPath = (LPWSTR) G_ALLOC(dwSize * sizeof(WCHAR));
szWbemInstance = (LPWSTR) G_ALLOC(dwSize * sizeof(WCHAR));
if (szFullPath == NULL || szWbemInstance == NULL) {
Status = PDH_MEMORY_ALLOCATION_FAILURE;
goto Cleanup;
}
// 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) {
Status = PdhiBreakWbemMachineName(pCounterPathElements->szMachineName, & szMachine, & szNamespace);
if (Status == ERROR_SUCCESS) {
StringCchPrintfW(szFullPath, dwSize, L"%ws%ws%ws%ws", szMachine, cszBackSlash, szNamespace, cszColon);
}
else {
goto Cleanup;
}
}
else {
* szFullPath = L'\0';
}
if (pCounterPathElements->szInstanceName == NULL) {
// then apply the singleton logic
StringCchCatW(szFullPath, dwSize, pCounterPathElements->szObjectName);
StringCchCatW(szFullPath, dwSize, 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;
if (pCounterPathElements->szParentInstance != NULL) {
szSrc = pCounterPathElements->szParentInstance;
while (* szSrc != L'\0') {
* szDest = * szSrc;
if (* szSrc == BACKSLASH_L) {
* ++ szDest = BACKSLASH_L;
}
szDest ++;
szSrc ++;
}
* szDest ++ = L'/'; // parent/child delimiter
}
szSrc = pCounterPathElements->szInstanceName;
while (* szSrc != L'\0') {
* szDest = * szSrc;
if (* szSrc == BACKSLASH_L) {
* ++ szDest = BACKSLASH_L;
}
szDest ++;
szSrc ++;
}
* szDest = L'\0';
// apply the instance name format
StringCchCatW(szFullPath, dwSize, pCounterPathElements->szObjectName);
StringCchCatW(szFullPath, dwSize, cszNameParam);
StringCchCatW(szFullPath, dwSize, szWbemInstance);
if (pCounterPathElements->dwInstanceIndex != PERF_NO_UNIQUE_ID && pCounterPathElements->dwInstanceIndex != 0) {
WCHAR szIndex[20];
ZeroMemory(szIndex, 20 * sizeof(WCHAR));
_ultow(pCounterPathElements->dwInstanceIndex, szIndex, 10);
StringCchCatW(szFullPath, dwSize, L"#");
StringCchCatW(szFullPath, dwSize, szIndex);
}
StringCchCatW(szFullPath, dwSize, cszDoubleQuote);
}
Cleanup:
if (Status == ERROR_SUCCESS) {
* szFullPathBuffer = szFullPath;
}
else {
G_FREE(szFullPath);
* szFullPathBuffer = NULL;
}
G_FREE(szMachine);
G_FREE(szNamespace);
G_FREE(szWbemInstance);
return Status;
}
PDH_FUNCTION
PdhiWbemGetCounterPropertyName(
IWbemClassObject * pThisClass,
LPCWSTR szCounterDisplayName,
LPWSTR * szPropertyName
)
{
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;
VARIANT vCountertype;
IWbemQualifierSet * pQualSet = NULL;
LPWSTR szLocCounter = NULL;
* szPropertyName = 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) {
hResult = SafeArrayAccessData(psaNames, (LPVOID *) & bsPropName);
if (SUCCEEDED(hResult)) {
for (lCount = lLower; lCount <= lUpper; lCount++) {
// this is the desired counter so
// get the qualifier set for this property
hResult = pThisClass->GetPropertyQualifierSet(bsPropName[lCount], & 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
szLocCounter = (LPWSTR) G_ALLOC(
(lstrlenW((LPWSTR) bsPropName[lCount]) + 1) * sizeof(WCHAR));
if (szLocCounter != NULL) {
StringCchCopyW(szLocCounter,
lstrlenW((LPWSTR) bsPropName[lCount]) + 1,
(LPWSTR) bsPropName[lCount]);
* szPropertyName = szLocCounter;
pdhStatus = ERROR_SUCCESS;
pQualSet->Release();
pQualSet = NULL;
break;
}
else {
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
}
}
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;
}
} // end for each element in SafeArray
SafeArrayUnaccessData(psaNames);
}
else {
// unable to read element in SafeArray
pdhStatus = PDH_WBEM_ERROR;
SetLastError(hResult);
}
}
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);
}
if (pdhStatus != ERROR_SUCCESS) {
G_FREE(szLocCounter);
}
return pdhStatus;
}
PDH_FUNCTION
PdhiWbemGetCounterDisplayName(
IWbemClassObject * pThisClass,
LPCWSTR szCounterName,
LPWSTR * szDisplayName
)
{
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;
LPWSTR szLocDisplay = NULL;
* szDisplayName = 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) {
hResult = SafeArrayAccessData(psaNames, (LPVOID *) & bsPropName);
if (SUCCEEDED(hResult)) {
for (lCount = lLower; lCount <= lUpper; lCount++) {
if (lstrcmpiW ((LPWSTR) (bsPropName[lCount]), szCounterName) == 0) {
// this is the desired counter so
// get the qualifier set for this property
hResult = pThisClass->GetPropertyQualifierSet(bsPropName[lCount], & 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
szLocDisplay = (LPWSTR) G_ALLOC(
(lstrlenW((LPWSTR) (V_BSTR(& vName))) + 1) * sizeof(WCHAR));
if (szLocDisplay != NULL) {
StringCchCopyW(szLocDisplay,
lstrlenW((LPWSTR) (V_BSTR(& vName))) + 1,
(LPWSTR) V_BSTR(& vName));
* szDisplayName = szLocDisplay;
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;
}
} // end for each element in SafeArray
SafeArrayUnaccessData(psaNames);
}
else {
// unable to read element in SafeArray
pdhStatus = PDH_WBEM_ERROR;
SetLastError(hResult);
}
}
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);
}
if (pdhStatus != ERROR_SUCCESS) {
G_FREE(szLocDisplay);
}
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,
IWbemClassObject ** pReturnClass
)
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
HRESULT hResult;
BSTR bsClassName;
BSTR bsClass;
BSTR bsDisplayName;
VARIANT vName;
LPWSTR szDisplayName = NULL;
LPWSTR szRtnDisplay = NULL;
IWbemClassObject * pThisClass = NULL;
IWbemQualifierSet * pQualSet = NULL;
* szClassDisplayName = 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 != NULL) {
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;
}
PdhiSysFreeString(& bsDisplayName);
}
else {
hResult = WBEM_E_OUT_OF_MEMORY;
}
pQualSet->Release();
}
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);
szRtnDisplay = (LPWSTR) G_ALLOC((lstrlenW(szDisplayName) + 1) * sizeof(WCHAR));
if (szRtnDisplay != NULL) {
StringCchCopyW(szRtnDisplay, lstrlenW(szDisplayName) + 1, szDisplayName);
* szClassDisplayName = szRtnDisplay;
pdhStatus = ERROR_SUCCESS;
}
else {
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
}
}
if (hResult == S_OK) {
if (pReturnClass != NULL) {
// return the class pointer, the caller will close it
* pReturnClass = pThisClass;
}
else {
// close it
pThisClass->Release();
}
}
else {
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(
PPDHI_WBEM_SERVER_DEF pThisServer,
LPVOID mszObjectList,
LPDWORD pcchBufferSize,
DWORD dwDetailLevel,
BOOL bRefresh,
BOOL bUnicode
);
PDH_FUNCTION
PdhiWbemGetObjectClassName(
PPDHI_WBEM_SERVER_DEF pThisServer,
LPCWSTR szObjectName,
LPWSTR * szObjectClassName,
IWbemClassObject ** pReturnClass
)
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
HRESULT hResult;
LPWSTR szLocObject = NULL;
LONG lResult;
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) {
szLocObject = (LPWSTR) G_ALLOC((lstrlenW(pObject->szObject) + 1) * sizeof(WCHAR));
if (szLocObject == NULL) {
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
}
else {
pdhStatus = ERROR_SUCCESS;
StringCchCopyW(szLocObject, lstrlenW(pObject->szObject) + 1, pObject->szObject);
}
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;
}
PdhiSysFreeString(& bsClassName);
}
else {
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
}
}
else if (pReturnClass != NULL) {
* pReturnClass = pObject->pClass;
}
break;
}
pObject = pObject->pNext;
}
}
if (pdhStatus == ERROR_SUCCESS) {
* szObjectClassName = szLocObject;
}
else {
G_FREE(szLocObject);
}
return pdhStatus;
}
#pragma warning ( default : 4127 )
PDH_FUNCTION
PdhiAddWbemServer(
LPCWSTR szMachineName,
PPDHI_WBEM_SERVER_DEF * pWbemServer
)
{
IWbemLocator * pWbemLocator = NULL;
IWbemServices * pWbemServices = NULL;
PDH_STATUS pdhStatus = ERROR_SUCCESS;
HRESULT hResult;
DWORD dwResult;
DWORD dwStrLen = 0;
PPDHI_WBEM_SERVER_DEF pNewServer = NULL;
LPWSTR szLocalMachineName = NULL;
LPWSTR szLocalNameSpaceString = NULL;
LPWSTR szLocalServerPath = NULL;
LPWSTR szLocale = NULL;
// szMachineName can be null,
// that means use the local machine and default namespace
// 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) {
pdhStatus = PdhiBreakWbemMachineName(szMachineName, & szLocalMachineName, & szLocalNameSpaceString);
if (pdhStatus == ERROR_SUCCESS) {
dwStrLen = lstrlenW(szLocalMachineName) + lstrlenW(szLocalNameSpaceString) + 1;
szLocalServerPath = (LPWSTR) G_ALLOC((dwStrLen + 32) * sizeof(WCHAR));
if (szLocalServerPath == NULL) {
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
}
else {
BSTR bstrLocalServerPath;
BSTR bstrLocale;
StringCchPrintfW(szLocalServerPath, dwStrLen, L"%ws%ws", szLocalMachineName, szLocalNameSpaceString);
bstrLocalServerPath = SysAllocString(szLocalServerPath);
// Create the locale
szLocale = szLocalServerPath + dwStrLen;
StringCchPrintfW(szLocale, 32, L"MS_%hX", GetUserDefaultUILanguage());
bstrLocale = SysAllocString(szLocale);
if (bstrLocalServerPath && bstrLocale) {
// try to connect to the service
hResult = pWbemLocator->ConnectServer(bstrLocalServerPath,
NULL,
NULL,
bstrLocale,
0L,
NULL,
NULL,
& pWbemServices);
if (FAILED(hResult)) {
SetLastError(hResult);
pdhStatus = PDH_CANNOT_CONNECT_WMI_SERVER;
}
else {
dwStrLen = lstrlenW(szLocalMachineName) + 1;
}
PdhiSysFreeString(& bstrLocalServerPath);
PdhiSysFreeString(& bstrLocale);
}
else {
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
}
}
}
// 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];
StringCchCopyW(pNewServer->szMachine, dwStrLen, 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
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));
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);
G_FREE(szLocalMachineName);
G_FREE(szLocalNameSpaceString);
G_FREE(szLocalServerPath);
return pdhStatus;
}
PDH_FUNCTION
PdhiCloseWbemServer(
PPDHI_WBEM_SERVER_DEF pWbemServer
)
{
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;
DWORD dwSize;
// get the local machine name & default name space if the caller
// has passed in a NULL machine name
if (szMachineName == NULL) {
pdhStatus = PdhiBreakWbemMachineName(NULL, & szWideMachineName, & szWideNamespace);
// lstrcatW (szWideMachineName, cszBackSlash);
// lstrcatW (szWideMachineName, szWideNamespace);
if (pdhStatus == ERROR_SUCCESS) {
dwSize = lstrlenW(szWideMachineName) + 3;
szMachineNameArg = (LPWSTR) G_ALLOC(sizeof(WCHAR) * dwSize);
if (szMachineNameArg == NULL) {
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
}
else {
if (szWideMachineName[0] == L'\\' && szWideMachineName[1] == L'\\') {
StringCchCopyW(szMachineNameArg, dwSize, szWideMachineName);
}
else {
StringCchPrintfW(szMachineNameArg, dwSize, L"%ws%ws", cszDoubleBackSlash, szWideMachineName);
}
pdhStatus = ERROR_SUCCESS;
}
}
}
else {
dwSize = lstrlenW(szMachineName) + 3;
szMachineNameArg = (LPWSTR) G_ALLOC(sizeof(WCHAR) * dwSize);
if (szMachineNameArg == NULL) {
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
}
else {
if (szMachineName[0] == L'\\' && szMachineName[1] == L'\\') {
StringCchCopyW(szMachineNameArg, dwSize, szMachineName);
}
else {
StringCchPrintfW(szMachineNameArg, dwSize, L"%ws%ws", cszDoubleBackSlash, szMachineName);
}
pdhStatus = ERROR_SUCCESS;
}
}
if (pdhStatus == ERROR_SUCCESS) {
// walk down list of connected servers and find the requested one
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) {
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;
}
}
}
}
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++;
}
G_FREE(szWideMachineName);
G_FREE(szWideNamespace);
G_FREE(szMachineNameArg);
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(
LPCWSTR szMachineName,
LPCWSTR szObjectName,
LPCWSTR szCounterName,
LPWSTR szExplain,
LPDWORD pdwExplain
)
{
PDH_STATUS Status = ERROR_SUCCESS;
HRESULT hResult;
BOOL bDisconnect = FALSE;
DWORD dwExplain = 0;
VARIANT vsExplain;
LPWSTR szObjectClassName = NULL;
PPDHI_WBEM_SERVER_DEF pThisServer = NULL;
IEnumWbemClassObject * pEnum = NULL;
IWbemClassObject * pThisObject = NULL;
IWbemQualifierSet * pQualSet = NULL;
BOOL fCoInitialized = PdhiCoInitialize();
if (szMachineName == NULL || szObjectName == NULL || pdwExplain == NULL) {
Status = PDH_INVALID_ARGUMENT;
}
else {
dwExplain = * pdwExplain;
if (szExplain != NULL && dwExplain != 0) {
ZeroMemory(szExplain, dwExplain);
}
}
if (Status == ERROR_SUCCESS) {
Status = PdhiConnectWbemServer(szMachineName, & pThisServer);
}
if (Status == ERROR_SUCCESS) {
bDisconnect = TRUE;
Status = PdhiWbemGetObjectClassName(pThisServer, szObjectName, & szObjectClassName, & 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) {
hResult = SafeArrayAccessData(psaNames, (LPVOID *) & bsPropName);
if (SUCCEEDED(hResult)) {
for (lCount = lLower; lCount <= lUpper; lCount++) {
hResult = pThisObject->GetPropertyQualifierSet(bsPropName[lCount], & 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) {
if (vName.vt == VT_BSTR &&
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)) + 1 < dwExplain) {
StringCchCopyW(szExplain, dwExplain, szResult);
Status = ERROR_SUCCESS;
}
else {
* pdwExplain = (DWORD) lstrlenW(szResult) + 1;
Status = PDH_MORE_DATA;
}
}
pQualSet->Release();
break;
}
VariantClear(& vName);
}
}
VariantClear(& vCountertype);
}
pQualSet->Release();
}
}
SafeArrayUnaccessData(psaNames);
}
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) + 1 < dwExplain) {
StringCchCopyW(szExplain, dwExplain, szResult);
Status = ERROR_SUCCESS;
}
else {
* pdwExplain = (DWORD) lstrlenW(szResult) + 1;
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();
}
G_FREE(szObjectClassName);
return Status;
}
PDH_FUNCTION
PdhiEnumWbemMachines(
LPVOID pMachineList,
LPDWORD pcchBufferSize,
BOOL bUnicode
)
{
PDH_STATUS pdhStatus;
PPDHI_WBEM_SERVER_DEF pThisServer = NULL;
DWORD dwCharsLeftInBuffer = * pcchBufferSize;
DWORD dwBufferSize = 0;
DWORD dwStrLen;
DWORD dwResult;
// 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
pdhStatus = AddUniqueWideStringToMultiSz(
pMachineList, pThisServer->szMachine, dwCharsLeftInBuffer, & dwResult, bUnicode);
if (pdhStatus == ERROR_SUCCESS) {
if (dwResult > 0) {
dwBufferSize = dwResult;
dwCharsLeftInBuffer = * pcchBufferSize - dwBufferSize;
} // else
// this string is already in the list so
// nothing was added
}
else if (pdhStatus == PDH_MORE_DATA) {
dwCharsLeftInBuffer = 0; // to prevent any other strings from being added
dwBufferSize += dwStrLen;
}
else {
goto Cleanup;
}
}
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;
Cleanup:
// CoUninitialize if necessary
if (fCoInitialized) {
PdhiCoUninitialize();
}
return pdhStatus;
}
#pragma warning ( disable : 4127 )
PDH_FUNCTION
PdhiEnumWbemServerObjects(
PPDHI_WBEM_SERVER_DEF pThisServer,
LPVOID mszObjectList,
LPDWORD pcchBufferSize,
DWORD dwDetailLevel,
BOOL bRefresh, // ignored
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 pThisObj = pThisServer->pObjList;
PPDHI_WBEM_OBJECT_DEF pNext;
pThisServer->pObjList = NULL;
while (pThisObj != NULL) {
pNext = pThisObj->pNext;
if (pThisObj->pClass != NULL) pThisObj->pClass->Release();
G_FREE(pThisObj);
pThisObj = 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
pdhStatus = AddUniqueWideStringToMultiSz(
mszObjectList, szClassName, dwCharsLeftInBuffer, & dwResult, bUnicode);
if (pdhStatus == ERROR_SUCCESS) {
if (dwResult > 0) {
dwBufferSize = dwResult;
dwCharsLeftInBuffer = * pcchBufferSize - dwBufferSize;
} // else
// this string is already in the list so
// nothing was added
}
else if (pdhStatus == PDH_MORE_DATA) {
dwCharsLeftInBuffer = 0; // to prevent any other strings from being added
dwBufferSize += dwStrLen;
}
}
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));
StringCchCopyW(pObject->szObject, lstrlenW(szClass) + 1, szClass);
pObject->szDisplay = (LPWSTR) (((LPBYTE) pObject)
+ sizeof(PDHI_WBEM_OBJECT_DEF)
+ sizeof(WCHAR) * (lstrlenW(szClass) + 1));
StringCchCopyW(pObject->szDisplay, lstrlenW(szClassName) + 1, 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();
}
if (dwBufferSize == 0) {
pdhStatus = PDH_WBEM_ERROR;
}
else {
dwBufferSize ++; // the final NULL
}
if (pdhStatus == ERROR_SUCCESS) {
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(
LPCWSTR szWideMachineName,
LPVOID mszObjectList,
LPDWORD pcchBufferSize,
DWORD dwDetailLevel,
BOOL bRefresh, // ignored
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(
LPCWSTR szMachineName,
LPVOID szDefaultObjectName,
LPDWORD pcchBufferSize,
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;
}
else if (pdhStatus == PDH_MORE_DATA) {
pdhStatus = PDH_WBEM_ERROR;
}
}
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) {
StringCchCopyW((LPWSTR) szDefaultObjectName,
* pcchBufferSize,
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(
LPCWSTR szWideMachineName,
LPCWSTR szWideObjectName,
LPVOID mszCounterList,
LPDWORD pcchCounterListLength,
LPVOID mszInstanceList,
LPDWORD pcchInstanceListLength,
DWORD dwDetailLevel,
DWORD dwFlags,
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;
LPWSTR szObjectClassName = NULL;
BSTR bsName = NULL;
BSTR bsClassName = NULL;
BOOL bSingletonClass = FALSE;
VARIANT vName;
DWORD bDisconnectServer = FALSE;
IWbemClassObject * pThisClass = NULL;
IWbemQualifierSet * pQualSet = NULL;
// CoInitialize() if we need to
BOOL fCoInitialized = PdhiCoInitialize();
DBG_UNREFERENCED_PARAMETER (dwFlags);
pdhStatus = PdhiConnectWbemServer(szWideMachineName, & pThisServer);
// enumerate the instances
if (pdhStatus == ERROR_SUCCESS) {
pdhStatus = PdhiWbemGetObjectClassName(pThisServer, szWideObjectName, & szObjectClassName, & pThisClass);
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);
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) {
hResult = SafeArrayAccessData(psaNames, (LPVOID *) & bsPropName);
if (SUCCEEDED(hResult)) {
for (lCount = lLower; lCount <= lUpper; lCount++) {
// get the qualifier set for this property
hResult = pThisClass->GetPropertyQualifierSet(bsPropName[lCount], & 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))) {
StringCchCopyW(szNextWideString,
* pcchCounterListLength - dwCounterStringLen,
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
}
} // end for each element in SafeArray
SafeArrayUnaccessData(psaNames);
}
else {
// unable to read element in SafeArray
pdhStatus = PDH_WBEM_ERROR;
SetLastError(hResult);
}
}
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 ++ = L'\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 * sizeof(WCHAR), & lSize2, (LPBYTE) szName);
if (SUCCEEDED(hResult) && lstrlenW(szName) > 0) {
if (bUnicode) {
dwStrLen = lstrlenW(szName) + 1;
if ((mszInstanceList != NULL)
&& ((dwInstanceStringLen + dwStrLen)
< (* pcchInstanceListLength))) {
StringCchCopyW(szNextWideString,
* pcchInstanceListLength - dwInstanceStringLen,
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)) {
IEnumWbemClassObject * pEnumObject = NULL;
bsName = SysAllocString(cszName);
bsClassName = SysAllocString(szObjectClassName);
if (bsName && bsClassName) {
// get Create enumerator for this class and get the instances
hResult = pThisServer->pSvc->CreateInstanceEnum(bsClassName, WBEM_FLAG_DEEP, NULL, & pEnumObject);
if (SUCCEEDED(hResult)) {
hResult = SetWbemSecurity(pEnumObject);
}
if (hResult != WBEM_NO_ERROR) {
pdhStatus = PDH_WBEM_ERROR;
SetLastError(hResult);
}
else {
LPWSTR szInstance;
while (TRUE) {
hResult = pEnumObject->Next(WBEM_INFINITE, 1, & pThisClass, & dwReturnCount);
if ((pThisClass == NULL) || (dwReturnCount == 0)) {
// no more instances
break;
}
else {
// name of this instance is in the NAME property
hResult = pThisClass->Get(bsName, 0, & vName, 0, 0);
if (hResult == WBEM_NO_ERROR) {
szInstance = (LPWSTR) V_BSTR(& vName);
if (bUnicode) {
dwStrLen = lstrlenW(szInstance) + 1;
if ((mszInstanceList != NULL)
&& ((dwInstanceStringLen + dwStrLen)
< (* pcchInstanceListLength))) {
StringCchCopyW(szNextWideString,
* pcchInstanceListLength - dwInstanceStringLen,
szInstance);
szNextWideString += dwStrLen;
}
else {
pdhStatus = PDH_MORE_DATA;
}
}
else {
dwStrLen = (dwInstanceStringLen <= * pcchInstanceListLength)
? (* pcchInstanceListLength - dwInstanceStringLen)
: (0);
pdhStatus = PdhiConvertUnicodeToAnsi(_getmbcp(),
szInstance,
szNextAnsiString,
& dwStrLen);
if (pdhStatus == ERROR_SUCCESS) {
szNextAnsiString += dwStrLen;
}
}
dwInstanceStringLen += dwStrLen;
}
// clear the variant
VariantClear(& vName);
}
pThisClass->Release();
}
}
}
else {
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
}
PdhiSysFreeString(& bsClassName);
PdhiSysFreeString(& bsName);
if (pEnumObject != NULL) pEnumObject->Release();
}
if (pdhStatus == ERROR_SUCCESS || pdhStatus == PDH_MORE_DATA) {
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 ++;
}
}
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 ++ = L'\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);
}
G_FREE(szObjectClassName);
return pdhStatus;
}
#pragma warning ( default : 4127 )
PDH_FUNCTION
PdhiGetDefaultWbemProperty(
LPCWSTR szMachineName,
LPCWSTR szObjectName,
LPVOID szDefaultCounterName,
LPDWORD pcchBufferSize,
BOOL bUnicode
)
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
DWORD dwStrLen;
PPDHI_WBEM_SERVER_DEF pThisServer;
HRESULT hResult;
DWORD dwCounterStringLen = 0;
LPWSTR szObjectClassName = NULL;
DWORD bDisconnectServer = FALSE;
BOOL bFound = FALSE;
long lFound = -1;
long lFirst = -1;
IWbemClassObject * pThisClass = NULL;
IWbemQualifierSet * pQualSet = 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, & 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 bsFirstName = 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) {
bFound = FALSE;
lFound = -1;
hResult = SafeArrayAccessData(psaNames, (LPVOID *) & bsPropName);
if (SUCCEEDED(hResult)) {
for (lCount = lLower; lCount <= lUpper; lCount ++) {
hResult = pThisClass->GetPropertyQualifierSet(bsPropName[lCount], & pQualSet);
if (hResult == WBEM_NO_ERROR) {
if (lFirst < 0) {
hResult = pQualSet->Get(bsDisplayname, 0, & vName, NULL);
if (hResult == WBEM_NO_ERROR) {
lFirst = lCount;
VariantClear(& vName);
}
}
hResult = pQualSet->Get(bsPerfDefault, 0, & vCountertype, NULL);
if (hResult == WBEM_NO_ERROR) {
if ((BOOL) V_BOOL(& vCountertype)) {
bFound = TRUE;
lFound = lCount;
}
VariantClear(& vCountertype);
}
pQualSet->Release();
}
if (bFound) break;
}
SafeArrayUnaccessData(psaNames);
}
if (lFound < 0) lFound = lFirst;
if (lFound < 0) {
pdhStatus = PDH_WBEM_ERROR;
SetLastError(PDH_WBEM_ERROR);
}
else {
hResult = SafeArrayGetElement(psaNames, & lFound, & bsFirstName);
if (hResult == S_OK) {
// get the qualifier set for this property
hResult = pThisClass->GetPropertyQualifierSet(bsFirstName, & pQualSet);
if (hResult == WBEM_NO_ERROR) {
// found the default property so load it and return
hResult = pQualSet->Get(bsDisplayname, 0, & vName, NULL);
if (hResult == WBEM_NO_ERROR) {
// display name found
if (bUnicode) {
dwStrLen = lstrlenW(V_BSTR(&vName)) + 1;
if ((szDefaultCounterName != NULL) && (dwStrLen <= * pcchBufferSize)) {
StringCchCopyW((LPWSTR) szDefaultCounterName,
* pcchBufferSize,
(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
VariantClear(& vName);
}
pQualSet->Release();
}
PdhiSysFreeString(& bsFirstName);
}
else {
// unable to read element in SafeArray
pdhStatus = PDH_WBEM_ERROR;
SetLastError(hResult);
}
}
}
else {
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
}
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();
}
G_FREE(szObjectClassName);
return pdhStatus;
}
PDH_FUNCTION
PdhiEncodeWbemPathW(
PPDH_COUNTER_PATH_ELEMENTS_W pCounterPathElements,
LPWSTR szFullPathBuffer,
LPDWORD pcchBufferSize,
LANGID LangId,
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;
LPWSTR szTempObjectString = NULL;
LPWSTR szTempCounterString = NULL;
DWORD dwCurSize = 0;
LPWSTR szThisChar;
IWbemClassObject * pWbemClass = NULL;
PPDHI_WBEM_SERVER_DEF pWbemServer = NULL;
DWORD bDisconnectServer = FALSE;
// CoInitialize() if we need to
BOOL fCoInitialized = PdhiCoInitialize();
BOOL bObjectColon = FALSE;
DBG_UNREFERENCED_PARAMETER(LangId);
// create a working buffer the same size as the one passed in
if (pCounterPathElements->szMachineName != NULL) {
dwBuffSize = lstrlenW(pCounterPathElements->szMachineName) + 1;
}
else {
dwBuffSize = lstrlenW(cszDoubleBackSlashDot) + 1;
}
if (pCounterPathElements->szObjectName != NULL) {
// 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, & 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,
& pWbemClass);
// add a backslash path separator for registry output
if (pdhStatus == ERROR_SUCCESS) {
if (dwFlags & PDH_PATH_WBEM_RESULT) {
bObjectColon = TRUE;
dwBuffSize += lstrlenW(cszColon);
G_FREE(szTempObjectString);
szTempObjectString = (LPWSTR) G_ALLOC(
(lstrlenW(pCounterPathElements->szObjectName) + 1) * sizeof(WCHAR));
if (szTempObjectString != NULL) {
StringCchCopyW(szTempObjectString,
lstrlenW(pCounterPathElements->szObjectName) + 1,
pCounterPathElements->szObjectName);
}
else {
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
}
}
else {
dwBuffSize += lstrlenW(cszBackSlash);
}
}
}
else {
// convert the display name to a Wbem class name
pdhStatus = PdhiWbemGetObjectClassName(pWbemServer,
pCounterPathElements->szObjectName,
& szTempObjectString,
& pWbemClass);
// add a colon path separator
bObjectColon = TRUE;
dwBuffSize += lstrlenW(cszColon);
}
if (pdhStatus == ERROR_SUCCESS) {
//then add the string
dwBuffSize += lstrlenW(szTempObjectString);
}
if (bDisconnectServer) {
if (pdhStatus == ERROR_SUCCESS) {
pdhStatus = PdhiDisconnectWbemServer(pWbemServer);
}
else {
// keep error code from function body
PdhiDisconnectWbemServer(pWbemServer);
}
}
}
}
else {
pdhStatus = PDH_CSTATUS_NO_OBJECT;
}
if (pCounterPathElements->szInstanceName != NULL) {
dwBuffSize += lstrlenW(cszLeftParen) + lstrlenW(pCounterPathElements->szInstanceName) + lstrlenW(cszRightParen);
if (pCounterPathElements->szParentInstance != NULL) {
dwBuffSize += lstrlenW(pCounterPathElements->szParentInstance) + lstrlenW(cszSlash);
}
}
if (pdhStatus == ERROR_SUCCESS) {
if (pCounterPathElements->szCounterName != NULL) {
// 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
// add a backslash path separator
dwBuffSize += lstrlenW(cszBackSlash);
if (dwFlags & PDH_PATH_WBEM_INPUT) {
// convert the WBEM Class to the display name
pdhStatus = PdhiWbemGetCounterDisplayName(pWbemClass,
pCounterPathElements->szCounterName,
& szTempCounterString);
if (pdhStatus == ERROR_SUCCESS) {
if (dwFlags & PDH_PATH_WBEM_RESULT) {
// just copy the string, but save
// the class pointer
G_FREE(szTempCounterString);
szTempCounterString = (LPWSTR) G_ALLOC(
(lstrlenW(pCounterPathElements->szCounterName) + 1) * sizeof(WCHAR));
if (szTempCounterString != NULL) {
StringCchCopyW(szTempCounterString,
lstrlenW(pCounterPathElements->szCounterName) + 1,
pCounterPathElements->szCounterName);
}
else {
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
}
}
}
}
else {
// convert the display name to a Wbem class name
pdhStatus = PdhiWbemGetCounterPropertyName(pWbemClass,
pCounterPathElements->szCounterName,
& szTempCounterString);
}
if (pdhStatus == ERROR_SUCCESS) {
//then add the string
dwBuffSize += lstrlenW(szTempCounterString);
}
}
else {
// no object name, so bad structure
pdhStatus = PDH_CSTATUS_NO_COUNTER;
}
}
if (pdhStatus == ERROR_SUCCESS) {
szTempPath = (LPWSTR) G_ALLOC(dwBuffSize * sizeof(WCHAR));
if (szTempPath == NULL) {
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
}
}
if (pdhStatus == ERROR_SUCCESS) {
// start by adding the machine name to the path
if (pCounterPathElements->szMachineName != NULL) {
StringCchCopyW(szTempPath, dwBuffSize, 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 != L'\0') && (* szThisChar != L'\\');
szThisChar ++);
if (* szThisChar != L'\0') * szThisChar = L'\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)) {
StringCchCopyW(szTempPath, dwBuffSize, cszDoubleBackSlashDot); // default machine
//NAMEFIX lstrcatW(szTempPath, cszWbemDefaultPerfRoot);
}
else {
// no entry required for the registry path
}
}
// now add the object or class name
if (pdhStatus == ERROR_SUCCESS) {
if (pCounterPathElements->szObjectName != NULL) {
// 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
if (bObjectColon) {
StringCchCatW(szTempPath, dwBuffSize, cszColon);
}
else {
StringCchCatW(szTempPath, dwBuffSize, cszBackSlash);
}
StringCchCatW(szTempPath, dwBuffSize, szTempObjectString);
}
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) {
StringCchCatW(szTempPath, dwBuffSize, cszLeftParen);
if (pCounterPathElements->szParentInstance != NULL) {
StringCchCatW(szTempPath, dwBuffSize, pCounterPathElements->szParentInstance);
StringCchCatW(szTempPath, dwBuffSize, cszSlash);
}
StringCchCatW(szTempPath, dwBuffSize, pCounterPathElements->szInstanceName);
StringCchCatW(szTempPath, dwBuffSize, cszRightParen);
}
}
// add counter name
if (pdhStatus == ERROR_SUCCESS) {
if (pCounterPathElements->szCounterName != NULL) {
StringCchCatW(szTempPath, dwBuffSize, cszBackSlash);
StringCchCatW(szTempPath, dwBuffSize, szTempCounterString);
}
else {
pdhStatus = PDH_CSTATUS_NO_COUNTER;
}
}
}
if (pdhStatus == ERROR_SUCCESS) {
dwCurSize = lstrlenW(szTempPath) + 1;
// copy path to the caller's buffer if it will fit
if (szFullPathBuffer != NULL && (dwCurSize < * pcchBufferSize)) {
StringCchCopyW(szFullPathBuffer, dwCurSize, szTempPath);
}
else {
pdhStatus = PDH_MORE_DATA;
}
* pcchBufferSize = dwCurSize;
}
// CoUninitialize if necessary
if (fCoInitialized) {
PdhiCoUninitialize();
}
G_FREE(szTempPath);
G_FREE(szTempObjectString);
G_FREE(szTempCounterString);
return pdhStatus;
}
PDH_FUNCTION
PdhiEncodeWbemPathA(
PPDH_COUNTER_PATH_ELEMENTS_A pCounterPathElements,
LPSTR szFullPathBuffer,
LPDWORD pcchBufferSize,
LANGID LangId,
DWORD dwFlags
)
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
LPWSTR wszReturnBuffer;
PPDH_COUNTER_PATH_ELEMENTS_W pWideCounterPathElements;
DWORD dwcchBufferSize;
DWORD dwBuffSize;
// get required buffer size...
dwBuffSize = sizeof (PDH_COUNTER_PATH_ELEMENTS_W);
pWideCounterPathElements = (PPDH_COUNTER_PATH_ELEMENTS_W) G_ALLOC(sizeof(PDH_COUNTER_PATH_ELEMENTS_W));
if (pWideCounterPathElements != NULL) {
if (pCounterPathElements->szMachineName != NULL) {
pWideCounterPathElements->szMachineName = PdhiMultiByteToWideChar(
_getmbcp(), pCounterPathElements->szMachineName);
if (pWideCounterPathElements->szMachineName == NULL) {
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
}
}
else {
pWideCounterPathElements->szMachineName = NULL;
}
if (pCounterPathElements->szObjectName != NULL) {
pWideCounterPathElements->szObjectName = PdhiMultiByteToWideChar(
_getmbcp(), pCounterPathElements->szObjectName);
if (pWideCounterPathElements->szObjectName == NULL) {
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
}
}
else {
pWideCounterPathElements->szObjectName = NULL;
}
if (pCounterPathElements->szCounterName != NULL) {
pWideCounterPathElements->szCounterName = PdhiMultiByteToWideChar(
_getmbcp(), pCounterPathElements->szCounterName);
if (pWideCounterPathElements->szCounterName == NULL) {
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
}
}
else {
pWideCounterPathElements->szCounterName = NULL;
}
if (pCounterPathElements->szInstanceName != NULL) {
pWideCounterPathElements->szInstanceName = PdhiMultiByteToWideChar(
_getmbcp(), pCounterPathElements->szInstanceName);
if (pWideCounterPathElements->szInstanceName == NULL) {
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
}
}
else {
pWideCounterPathElements->szInstanceName = NULL;
}
if (pCounterPathElements->szParentInstance != NULL) {
pWideCounterPathElements->szParentInstance = PdhiMultiByteToWideChar(
_getmbcp(), pCounterPathElements->szParentInstance);
if (pWideCounterPathElements->szParentInstance == NULL) {
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
}
}
else {
pWideCounterPathElements->szParentInstance = NULL;
}
pWideCounterPathElements->dwInstanceIndex = pCounterPathElements->dwInstanceIndex;
dwcchBufferSize = * pcchBufferSize;
if (szFullPathBuffer != NULL) {
wszReturnBuffer = (LPWSTR) G_ALLOC(dwcchBufferSize * sizeof(WCHAR));
if (wszReturnBuffer == NULL) {
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
}
}
else {
wszReturnBuffer = NULL;
}
if (pdhStatus == ERROR_SUCCESS) {
// 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(wszReturnBuffer);
G_FREE(pWideCounterPathElements->szMachineName);
G_FREE(pWideCounterPathElements->szObjectName);
G_FREE(pWideCounterPathElements->szCounterName);
G_FREE(pWideCounterPathElements->szInstanceName);
G_FREE(pWideCounterPathElements->szParentInstance);
G_FREE(pWideCounterPathElements);
}
else {
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
}
return pdhStatus;
}
PDH_FUNCTION
PdhiDecodeWbemPathW(
LPCWSTR szFullPathBuffer,
PPDH_COUNTER_PATH_ELEMENTS_W pCounterPathElements,
LPDWORD pdwBufferSize,
LANGID LangId,
DWORD dwFlags
)
{
PPDHI_COUNTER_PATH pLocalCounterPath;
PDH_STATUS pdhStatus = ERROR_SUCCESS;
BOOL bMoreData = FALSE;
DWORD dwBufferSize = * pdwBufferSize;
DWORD dwUsed = sizeof(PDH_COUNTER_PATH_ELEMENTS_W);
DWORD dwString;
DWORD dwSize;
LPWSTR szString = NULL;
LPWSTR wszTempBuffer = NULL;
LPWSTR szSrc = NULL;
PPDHI_WBEM_SERVER_DEF pThisServer = NULL;
IWbemClassObject * pThisClass = NULL;
// CoInitialize() if we need to
BOOL fCoInitialized = PdhiCoInitialize();
DBG_UNREFERENCED_PARAMETER(LangId);
// allocate a temporary work buffer
dwSize = sizeof(PDHI_COUNTER_PATH) + 2 * sizeof(WCHAR)
* (lstrlenW(szStaticLocalMachineName) + lstrlenW(szFullPathBuffer) + 3);
pLocalCounterPath = (PPDHI_COUNTER_PATH) G_ALLOC(dwSize);
if (pLocalCounterPath == NULL) {
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
}
else {
// 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
szString = (pCounterPathElements != NULL) ? ((LPWSTR) & pCounterPathElements[1]) : (NULL);
if (pLocalCounterPath->szMachineName != NULL) {
dwString = lstrlenW(pLocalCounterPath->szMachineName) + 1;
if (szString != NULL && dwString * sizeof(WCHAR) + dwUsed <= dwBufferSize) {
pCounterPathElements->szMachineName = szString;
StringCbCopyW(szString, dwBufferSize - dwUsed, pLocalCounterPath->szMachineName);
szString += dwString;
}
else {
bMoreData = TRUE;
pCounterPathElements->szMachineName = NULL;
szString = NULL;
}
dwUsed += (dwString * sizeof(WCHAR));
// 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) {
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,
& 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,
& pThisClass);
if (pdhStatus == ERROR_SUCCESS) {
szSrc = wszTempBuffer;
}
}
if (pdhStatus == ERROR_SUCCESS) {
dwString = lstrlenW(szSrc) + 1;
if (szString != NULL && dwString * sizeof(WCHAR) + dwUsed <= dwBufferSize) {
pCounterPathElements->szObjectName = szString;
StringCbCopyW(szString, dwBufferSize - dwUsed, szSrc);
szString += dwString;
}
else {
bMoreData = TRUE;
pCounterPathElements->szObjectName = NULL;
szString = NULL;
}
dwUsed += (dwString * sizeof(WCHAR));
}
G_FREE(wszTempBuffer);
wszTempBuffer = NULL;
}
else {
pCounterPathElements->szObjectName = NULL;
}
}
if (pdhStatus == ERROR_SUCCESS) {
if (pLocalCounterPath->szInstanceName != NULL) {
dwString = lstrlenW(pLocalCounterPath->szInstanceName) + 1;
if (szString != NULL && dwString * sizeof(WCHAR) + dwUsed <= dwBufferSize) {
pCounterPathElements->szInstanceName = szString;
StringCbCopyW(szString, dwBufferSize - dwUsed, pLocalCounterPath->szInstanceName);
szString += dwString;
}
else {
bMoreData = TRUE;
pCounterPathElements->szInstanceName = NULL;
szString = NULL;
}
dwUsed += (dwString * sizeof(WCHAR));
if (pLocalCounterPath->szParentName != NULL) {
dwString = lstrlenW(pLocalCounterPath->szParentName) + 1;
if (szString != NULL && dwString * sizeof(WCHAR) + dwUsed <= dwBufferSize) {
pCounterPathElements->szParentInstance = szString;
StringCbCopyW(szString, dwBufferSize - dwUsed, pLocalCounterPath->szParentName);
szString += dwString;
}
else {
bMoreData = TRUE;
pCounterPathElements->szParentInstance = NULL;
szString = NULL;
}
dwUsed += (dwString * sizeof(WCHAR));
}
else {
pCounterPathElements->szParentInstance = NULL;
}
pCounterPathElements->dwInstanceIndex = pLocalCounterPath->dwIndex;
}
else {
pCounterPathElements->szInstanceName = NULL;
pCounterPathElements->szParentInstance = NULL;
pCounterPathElements->dwInstanceIndex = (DWORD) PERF_NO_UNIQUE_ID;
}
}
if (pdhStatus == ERROR_SUCCESS) {
if (pLocalCounterPath->szCounterName != NULL) {
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);
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);
if (pdhStatus == ERROR_SUCCESS) {
szSrc = wszTempBuffer;
}
}
dwString = lstrlenW(szSrc) + 1;
if (szString != NULL && dwString * sizeof(WCHAR) + dwUsed <= dwBufferSize) {
pCounterPathElements->szCounterName = szString;
StringCbCopyW(szString, dwBufferSize - dwUsed, szSrc);
szString += dwString;
}
else {
bMoreData = TRUE;
pCounterPathElements->szCounterName = NULL;
szString = NULL;
}
dwUsed += (dwString * sizeof(WCHAR));
}
else {
pCounterPathElements->szCounterName = NULL;
}
}
if (pdhStatus == ERROR_SUCCESS) {
* pdwBufferSize = dwUsed;
if (bMoreData) pdhStatus = PDH_MORE_DATA;
}
}
else {
// unable to read path
pdhStatus = PDH_INVALID_PATH;
}
// Cleanup pThisServer if used
if (NULL != pThisServer) {
if (pdhStatus == ERROR_SUCCESS) {
pdhStatus = PdhiDisconnectWbemServer(pThisServer);
}
else {
// don't trash the return status
PdhiDisconnectWbemServer(pThisServer);
}
}
}
// CoUninitialize if necessary
if (fCoInitialized) {
PdhiCoUninitialize();
}
G_FREE(pLocalCounterPath);
G_FREE(wszTempBuffer);
return pdhStatus;
}
PDH_FUNCTION
PdhiDecodeWbemPathA(
LPCSTR szFullPathBuffer,
PPDH_COUNTER_PATH_ELEMENTS_A pCounterPathElements,
LPDWORD pdwBufferSize,
LANGID LangId,
DWORD dwFlags
)
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
LPWSTR wszWidePath = NULL;
PPDH_COUNTER_PATH_ELEMENTS_W pWideElements = NULL;
DWORD dwBufferSize;
DWORD dwSize;
DWORD dwDest = 0;
LONG lSizeRemaining;
LPSTR szNextString;
dwBufferSize = * pdwBufferSize;
wszWidePath = PdhiMultiByteToWideChar(_getmbcp(), (LPSTR) szFullPathBuffer);
if (wszWidePath == NULL) {
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
}
if (pdhStatus == ERROR_SUCCESS) {
// compute size of temp element buffer
if (dwBufferSize > sizeof(PDH_COUNTER_PATH_ELEMENTS_A)) {
lSizeRemaining = dwBufferSize - sizeof(PDH_COUNTER_PATH_ELEMENTS_A);
}
else {
lSizeRemaining = 0;
}
if (pCounterPathElements != NULL) {
dwSize = sizeof(PDH_COUNTER_PATH_ELEMENTS_W)
+ 2 * sizeof(WCHAR) * (lstrlenW(szStaticLocalMachineName) + lstrlenA(szFullPathBuffer) + 3);
pWideElements = (PDH_COUNTER_PATH_ELEMENTS_W *) G_ALLOC(dwSize);
if (pWideElements == NULL) {
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
}
}
else {
pWideElements = NULL;
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
if (pdhStatus == ERROR_SUCCESS) {
// convert path to Wide
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
}
G_FREE(pWideElements);
G_FREE(wszWidePath);
return pdhStatus;
}
BOOL
WbemInitCounter(
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;
LPWSTR szBasePropertyName = NULL;
DWORD dwBasePropertyName;
LPWSTR szFreqPropertyName = NULL;
DWORD dwFreqPropertyName;
LPWSTR szWbemItemPath = NULL;
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
dwBasePropertyName = (DWORD) lstrlenW(pCounter->szFullName) + (DWORD) lstrlenW(cszBaseSuffix);
if (dwBasePropertyName < (DWORD) lstrlenW(cszTimestampPerfTime)) {
dwBasePropertyName = (DWORD) lstrlenW(cszTimestampPerfTime);
}
if (dwBasePropertyName < (DWORD) lstrlenW(cszTimestampSys100Ns)) {
dwBasePropertyName = (DWORD) lstrlenW(cszTimestampSys100Ns);
}
if (dwBasePropertyName < (DWORD) lstrlenW(cszTimestampObject)) {
dwBasePropertyName = (DWORD) lstrlenW(cszTimestampObject);
}
szBasePropertyName = (LPWSTR) G_ALLOC((dwBasePropertyName + 1) * sizeof(WCHAR));
dwFreqPropertyName = (DWORD) lstrlenW(cszFrequencyPerfTime);
if (dwFreqPropertyName < (DWORD) lstrlenW(cszFrequencySys100Ns)) {
dwFreqPropertyName = (DWORD) lstrlenW(cszFrequencySys100Ns);
}
if (dwFreqPropertyName < (DWORD) lstrlenW(cszFrequencyObject)) {
dwFreqPropertyName = (DWORD) lstrlenW(cszFrequencyObject);
}
szFreqPropertyName = (LPWSTR) G_ALLOC((dwFreqPropertyName + 1) * sizeof(WCHAR));
if (szBasePropertyName == NULL || szFreqPropertyName == NULL) {
dwLastError = PDH_MEMORY_ALLOCATION_FAILURE;
bReturn = FALSE;
}
// make sure the query has a refresher started already
if (bReturn && 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) {
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) {
pCounterInList = pCounter->pOwner->pCounterListHead;
if (pCounterInList == NULL) {
// then there are no entries to search so continue
}
else {
do {
// check for matching machine name
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) {
bMatchFound = FALSE;
if (pCounter->pCounterPath->szParentName == NULL
&& pCounterInList->pCounterPath->szParentName == NULL) {
bMatchFound = TRUE;
}
else if (pCounter->pCounterPath->szParentName != NULL
&& pCounterInList->pCounterPath->szParentName != NULL
&& lstrcmpiW(pCounterInList->pCounterPath->szParentName,
pCounter->pCounterPath->szParentName) == 0) {
bMatchFound = TRUE;
}
if (bMatchFound) {
bMatchFound = FALSE;
if (pCounter->pCounterPath->dwIndex == pCounterInList->pCounterPath->dwIndex) {
bMatchFound = TRUE;
}
else if (pCounter->pCounterPath->dwIndex == 0
|| pCounter->pCounterPath->dwIndex == PERF_NO_UNIQUE_ID) {
if (pCounterInList->pCounterPath->dwIndex == 0
|| pCounterInList->pCounterPath->dwIndex == PERF_NO_UNIQUE_ID) {
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;
}
}
}
}
}
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 {
// 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;
}
PdhiSysFreeString(& bsPropName);
}
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);
// get counter type field
// first get the property qualifiers
bsPropName = SysAllocString(pPathElem->szCounterName);
if (bsPropName) {
hRes = pCounter->pWbemObject->GetPropertyQualifierSet(bsPropName, & pQualSet);
PdhiSysFreeString(& bsPropName);
}
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
StringCchPrintfW(szBasePropertyName, dwBasePropertyName + 1, L"%ws%ws",
pPathElem->szCounterName, cszBaseSuffix);
// get the handle to the denominator
hRes = pCounter->pWbemAccess->GetPropertyHandle(szBasePropertyName,
& pCounter->lDenItemType,
& pCounter->lDenItemHandle);
}
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
StringCchCopyW(szBasePropertyName, dwBasePropertyName + 1, cszTimestampPerfTime);
StringCchCopyW(szFreqPropertyName, dwFreqPropertyName + 1, cszFrequencyPerfTime);
}
else if ((pCounter->plCounterInfo.dwCounterType & PERF_TIMER_FIELD) == PERF_TIMER_100NS) {
StringCchCopyW(szBasePropertyName, dwBasePropertyName + 1, cszTimestampSys100Ns);
StringCchCopyW(szFreqPropertyName, dwFreqPropertyName + 1, cszFrequencySys100Ns);
}
else if ((pCounter->plCounterInfo.dwCounterType & PERF_TIMER_FIELD) == PERF_OBJECT_TIMER) {
StringCchCopyW(szBasePropertyName, dwBasePropertyName + 1, cszTimestampObject);
StringCchCopyW(szFreqPropertyName, dwFreqPropertyName + 1, cszFrequencyObject);
}
// get the handle to the denominator
hRes = pCounter->pWbemAccess->GetPropertyHandle(szBasePropertyName,
& pCounter->lDenItemType,
& pCounter->lDenItemHandle);
// get the handle to the frequency
hRes = pCounter->pWbemAccess->GetPropertyHandle(szFreqPropertyName,
& pCounter->lFreqItemType,
& pCounter->lFreqItemHandle);
}
// 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
}
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;
}
}
G_FREE(pPathElem);
G_FREE(szWbemItemPath);
G_FREE(szBasePropertyName);
G_FREE(szFreqPropertyName);
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(
PPDHI_COUNTER pCounter,
FILETIME * pTimeStamp
)
{
DWORD LocalCStatus = 0;
DWORD LocalCType = 0;
ULONGLONG llValue;
DWORD dwValue;
BOOL bReturn = TRUE;
// 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
pCounter->pWbemAccess->ReadDWORD(pCounter->lNumItemHandle, & dwValue);
pCounter->ThisValue.FirstValue = (LONGLONG) dwValue;
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) {
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
pCounter->pWbemAccess->ReadQWORD(pCounter->lNumItemHandle, & llValue);
pCounter->ThisValue.FirstValue = (LONGLONG) llValue;
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) {
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
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
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
pCounter->pWbemAccess->ReadDWORD(pCounter->lNumItemHandle, & dwValue);
pCounter->ThisValue.FirstValue = (LONGLONG) dwValue;
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
pCounter->pWbemAccess->ReadQWORD(pCounter->lNumItemHandle, & llValue);
pCounter->ThisValue.FirstValue = (LONGLONG) llValue;
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
pCounter->pWbemAccess->ReadQWORD(pCounter->lNumItemHandle, & llValue);
pCounter->ThisValue.FirstValue = (LONGLONG) llValue;
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) {
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(
PPDHI_COUNTER pCounter,
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;
IWbemObjectAccess ** pWbemInstances = NULL;
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)) {
// get count of instances in enumerator
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 = (IWbemObjectAccess **) G_ALLOC(lNumInstances * sizeof(IWbemObjectAccess *));
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) + (PDH_WMI_STR_SIZE * 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);
if (pCounter->lNameHandle != -1) {
hRes = pWbemAccess->ReadPropertyValue(pCounter->lNameHandle,
lAvailableSize,
& lReturnSize,
(LPBYTE) szNextNameString);
}
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
pWbemAccess->ReadDWORD(pCounter->lNumItemHandle, & dwValue);
pThisItem->FirstValue = (LONGLONG) dwValue;
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) {
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
pWbemAccess->ReadQWORD(pCounter->lNumItemHandle, & llValue);
pThisItem->FirstValue = (LONGLONG) llValue;
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) {
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
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
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
pWbemAccess->ReadDWORD(pCounter->lNumItemHandle, & dwValue);
pThisItem->FirstValue = (LONGLONG) dwValue;
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
pCounter->pWbemAccess->ReadQWORD(pCounter->lNumItemHandle, & llValue);
pCounter->ThisValue.FirstValue = (LONGLONG) llValue;
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
pWbemAccess->ReadQWORD(pCounter->lNumItemHandle, & llValue);
pThisItem->FirstValue = (LONGLONG) llValue;
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) {
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
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;
}
}
}
}
G_FREE(pWbemInstances);
return bReturn;
}
LONG
GetQueryWbemData(
PPDHI_QUERY pQuery,
LONGLONG * pllTimeStamp
)
{
FILETIME GmtFileTime;
FILETIME LocFileTime;
LONGLONG llTimeStamp = 0;
HRESULT hRes = S_OK;
LONG lRetStatus = ERROR_SUCCESS;
PPDHI_COUNTER pCounter;
PDH_STATUS pdhStatus;
// refresh Wbem Refresher
if (bDontRefresh) {
lRetStatus = ERROR_BUSY;
}
else 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_NO_DATA;
}
// get timestamp for this counter
GetSystemTimeAsFileTime(& GmtFileTime);
FileTimeToLocalFileTime(& GmtFileTime, & LocFileTime);
llTimeStamp = MAKELONGLONG(LocFileTime.dwLowDateTime, LocFileTime.dwHighDateTime);
pCounter = pQuery->pCounterListHead;
if (pCounter == NULL) {
if (lRetStatus == ERROR_SUCCESS) lRetStatus = PDH_NO_DATA;
}
else {
do {
if (lRetStatus == ERROR_SUCCESS) {
// now update the counters using this new data
if (pCounter->dwFlags & PDHIC_MULTI_INSTANCE) {
pdhStatus = UpdateWbemMultiInstanceCounterValue(pCounter, (FILETIME *) & llTimeStamp);
}
else {
// update single instance counter values
pdhStatus = UpdateWbemCounterValue(pCounter, (FILETIME *) & llTimeStamp);
}
}
else if (pCounter->dwFlags & PDHIC_MULTI_INSTANCE) {
if (pCounter->pThisRawItemList != NULL) {
if (pCounter->pLastRawItemList != NULL
&& pCounter->pLastRawItemList != pCounter->pThisRawItemList) {
G_FREE(pCounter->pLastRawItemList);
}
pCounter->pLastRawItemList = pCounter->pThisRawItemList;
pCounter->pThisRawItemList = NULL;
}
pCounter->pThisRawItemList = (PPDHI_RAW_COUNTER_ITEM_BLOCK)
G_ALLOC(sizeof(PDHI_RAW_COUNTER_ITEM_BLOCK));
if (pCounter->pThisRawItemList != NULL) {
pCounter->pThisRawItemList->dwLength = sizeof(PDHI_RAW_COUNTER_ITEM_BLOCK);
pCounter->pThisRawItemList->dwItemCount = 0;
pCounter->pThisRawItemList->CStatus = PDH_WBEM_ERROR;
pCounter->pThisRawItemList->TimeStamp.dwLowDateTime = LODWORD(llTimeStamp);
pCounter->pThisRawItemList->TimeStamp.dwHighDateTime = HIDWORD(llTimeStamp);
}
}
else {
pCounter->LastValue = pCounter->ThisValue;
pCounter->ThisValue.CStatus = PDH_WBEM_ERROR;
pCounter->ThisValue.MultiCount = 1;
pCounter->ThisValue.FirstValue = 0;
pCounter->ThisValue.SecondValue = 0;
pCounter->ThisValue.TimeStamp.dwLowDateTime = LODWORD(llTimeStamp);
pCounter->ThisValue.TimeStamp.dwHighDateTime = HIDWORD(llTimeStamp);
}
pCounter = pCounter->next.flink;
}
while (pCounter != pQuery->pCounterListHead);
}
if (lRetStatus == ERROR_SUCCESS) {
* 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) {
sc = pInterface->QueryInterface(IID_IClientSecurity, (void **) &pCliSec);
if (sc == S_OK) {
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;
}