windows-nt/Source/XPSP1/NT/admin/snapin/smonlog/smlogcfg/smctrqry.cpp

812 lines
22 KiB
C++
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++
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;
}