812 lines
22 KiB
C++
812 lines
22 KiB
C++
/*++
|
|
|
|
Copyright (C) 1998-1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
smctrqry.cpp
|
|
|
|
Abstract:
|
|
|
|
Implementation of the counter log query class.
|
|
|
|
--*/
|
|
|
|
#include "Stdafx.h"
|
|
#include <pdhp.h> // for MIN_TIME_VALUE, MAX_TIME_VALUE
|
|
#include <pdhmsg.h>
|
|
#include "smctrqry.h"
|
|
|
|
USE_HANDLE_MACROS("SMLOGCFG(smctrqry.cpp)");
|
|
|
|
//
|
|
// Constructor
|
|
CSmCounterLogQuery::CSmCounterLogQuery( CSmLogService* pLogService )
|
|
: CSmLogQuery( pLogService ),
|
|
m_dwCounterListLength ( 0 ),
|
|
m_szNextCounter ( NULL ),
|
|
mr_szCounterList ( NULL )
|
|
{
|
|
// initialize member variables
|
|
memset (&mr_stiSampleInterval, 0, sizeof(mr_stiSampleInterval));
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Destructor
|
|
CSmCounterLogQuery::~CSmCounterLogQuery()
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Open function. either opens an existing log query entry
|
|
// or creates a new one
|
|
//
|
|
DWORD
|
|
CSmCounterLogQuery::Open ( const CString& rstrName, HKEY hKeyQuery, BOOL bReadOnly)
|
|
{
|
|
DWORD dwStatus = ERROR_SUCCESS;
|
|
|
|
ASSERT ( SLQ_COUNTER_LOG == GetLogType() );
|
|
|
|
dwStatus = CSmLogQuery::Open ( rstrName, hKeyQuery, bReadOnly );
|
|
|
|
return dwStatus;
|
|
}
|
|
|
|
//
|
|
// Close Function
|
|
// closes registry handles and frees allocated memory
|
|
//
|
|
DWORD
|
|
CSmCounterLogQuery::Close ()
|
|
{
|
|
DWORD dwStatus;
|
|
LOCALTRACE (L"Closing Query\n");
|
|
|
|
if (mr_szCounterList != NULL) {
|
|
delete (mr_szCounterList);
|
|
mr_szCounterList = NULL;
|
|
}
|
|
|
|
dwStatus = CSmLogQuery::Close();
|
|
|
|
return dwStatus;
|
|
}
|
|
|
|
|
|
//
|
|
// UpdateRegistry function.
|
|
// copies the current settings to the registry where they
|
|
// are read by the log service
|
|
//
|
|
DWORD
|
|
CSmCounterLogQuery::UpdateRegistry()
|
|
{
|
|
DWORD dwStatus = ERROR_SUCCESS;
|
|
DWORD dwBufferSize;
|
|
LPTSTR szNewCounterList = NULL;
|
|
|
|
if ( IsModifiable() ) {
|
|
|
|
dwBufferSize = 0;
|
|
//
|
|
// Translate the counter list into English
|
|
//
|
|
dwStatus = TranslateMSZCounterList(mr_szCounterList,
|
|
NULL,
|
|
&dwBufferSize,
|
|
FALSE);
|
|
if (dwStatus == ERROR_NOT_ENOUGH_MEMORY) {
|
|
szNewCounterList = (LPTSTR) new char [dwBufferSize];
|
|
if (szNewCounterList != NULL) {
|
|
dwStatus = TranslateMSZCounterList(mr_szCounterList,
|
|
szNewCounterList,
|
|
&dwBufferSize,
|
|
FALSE);
|
|
}
|
|
}
|
|
|
|
if (dwStatus == ERROR_SUCCESS && szNewCounterList != NULL) {
|
|
dwStatus = WriteRegistryStringValue (
|
|
m_hKeyQuery,
|
|
IDS_REG_COUNTER_LIST,
|
|
REG_MULTI_SZ,
|
|
szNewCounterList,
|
|
&dwBufferSize);
|
|
}
|
|
else {
|
|
dwBufferSize = m_dwCounterListLength * sizeof(TCHAR);
|
|
dwStatus = WriteRegistryStringValue (
|
|
m_hKeyQuery,
|
|
IDS_REG_COUNTER_LIST,
|
|
REG_MULTI_SZ,
|
|
mr_szCounterList,
|
|
&dwBufferSize);
|
|
}
|
|
|
|
// Schedule
|
|
|
|
if ( ERROR_SUCCESS == dwStatus ) {
|
|
dwStatus = WriteRegistrySlqTime (
|
|
m_hKeyQuery,
|
|
IDS_REG_SAMPLE_INTERVAL,
|
|
&mr_stiSampleInterval);
|
|
}
|
|
|
|
if ( ERROR_SUCCESS == dwStatus ) {
|
|
dwStatus = CSmLogQuery::UpdateRegistry ();
|
|
}
|
|
|
|
} else {
|
|
dwStatus = ERROR_ACCESS_DENIED;
|
|
}
|
|
|
|
return dwStatus;
|
|
}
|
|
|
|
//
|
|
// SyncWithRegistry()
|
|
// reads the current values for this query from the registry
|
|
// and reloads the internal values to match
|
|
//
|
|
//
|
|
DWORD
|
|
CSmCounterLogQuery::SyncWithRegistry()
|
|
{
|
|
DWORD dwBufferSize = 0;
|
|
DWORD dwStatus = ERROR_SUCCESS;
|
|
SLQ_TIME_INFO stiDefault;
|
|
LPTSTR szNewCounterList;
|
|
|
|
ASSERT (m_hKeyQuery != NULL);
|
|
|
|
// load counter string list
|
|
|
|
// Get Counter List
|
|
dwStatus = ReadRegistryStringValue (
|
|
m_hKeyQuery,
|
|
IDS_REG_COUNTER_LIST,
|
|
NULL,
|
|
&mr_szCounterList,
|
|
&dwBufferSize);
|
|
|
|
if (dwStatus != ERROR_SUCCESS) {
|
|
m_szNextCounter = NULL; //re-initialize
|
|
m_dwCounterListLength = 0;
|
|
} else {
|
|
m_dwCounterListLength = dwBufferSize / sizeof(TCHAR);
|
|
//
|
|
// Translate the counter list into Locale
|
|
//
|
|
dwBufferSize = 0;
|
|
dwStatus = TranslateMSZCounterList(
|
|
mr_szCounterList,
|
|
NULL,
|
|
&dwBufferSize,
|
|
TRUE);
|
|
|
|
if (dwStatus == ERROR_NOT_ENOUGH_MEMORY) {
|
|
|
|
szNewCounterList = (LPTSTR) new char [dwBufferSize];
|
|
|
|
if (szNewCounterList != NULL) {
|
|
//
|
|
// Translate the counter list into Locale
|
|
//
|
|
dwStatus = TranslateMSZCounterList(
|
|
mr_szCounterList,
|
|
szNewCounterList,
|
|
&dwBufferSize,
|
|
TRUE);
|
|
|
|
if (dwStatus == ERROR_SUCCESS) {
|
|
m_dwCounterListLength = dwBufferSize / sizeof(TCHAR);
|
|
//
|
|
// Remove the old
|
|
//
|
|
delete (mr_szCounterList);
|
|
m_szNextCounter = NULL;
|
|
mr_szCounterList = szNewCounterList;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Schedule
|
|
|
|
stiDefault.wTimeType = SLQ_TT_TTYPE_SAMPLE;
|
|
stiDefault.dwAutoMode = SLQ_AUTO_MODE_AFTER;
|
|
stiDefault.wDataType = SLQ_TT_DTYPE_UNITS;
|
|
stiDefault.dwUnitType = SLQ_TT_UTYPE_SECONDS;
|
|
stiDefault.dwValue = 15;
|
|
|
|
dwStatus = ReadRegistrySlqTime (
|
|
m_hKeyQuery,
|
|
IDS_REG_SAMPLE_INTERVAL,
|
|
&stiDefault,
|
|
&mr_stiSampleInterval);
|
|
ASSERT (dwStatus == ERROR_SUCCESS);
|
|
|
|
// Call parent class last to update shared values.
|
|
|
|
dwStatus = CSmLogQuery::SyncWithRegistry();
|
|
ASSERT (dwStatus == ERROR_SUCCESS);
|
|
|
|
return dwStatus;
|
|
}
|
|
|
|
//
|
|
// Get first counter in counter list
|
|
//
|
|
LPCWSTR
|
|
CSmCounterLogQuery::GetFirstCounter()
|
|
{
|
|
LPTSTR szReturn;
|
|
|
|
szReturn = mr_szCounterList;
|
|
if (szReturn != NULL) {
|
|
if (*szReturn == 0) {
|
|
// then it's an empty string
|
|
szReturn = NULL;
|
|
m_szNextCounter = NULL;
|
|
} else {
|
|
m_szNextCounter = szReturn + lstrlen(szReturn) + 1;
|
|
if (*m_szNextCounter == 0) {
|
|
// end of list reached so set pointer to NULL
|
|
m_szNextCounter = NULL;
|
|
}
|
|
}
|
|
} else {
|
|
// no buffer allocated yet
|
|
m_szNextCounter = NULL;
|
|
}
|
|
return (LPCWSTR)szReturn;
|
|
}
|
|
|
|
//
|
|
// Get next counter in counter list
|
|
// NULL pointer means no more counters in list
|
|
//
|
|
LPCWSTR
|
|
CSmCounterLogQuery::GetNextCounter()
|
|
{
|
|
LPTSTR szReturn;
|
|
szReturn = m_szNextCounter;
|
|
|
|
if (m_szNextCounter != NULL) {
|
|
m_szNextCounter += lstrlen(szReturn) + 1;
|
|
if (*m_szNextCounter == 0) {
|
|
// end of list reached so set pointer to NULL
|
|
m_szNextCounter = NULL;
|
|
}
|
|
} else {
|
|
// already at the end of the list so nothing to do
|
|
}
|
|
|
|
return (LPCWSTR)szReturn;
|
|
}
|
|
|
|
//
|
|
// clear out the counter list
|
|
//
|
|
VOID
|
|
CSmCounterLogQuery::ResetCounterList()
|
|
{
|
|
if (mr_szCounterList != NULL) {
|
|
delete (mr_szCounterList);
|
|
m_szNextCounter = NULL;
|
|
mr_szCounterList = NULL;
|
|
}
|
|
|
|
m_dwCounterListLength = sizeof(WCHAR); // sizeof MSZ Null
|
|
try {
|
|
mr_szCounterList = new WCHAR [m_dwCounterListLength];
|
|
mr_szCounterList[0] = 0;
|
|
} catch ( ... ) {
|
|
m_dwCounterListLength = 0;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Add this counter string to the internal list
|
|
//
|
|
BOOL
|
|
CSmCounterLogQuery::AddCounter(LPCWSTR szCounterPath)
|
|
{
|
|
DWORD dwNewSize;
|
|
LPTSTR szNewString;
|
|
LPTSTR szNextString;
|
|
|
|
ASSERT (szCounterPath != NULL);
|
|
|
|
if (szCounterPath == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
dwNewSize = lstrlen(szCounterPath) + 1;
|
|
|
|
if (m_dwCounterListLength <= 2) {
|
|
dwNewSize += 1; // add room for the MSZ null
|
|
// then this is the first string to go in the list
|
|
try {
|
|
szNewString = new TCHAR [dwNewSize];
|
|
} catch ( ... ) {
|
|
return FALSE; // leave now
|
|
}
|
|
szNextString = szNewString;
|
|
} else {
|
|
dwNewSize += m_dwCounterListLength;
|
|
// this is the nth string to go in the list
|
|
try {
|
|
szNewString = new TCHAR [dwNewSize];
|
|
} catch ( ... ) {
|
|
return FALSE; // leave now
|
|
}
|
|
memcpy (szNewString, mr_szCounterList,
|
|
(m_dwCounterListLength * sizeof(TCHAR)));
|
|
szNextString = szNewString;
|
|
szNextString += m_dwCounterListLength - 1;
|
|
}
|
|
lstrcpyW (szNextString, szCounterPath);
|
|
szNextString = szNewString;
|
|
szNextString += dwNewSize - 1;
|
|
*szNextString = 0; // MSZ Null
|
|
|
|
if (mr_szCounterList != NULL) {
|
|
delete (mr_szCounterList);
|
|
}
|
|
mr_szCounterList = szNewString;
|
|
m_szNextCounter = szNewString;
|
|
m_dwCounterListLength = dwNewSize;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
CSmCounterLogQuery::GetLogTime(PSLQ_TIME_INFO pTimeInfo, DWORD dwFlags)
|
|
{
|
|
BOOL bStatus;
|
|
|
|
ASSERT ( ( SLQ_TT_TTYPE_START == dwFlags )
|
|
|| ( SLQ_TT_TTYPE_STOP == dwFlags )
|
|
|| ( SLQ_TT_TTYPE_RESTART == dwFlags )
|
|
|| ( SLQ_TT_TTYPE_SAMPLE == dwFlags ) );
|
|
|
|
bStatus = CSmLogQuery::GetLogTime( pTimeInfo, dwFlags );
|
|
|
|
return bStatus;
|
|
}
|
|
|
|
BOOL
|
|
CSmCounterLogQuery::SetLogTime(PSLQ_TIME_INFO pTimeInfo, const DWORD dwFlags)
|
|
{
|
|
BOOL bStatus;
|
|
|
|
ASSERT ( ( SLQ_TT_TTYPE_START == dwFlags )
|
|
|| ( SLQ_TT_TTYPE_STOP == dwFlags )
|
|
|| ( SLQ_TT_TTYPE_RESTART == dwFlags )
|
|
|| ( SLQ_TT_TTYPE_SAMPLE == dwFlags ) );
|
|
|
|
bStatus = CSmLogQuery::SetLogTime( pTimeInfo, dwFlags );
|
|
|
|
return bStatus;
|
|
}
|
|
|
|
BOOL
|
|
CSmCounterLogQuery::GetDefaultLogTime(SLQ_TIME_INFO& rTimeInfo, DWORD dwFlags)
|
|
{
|
|
ASSERT ( ( SLQ_TT_TTYPE_START == dwFlags )
|
|
|| ( SLQ_TT_TTYPE_STOP == dwFlags ) );
|
|
|
|
rTimeInfo.wTimeType = (WORD)dwFlags;
|
|
rTimeInfo.wDataType = SLQ_TT_DTYPE_DATETIME;
|
|
|
|
if ( SLQ_TT_TTYPE_START == dwFlags ) {
|
|
SYSTEMTIME stLocalTime;
|
|
FILETIME ftLocalTime;
|
|
|
|
// Milliseconds set to 0 for Schedule times
|
|
GetLocalTime (&stLocalTime);
|
|
stLocalTime.wMilliseconds = 0;
|
|
SystemTimeToFileTime (&stLocalTime, &ftLocalTime);
|
|
|
|
rTimeInfo.dwAutoMode = SLQ_AUTO_MODE_AT;
|
|
rTimeInfo.llDateTime = *(LONGLONG *)&ftLocalTime;
|
|
} else {
|
|
// Default stop values
|
|
rTimeInfo.dwAutoMode = SLQ_AUTO_MODE_NONE;
|
|
rTimeInfo.llDateTime = MAX_TIME_VALUE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
DWORD
|
|
CSmCounterLogQuery::GetLogType()
|
|
{
|
|
return ( SLQ_COUNTER_LOG );
|
|
}
|
|
|
|
HRESULT
|
|
CSmCounterLogQuery::LoadCountersFromPropertyBag (
|
|
IPropertyBag* pPropBag,
|
|
IErrorLog* pIErrorLog )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
PDH_STATUS pdhStatus;
|
|
CString strParamName;
|
|
DWORD dwCount = 0;
|
|
DWORD dwIndex;
|
|
LPTSTR szLocaleBuf = NULL;
|
|
DWORD dwLocaleBufSize = 0;
|
|
|
|
hr = DwordFromPropertyBag (
|
|
pPropBag,
|
|
pIErrorLog,
|
|
IDS_HTML_SYSMON_COUNTERCOUNT,
|
|
0,
|
|
dwCount);
|
|
|
|
for ( dwIndex = 1; dwIndex <= dwCount; dwIndex++ ) {
|
|
LPTSTR szCounterPath = NULL;
|
|
LPTSTR pszPath = NULL;
|
|
DWORD dwBufSize = 0;
|
|
LPTSTR pNewBuf;
|
|
|
|
strParamName.Format ( IDS_HTML_SYSMON_COUNTERPATH, dwIndex );
|
|
hr = StringFromPropertyBag (
|
|
pPropBag,
|
|
pIErrorLog,
|
|
strParamName,
|
|
L"",
|
|
&szCounterPath,
|
|
&dwBufSize );
|
|
|
|
pszPath = szCounterPath;
|
|
|
|
if (dwBufSize > sizeof(TCHAR)) {
|
|
//
|
|
// Initialize the locale path buffer
|
|
//
|
|
if (dwLocaleBufSize == 0) {
|
|
dwLocaleBufSize = (MAX_PATH + 1) * sizeof(TCHAR);
|
|
szLocaleBuf = (LPTSTR) G_ALLOC(dwLocaleBufSize);
|
|
if (szLocaleBuf == NULL) {
|
|
dwLocaleBufSize = 0;
|
|
}
|
|
}
|
|
|
|
if (szLocaleBuf != NULL) {
|
|
//
|
|
// Translate counter name from English to Localization
|
|
//
|
|
dwBufSize = dwLocaleBufSize;
|
|
|
|
pdhStatus = PdhTranslateLocaleCounter(
|
|
szCounterPath,
|
|
szLocaleBuf,
|
|
&dwBufSize);
|
|
|
|
if (pdhStatus == PDH_MORE_DATA) {
|
|
pNewBuf = (LPTSTR)G_REALLOC(szLocaleBuf, dwBufSize);
|
|
if (pNewBuf != NULL) {
|
|
szLocaleBuf = pNewBuf;
|
|
dwLocaleBufSize = dwBufSize;
|
|
|
|
pdhStatus = PdhTranslateLocaleCounter(
|
|
szCounterPath,
|
|
szLocaleBuf,
|
|
&dwBufSize);
|
|
}
|
|
}
|
|
|
|
if (pdhStatus == ERROR_SUCCESS) {
|
|
pszPath = szLocaleBuf;
|
|
}
|
|
}
|
|
|
|
AddCounter ( pszPath );
|
|
}
|
|
|
|
delete (szCounterPath);
|
|
}
|
|
|
|
if (szLocaleBuf != NULL) {
|
|
G_FREE(szLocaleBuf);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CSmCounterLogQuery::LoadFromPropertyBag (
|
|
IPropertyBag* pPropBag,
|
|
IErrorLog* pIErrorLog )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
SLQ_TIME_INFO stiDefault;
|
|
|
|
// Continue even if error, using defaults for missing values.
|
|
hr = LoadCountersFromPropertyBag( pPropBag, pIErrorLog );
|
|
|
|
stiDefault.wTimeType = SLQ_TT_TTYPE_SAMPLE;
|
|
stiDefault.dwAutoMode = SLQ_AUTO_MODE_AFTER;
|
|
stiDefault.wDataType = SLQ_TT_DTYPE_UNITS;
|
|
stiDefault.dwUnitType = SLQ_TT_UTYPE_SECONDS;
|
|
stiDefault.dwValue = 15;
|
|
|
|
hr = SlqTimeFromPropertyBag (
|
|
pPropBag,
|
|
pIErrorLog,
|
|
SLQ_TT_TTYPE_SAMPLE,
|
|
&stiDefault,
|
|
&mr_stiSampleInterval );
|
|
|
|
hr = CSmLogQuery::LoadFromPropertyBag( pPropBag, pIErrorLog );
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CSmCounterLogQuery::SaveCountersToPropertyBag (
|
|
IPropertyBag* pPropBag )
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
CString strParamName;
|
|
LPCTSTR pszCounterPath;
|
|
LPTSTR szEnglishBuf = NULL;
|
|
DWORD dwEnglishBufSize = 0;
|
|
LPCTSTR pszPath = NULL;
|
|
PDH_STATUS pdhStatus;
|
|
|
|
DWORD dwIndex = 0;
|
|
|
|
pszCounterPath = GetFirstCounter();
|
|
|
|
MFC_TRY
|
|
// Passing sz ( TCHAR[n] ) causes memory alloc, which might throw an exception
|
|
while ( NULL != pszCounterPath ) {
|
|
LPTSTR pNewBuf;
|
|
DWORD dwBufSize;
|
|
|
|
pszPath = pszCounterPath;
|
|
|
|
//
|
|
// Initialize the locale path buffer
|
|
//
|
|
if (dwEnglishBufSize == 0) {
|
|
dwEnglishBufSize = (MAX_PATH + 1) * sizeof(TCHAR);
|
|
szEnglishBuf = (LPTSTR) G_ALLOC(dwEnglishBufSize);
|
|
if (szEnglishBuf == NULL) {
|
|
dwEnglishBufSize = 0;
|
|
}
|
|
}
|
|
|
|
if (szEnglishBuf != NULL) {
|
|
//
|
|
// Translate counter name from Localization into English
|
|
//
|
|
dwBufSize = dwEnglishBufSize;
|
|
|
|
pdhStatus = PdhTranslate009Counter(
|
|
(LPTSTR)pszCounterPath,
|
|
szEnglishBuf,
|
|
&dwBufSize);
|
|
|
|
if (pdhStatus == PDH_MORE_DATA) {
|
|
pNewBuf = (LPTSTR)G_REALLOC(szEnglishBuf, dwBufSize);
|
|
if (pNewBuf != NULL) {
|
|
szEnglishBuf = pNewBuf;
|
|
dwEnglishBufSize = dwBufSize;
|
|
|
|
pdhStatus = PdhTranslate009Counter(
|
|
(LPTSTR)pszCounterPath,
|
|
szEnglishBuf,
|
|
&dwBufSize);
|
|
}
|
|
}
|
|
|
|
if (pdhStatus == ERROR_SUCCESS) {
|
|
pszPath = szEnglishBuf;
|
|
}
|
|
}
|
|
|
|
// Counter path count starts with 1.
|
|
strParamName.Format ( IDS_HTML_SYSMON_COUNTERPATH, ++dwIndex );
|
|
hr = StringToPropertyBag ( pPropBag, strParamName, pszPath );
|
|
|
|
pszCounterPath = GetNextCounter();
|
|
}
|
|
|
|
hr = DwordToPropertyBag ( pPropBag, IDS_HTML_SYSMON_COUNTERCOUNT, dwIndex );
|
|
MFC_CATCH_HR
|
|
|
|
if (szEnglishBuf != NULL) {
|
|
G_FREE(szEnglishBuf);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CSmCounterLogQuery::SaveToPropertyBag (
|
|
IPropertyBag* pPropBag,
|
|
BOOL fSaveAllProps )
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
|
|
hr = CSmLogQuery::SaveToPropertyBag( pPropBag, fSaveAllProps );
|
|
|
|
hr = SaveCountersToPropertyBag ( pPropBag );
|
|
|
|
hr = SlqTimeToPropertyBag ( pPropBag, SLQ_TT_TTYPE_SAMPLE, &mr_stiSampleInterval );
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CSmCounterLogQuery::TranslateMSZCounterList(
|
|
LPTSTR pszCounterList,
|
|
LPTSTR pBuffer,
|
|
LPDWORD pdwBufferSize,
|
|
BOOL bFlag
|
|
)
|
|
{
|
|
LPTSTR pTmpBuf = NULL;
|
|
DWORD dwTmpBufSize = 0;
|
|
DWORD dwSize = 0;
|
|
LPTSTR pNewBuf = NULL;
|
|
LPTSTR pszCounterPath = NULL;
|
|
LPTSTR pszCounterPathToAdd = NULL;
|
|
LPTSTR pNextStringPosition = NULL;
|
|
BOOL bNotEnoughBuffer = FALSE;
|
|
DWORD dwNewCounterListLen = 0;
|
|
DWORD dwCounterPathLen = 0;
|
|
PDH_STATUS Status = ERROR_SUCCESS;
|
|
|
|
if (pszCounterList == NULL || pdwBufferSize == NULL) {
|
|
|
|
Status = ERROR_INVALID_PARAMETER;
|
|
goto ErrorOut;
|
|
}
|
|
|
|
if (pBuffer == NULL || *pdwBufferSize == 0) {
|
|
bNotEnoughBuffer = TRUE;
|
|
}
|
|
|
|
//
|
|
// Probe parameters
|
|
//
|
|
__try {
|
|
if (* pdwBufferSize != 0 && pBuffer != NULL) {
|
|
*pBuffer = 0;
|
|
|
|
* (LPTSTR) ( ((LPBYTE) pBuffer)
|
|
+ ((* pdwBufferSize) - sizeof(*pBuffer)) ) = 0;
|
|
}
|
|
|
|
pszCounterPath = pszCounterList;
|
|
|
|
while (*pszCounterPath) {
|
|
pszCounterPathToAdd = pszCounterPath;
|
|
|
|
//
|
|
// Initialize the buffer used for translating counter path
|
|
// called only once
|
|
//
|
|
if (pTmpBuf == NULL) {
|
|
dwTmpBufSize = (MAX_PATH + 1) * sizeof(TCHAR);
|
|
pTmpBuf = (LPTSTR) G_ALLOC(dwTmpBufSize);
|
|
if (pTmpBuf == NULL) {
|
|
Status = ERROR_OUTOFMEMORY;
|
|
goto ErrorOut;
|
|
}
|
|
}
|
|
|
|
if (pTmpBuf != NULL) {
|
|
dwSize = dwTmpBufSize;
|
|
|
|
if (bFlag) {
|
|
Status = PdhTranslateLocaleCounter(
|
|
pszCounterPath,
|
|
pTmpBuf,
|
|
&dwSize);
|
|
}
|
|
else {
|
|
Status = PdhTranslate009Counter(
|
|
pszCounterPath,
|
|
pTmpBuf,
|
|
&dwSize);
|
|
}
|
|
|
|
if (Status == PDH_MORE_DATA) {
|
|
pNewBuf = (LPTSTR) G_REALLOC(pTmpBuf, dwSize);
|
|
if (pNewBuf == NULL) {
|
|
Status = ERROR_OUTOFMEMORY;
|
|
goto ErrorOut;
|
|
}
|
|
pTmpBuf = pNewBuf;
|
|
dwTmpBufSize = dwSize;
|
|
|
|
//
|
|
// Try second time
|
|
//
|
|
if (bFlag) {
|
|
Status = PdhTranslateLocaleCounter(
|
|
pszCounterPath,
|
|
pTmpBuf,
|
|
&dwSize);
|
|
}
|
|
else {
|
|
Status = PdhTranslate009Counter(
|
|
pszCounterPath,
|
|
pTmpBuf,
|
|
&dwSize);
|
|
}
|
|
}
|
|
|
|
if (Status == ERROR_SUCCESS) {
|
|
pszCounterPathToAdd = pTmpBuf;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Add the translated counter path(it is the original
|
|
// counter path if translation failed) to the new counter
|
|
// path list
|
|
//
|
|
|
|
dwCounterPathLen = lstrlen(pszCounterPathToAdd) + 1;
|
|
|
|
dwNewCounterListLen += dwCounterPathLen;
|
|
|
|
if (! bNotEnoughBuffer) {
|
|
if ( (dwNewCounterListLen + 1) * sizeof(TCHAR) <= *pdwBufferSize) {
|
|
//
|
|
// Set up the copy position
|
|
//
|
|
pNextStringPosition = pBuffer + dwNewCounterListLen - dwCounterPathLen;
|
|
lstrcpy(pNextStringPosition, pszCounterPathToAdd);
|
|
}
|
|
else {
|
|
bNotEnoughBuffer = TRUE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Continue processing next counter path
|
|
//
|
|
pszCounterPath += lstrlen(pszCounterPath) + 1;
|
|
}
|
|
|
|
dwNewCounterListLen ++;
|
|
if (! bNotEnoughBuffer) {
|
|
//
|
|
// Append the terminating 0
|
|
//
|
|
pBuffer[dwNewCounterListLen-1] = 0;
|
|
}
|
|
else {
|
|
Status = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
*pdwBufferSize = dwNewCounterListLen * sizeof(TCHAR);
|
|
|
|
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
|
Status = ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
ErrorOut:
|
|
if (pTmpBuf != NULL) {
|
|
G_FREE(pTmpBuf);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|