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.
 
 
 
 
 
 

5197 lines
161 KiB

/*****************************************************************************\
Copyright (c) Microsoft Corporation. All rights reserved.
\*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <tchar.h>
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <winbase.h>
#include <userenv.h>
#include <wmistr.h>
#include <evntrace.h>
#include <pdh.h>
#include <pdhp.h>
#include <pdhmsg.h>
#include <wincrypt.h>
#include <shlwapi.h>
#include "plogman.h"
#include "pdhdlgs.h"
HANDLE hPdhPlaMutex = NULL;
/*****************************************************************************\
Strings
\*****************************************************************************/
// Common
LPCWSTR szCollection = L"Collection Name";
LPCWSTR szKey = L"Key";
LPCWSTR szRunAs = L"Run As";
LPCWSTR szSysmonLog = L"SysmonLog";
LPCWSTR szCurrentState = L"Current State";
LPCWSTR szLogType = L"Log Type";
LPCWSTR szLogBaseName = L"Log File Base Name";
LPCWSTR szStart = L"Start";
LPCWSTR szStop = L"Stop";
LPCWSTR szRestart = L"Restart";
LPCWSTR szLogMaxSize = L"Log File Max Size";
LPCWSTR szCurrentLogFile = L"Current Log File Name";
LPCWSTR szLogSerialNumber = L"Log File Serial Number";
LPCWSTR szLogAutoFormat = L"Log File Auto Format";
LPCWSTR szComment = L"Comment";
LPCWSTR szEOFCmd = L"EOF Command File";
LPCWSTR szLogFolder = L"Log File Folder";
LPCWSTR szLogFileType = L"Log File Type";
LPCWSTR szRepeatSchedule = L"Repeat Schedule";
LPCWSTR szRepeatScheduleBegin = L"Repeat Schedule Start";
LPCWSTR szRepeatScheduleEnd = L"Repeat Schedule Stop";
LPCWSTR szCreateNewFile = L"Create New File";
LPCWSTR szDatastoreAttributes = L"Data Store Attributes";
// Trace
LPCWSTR szTraceProviderCount = L"Trace Provider Count";
LPCWSTR szTraceBufferSize = L"Trace Buffer Size";
LPCWSTR szTraceBufferMin = L"Trace Buffer Min Count";
LPCWSTR szTraceBufferMax = L"Trace Buffer Max Count";
LPCWSTR szTraceFlushInterval = L"Trace Buffer Flush Interval";
LPCWSTR szTraceFlags = L"Trace Flags";
LPCWSTR szTraceProviderList = L"Trace Provider List";
LPCWSTR szTraceProviderFlags = L"Trace Provider Flags";
LPCWSTR szTraceProviderLevels = L"Trace Provider Levels";
LPCWSTR szTraceMode = L"Trace Mode";
LPCWSTR szTraceLoggerName = L"Trace Logger Name";
// Performance
LPCWSTR szPerfCounterList = L"Counter List";
LPCWSTR szSqlBaseName = L"Sql Log Base Name";
LPCWSTR szSampleInterval = L"Sample Interval";
/*****************************************************************************/
extern "C"
{
LPWSTR
PlaiStringDuplicate( LPWSTR sz )
{
LPWSTR szDup = NULL;
__try {
if( NULL != sz ){
size_t cbSize = ( _tcslen( sz ) + 1 ) * sizeof(WCHAR);
szDup = (LPWSTR)G_ALLOC( cbSize );
if( NULL != szDup ){
StringCbCopy( szDup, cbSize, sz );
}
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
G_FREE( szDup );
szDup = NULL;
}
return szDup;
}
}
#define CHECK_NAMES( szName, szCom, strCom ) \
if( szName == NULL ){ \
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE; \
goto cleanup; \
} \
if( NULL != strCom && NULL == szCom ){ \
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE; \
goto cleanup; \
}
PDH_FUNCTION
PlaiErrorToPdhStatus( DWORD dwStatus )
{
switch( dwStatus ){
case ERROR_SUCCESS: return ERROR_SUCCESS;
case ERROR_FILE_NOT_FOUND: return PDH_PLA_COLLECTION_NOT_FOUND;
case ERROR_SERVICE_ALREADY_RUNNING: return PDH_PLA_COLLECTION_ALREADY_RUNNING;
case ERROR_DIRECTORY: return PDH_PLA_ERROR_FILEPATH;
case ERROR_OUTOFMEMORY: return PDH_MEMORY_ALLOCATION_FAILURE;
case ERROR_NOT_ENOUGH_MEMORY: return PDH_MEMORY_ALLOCATION_FAILURE;
case ERROR_NO_DATA: return PDH_NO_DATA;
case ERROR_ACCESS_DENIED: return PDH_ACCESS_DENIED;
case WBEM_E_NOT_FOUND: return PDH_WBEM_ERROR;
case E_FAIL: return PDH_WBEM_ERROR;
case WBEM_E_PROVIDER_FAILURE: return PDH_WBEM_ERROR;
case WBEM_E_OUT_OF_MEMORY: return PDH_MEMORY_ALLOCATION_FAILURE;
case ERROR_BAD_NETPATH: return PDH_ACCESS_DENIED;
case WBEM_E_ACCESS_DENIED: return PDH_ACCESS_DENIED;
default: return PDH_INVALID_DATA;
}
}
ULONG
PlaMszStrLenA( LPSTR mszString )
{
ULONG nLength = 0;
ULONG nTotalLength = 0;
LPSTR strScan = mszString;
if( mszString == NULL ){
return 0;
}
while( *strScan != '\0' ){
nLength = (strlen( strScan )+1);
strScan += nLength;
nTotalLength += nLength;
}
return (nTotalLength*sizeof(char) + (sizeof(char) * 2));
}
ULONG
PlaMszStrLenW( LPWSTR mszString )
{
ULONG nLength = 0;
ULONG nTotalLength = 0;
LPTSTR strScan = mszString;
if( mszString == NULL ){
return 0;
}
while( *strScan != L'\0' ){
nLength = (wcslen( strScan )+1);
strScan += nLength;
nTotalLength += nLength;
}
return (nTotalLength*sizeof(WCHAR) + (sizeof(WCHAR)));
}
_inline BOOL
PlaiIsStringEmpty( LPWSTR str )
{
if( NULL == str ){
return TRUE;
}
if( L'\0' == *str ){
return TRUE;
}
return FALSE;
}
_inline BOOL
PlaiIsCharWhitespace( WCHAR ch )
{
switch( ch ){
case L' ':
case L'\r':
case L'\n':
case L'\t':
return TRUE;
default:
return FALSE;
}
}
PDH_FUNCTION
Plaiatow( LPSTR strA, LPWSTR &strW )
{
if( NULL == strA ){
strW = NULL;
return ERROR_SUCCESS;
}
strW = (LPWSTR)G_ALLOC( (strlen(strA)+1) * sizeof(WCHAR) );
if( strW ){
mbstowcs( strW, strA, (strlen(strA)+1) );
return ERROR_SUCCESS;
}
strW = NULL;
return PDH_MEMORY_ALLOCATION_FAILURE;
}
ULONG
Plaihextoi( LPWSTR s )
{
long len;
ULONG num, base, hex;
if ( PlaiIsStringEmpty( s ) ) {
return 0;
}
len = (long) wcslen(s);
if (len == 0) {
return 0;
}
hex = 0;
base = 1;
num = 0;
while (-- len >= 0) {
if (s[len] >= L'0' && s[len] <= L'9'){
num = s[len] - L'0';
}else if (s[len] >= L'a' && s[len] <= L'f'){
num = (s[len] - L'a') + 10;
}else if (s[len] >= L'A' && s[len] <= L'F'){
num = (s[len] - L'A') + 10;
}else if( s[len] == L'x' || s[len] == L'X'){
break;
}else{
continue;
}
hex += num * base;
base = base * 16;
}
return hex;
}
PDH_FUNCTION
PlaiTranslateKernelFlags( LPDWORD pdwInternal, LPDWORD pdwReal )
{
if( *pdwReal & EVENT_TRACE_FLAG_PROCESS ){
*pdwInternal |= PLA_TLI_ENABLE_PROCESS_TRACE;
}
if( *pdwReal & EVENT_TRACE_FLAG_THREAD ){
*pdwInternal |= PLA_TLI_ENABLE_THREAD_TRACE;
}
if( *pdwReal & EVENT_TRACE_FLAG_MEMORY_PAGE_FAULTS ){
*pdwInternal |= PLA_TLI_ENABLE_MEMMAN_TRACE;
}
if( *pdwReal & EVENT_TRACE_FLAG_MEMORY_HARD_FAULTS ){
*pdwInternal |= PLA_TLI_ENABLE_MEMMAN_TRACE;
}
if( *pdwReal & EVENT_TRACE_FLAG_DISK_IO ){
*pdwInternal |= PLA_TLI_ENABLE_DISKIO_TRACE;
}
if( *pdwReal & EVENT_TRACE_FLAG_NETWORK_TCPIP ){
*pdwInternal |= PLA_TLI_ENABLE_NETWORK_TCPIP_TRACE;
}
if( *pdwReal & EVENT_TRACE_FLAG_DISK_FILE_IO ){
*pdwInternal |= PLA_TLI_ENABLE_FILEIO_TRACE;
}
return ERROR_SUCCESS;
}
BOOL
PlaiIsLocalComputer( LPWSTR strComputer )
{
if( PlaiIsStringEmpty( strComputer ) ){
return TRUE;
}else{
LPWSTR str = strComputer;
WCHAR buffer[MAX_COMPUTERNAME_LENGTH+1];
DWORD dwSize = MAX_COMPUTERNAME_LENGTH+1;
BOOL bResult;
bResult = GetComputerName( buffer, &dwSize );
if( bResult ){
while( *str == L'\\' ){
str++;
}
return (_wcsicmp( buffer, str ) == 0);
}else{
return TRUE;
}
}
return FALSE;
}
/*****************************************************************************/
DWORD
PlaiUpdateServiceMode( LPTSTR strComputer )
{
DWORD dwStatus = ERROR_SUCCESS;
BOOL bStatus;
PDH_STATUS pdhStatus;
SC_HANDLE hSC = NULL;
SC_HANDLE hService = NULL;
QUERY_SERVICE_CONFIG* pServiceConfig = NULL;
DWORD dwSize = 0;
BOOL bAutoStart = FALSE;
PDH_PLA_INFO_W info;
LPWSTR mszCollections = NULL;
pdhStatus = PdhPlaEnumCollections( strComputer, &dwSize, mszCollections );
if( ERROR_SUCCESS == pdhStatus || PDH_INSUFFICIENT_BUFFER == pdhStatus ){
mszCollections = (LPWSTR)G_ALLOC( dwSize * sizeof(TCHAR) );
if( mszCollections ){
LPTSTR strCollection;
pdhStatus = PdhPlaEnumCollections( strComputer, &dwSize, mszCollections );
if( ERROR_SUCCESS == pdhStatus && NULL != mszCollections ){
dwSize = sizeof( PDH_PLA_INFO_W );
strCollection = mszCollections;
while( *strCollection != L'\0' ){
info.dwMask = PLA_INFO_FLAG_BEGIN;
strCollection += ( wcslen( strCollection ) + 1 );
pdhStatus = PdhPlaGetInfoW( strCollection, strComputer, &dwSize, &info );
if( ERROR_SUCCESS == pdhStatus ){
if( (info.dwMask & PLA_INFO_FLAG_BEGIN) &&
info.ptLogBeginTime.dwAutoMode != PLA_AUTO_MODE_NONE ){
bAutoStart = TRUE;
break;
}
}
}
}
}else{
dwStatus = ERROR_OUTOFMEMORY;
}
}else{
dwStatus = ERROR_FILE_NOT_FOUND;
}
if( ERROR_SUCCESS != dwStatus ){
goto cleanup;
}
hSC = OpenSCManager ( strComputer, NULL, GENERIC_READ );
if (hSC == NULL) {
dwStatus = GetLastError();
goto cleanup;
}
BOOL bUpdate = FALSE;
dwSize = 4096;
pServiceConfig = (QUERY_SERVICE_CONFIG*)G_ALLOC( dwSize );
if( NULL == pServiceConfig ){
dwStatus = ERROR_OUTOFMEMORY;
goto cleanup;
}
ZeroMemory( pServiceConfig, dwSize );
hService = OpenService (
hSC,
szSysmonLog,
SERVICE_CHANGE_CONFIG | SERVICE_QUERY_CONFIG | SERVICE_START
);
if( NULL == hService ){
dwStatus = GetLastError();
goto cleanup;
}
bStatus = QueryServiceConfig (
hService,
pServiceConfig,
dwSize,
&dwSize
);
if( !bStatus ){
dwStatus = GetLastError();
goto cleanup;
}
if ( bAutoStart ) {
if ( SERVICE_DEMAND_START == pServiceConfig->dwStartType ) {
bUpdate = TRUE;
}
} else {
if ( SERVICE_AUTO_START == pServiceConfig->dwStartType ) {
bUpdate = TRUE;
}
}
if( bUpdate ){
SC_ACTION ServiceControlAction[3];
SERVICE_FAILURE_ACTIONS FailActions;
bStatus = ChangeServiceConfig (
hService,
SERVICE_NO_CHANGE,
(bAutoStart ? SERVICE_AUTO_START : SERVICE_DEMAND_START),
SERVICE_NO_CHANGE,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
);
if( !bStatus ){
dwStatus = GetLastError();
goto cleanup;
}
ZeroMemory( ServiceControlAction, sizeof(SC_ACTION) * 3 );
ZeroMemory( &FailActions, sizeof(SERVICE_FAILURE_ACTIONS) );
if ( bAutoStart ) {
ServiceControlAction[0].Type = SC_ACTION_RESTART;
ServiceControlAction[1].Type = SC_ACTION_RESTART;
ServiceControlAction[2].Type = SC_ACTION_RESTART;
} else {
ServiceControlAction[0].Type = SC_ACTION_NONE;
ServiceControlAction[1].Type = SC_ACTION_NONE;
ServiceControlAction[2].Type = SC_ACTION_NONE;
}
FailActions.dwResetPeriod = 60;
FailActions.cActions = 3;
FailActions.lpsaActions = ServiceControlAction;
bStatus = ChangeServiceConfig2(
hService,
SERVICE_CONFIG_FAILURE_ACTIONS,
&FailActions
);
if ( ! bStatus ) {
dwStatus = GetLastError();
}
}
cleanup:
G_FREE( mszCollections );
G_FREE( pServiceConfig );
if( NULL != hService ){
CloseServiceHandle (hService);
}
if( NULL != hSC ){
CloseServiceHandle (hSC);
}
return dwStatus;
}
DWORD
PlaiGetServiceState (
LPCWSTR szComputerName,
DWORD& rdwState
)
{
DWORD dwStatus = ERROR_SUCCESS;
SERVICE_STATUS ssData;
SC_HANDLE hSC;
SC_HANDLE hLogService;
rdwState = 0; // Error by default.
// open SC database
hSC = OpenSCManagerW ( szComputerName, NULL, SC_MANAGER_CONNECT);
if (hSC != NULL) {
// open service
hLogService = OpenServiceW (
hSC,
szSysmonLog,
SERVICE_INTERROGATE );
if (hLogService != NULL) {
if ( ControlService (
hLogService,
SERVICE_CONTROL_INTERROGATE,
&ssData)) {
rdwState = ssData.dwCurrentState;
} else {
dwStatus = GetLastError();
rdwState = SERVICE_STOPPED;
}
CloseServiceHandle (hLogService);
} else {
dwStatus = GetLastError();
}
CloseServiceHandle (hSC);
} else {
dwStatus = GetLastError();
}
if ( ERROR_SERVICE_NOT_ACTIVE == dwStatus || ERROR_SERVICE_REQUEST_TIMEOUT == dwStatus ) {
rdwState = SERVICE_STOPPED;
dwStatus = ERROR_SUCCESS;
}
return dwStatus;
}
PDH_FUNCTION
PlaiSynchronize( LPCWSTR szComputerName )
{
// If the service is running, tell it to synchronize itself,
// Check the state afterwards to see if it got the message.
// If stop pending or stopped, wait until the service is
// stopped and then attempt to start it. The service
// synchronizes itself from the registry when it is started.
// Return ERROR_SUCCESS for success, other for failure.
SC_HANDLE hSC = NULL;
SC_HANDLE hLogService = NULL;
SERVICE_STATUS ssData;
DWORD dwCurrentState;
DWORD dwTimeout = 25;
DWORD dwStatus = ERROR_SUCCESS;
dwStatus = PlaiGetServiceState ( szComputerName, dwCurrentState );
if ( ERROR_SUCCESS == dwStatus && 0 != dwCurrentState ) {
// open SC database
hSC = OpenSCManagerW ( szComputerName, NULL, SC_MANAGER_CONNECT);
if ( NULL != hSC ) {
// open service
hLogService = OpenServiceW (
hSC,
szSysmonLog,
SERVICE_USER_DEFINED_CONTROL
| SERVICE_START );
if ( NULL != hLogService ) {
if ( ( SERVICE_STOPPED != dwCurrentState )
&& ( SERVICE_STOP_PENDING != dwCurrentState ) ) {
// Wait 100 milliseconds before synchronizing service,
// to ensure that registry values are written.
_sleep ( 100 );
ControlService (
hLogService,
PLA_SERVICE_CONTROL_SYNCHRONIZE,
&ssData);
dwCurrentState = ssData.dwCurrentState;
}
// Make sure that the ControlService call reached the service
// while it was in run state.
if ( ( SERVICE_STOPPED == dwCurrentState )
|| ( SERVICE_STOP_PENDING == dwCurrentState ) ) {
if ( SERVICE_STOP_PENDING == dwCurrentState ) {
// wait for the service to stop before starting it.
while ( --dwTimeout && ERROR_SUCCESS == dwStatus ) {
dwStatus = PlaiGetServiceState ( szComputerName, dwCurrentState );
if ( SERVICE_STOP_PENDING == dwCurrentState ) {
_sleep(200);
} else {
break;
}
}
}
dwTimeout = 25;
if ( SERVICE_STOPPED == dwCurrentState ) {
if ( StartService (hLogService, 0, NULL) ) {
// wait for the service to start or stop
// before returning
while ( --dwTimeout && ERROR_SUCCESS == dwStatus ) {
dwStatus = PlaiGetServiceState ( szComputerName, dwCurrentState );
if ( SERVICE_START_PENDING == dwCurrentState ) {
_sleep(200);
} else {
break;
}
}
} else {
dwStatus = GetLastError();
}
}
}
}
CloseServiceHandle ( hLogService );
} else {
dwStatus = GetLastError();
}
CloseServiceHandle (hSC);
} else {
dwStatus = GetLastError();
}
if( 0 == dwCurrentState || ERROR_SUCCESS != dwStatus ){
return PDH_PLA_SERVICE_ERROR;
}
return ERROR_SUCCESS;
}
/*****************************************************************************\
PdhPlaSchedule
Sets the start/stop attributes of a log query
Arguments:
LPTSTR strName
Log Name
LPTSTR strComputer
Computer to connect to
DWORD fType
PLA_AUTO_MODE_NONE Sets schedule to manual start if pInfo->StartTime is non-zero
Sets schedule to manula stop if pInfo->EndTime is non-zero and
Stops logger if it is running
PLA_AUTO_MODE_AT Uses pInfo for start and end times
PLA_AUTO_MODE_AFTER Sets the logger to run for a specified
period. Does not start the logger.
Uses pInfo->SampleCount for interval type
PLA_TT_UTYPE_SECONDS
PLA_TT_UTYPE_MINUTES
PLA_TT_UTYPE_HOURS
PLA_TT_UTYPE_DAYS
PPDH_TIME_INFO pInfo
Start and Stop times
Return:
PDH_INVALID_ARGUMENT
A required argument is missing or incorrect.
PDH_PLA_COLLECTION_ALREADY_RUNNING
The Query is currently running, no action taken
PDH_PLA_ERROR_SCHEDULE_OVERLAP
The start and stop times overlap.
PDH_PLA_COLLECTION_NOT_FOUND
Query does not exist
PDH_PLA_ERROR_SCHEDULE_ELAPSED
The end time has elapsed
ERROR_SUCCESS
\*****************************************************************************/
PDH_FUNCTION
PlaiSchedule(
LPWSTR strComputer,
HKEY hkeyQuery,
DWORD fType,
PPDH_TIME_INFO pInfo
)
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
PLA_TIME_INFO stiData;
DWORD dwRegValue;
RegFlushKey( hkeyQuery );
// Make sure its not already running
pdhStatus = PlaiReadRegistryDwordValue(
hkeyQuery,
szCurrentState,
&dwRegValue );
if( ERROR_SUCCESS == pdhStatus ){
if( PLA_QUERY_RUNNING == dwRegValue ){
DWORD dwState;
PlaiGetServiceState( strComputer, dwState );
if( dwState != SERVICE_STOPPED ){
RegCloseKey( hkeyQuery );
return PDH_PLA_COLLECTION_ALREADY_RUNNING;
}
}
}
memset (&stiData, 0, sizeof(stiData));
switch( fType ){
case PLA_AUTO_MODE_NONE:
stiData.wDataType = PLA_TT_DTYPE_DATETIME;
stiData.dwAutoMode = PLA_AUTO_MODE_NONE;
PlaiRemoveRepeat( hkeyQuery );
stiData.llDateTime = MIN_TIME_VALUE;
if( pInfo->StartTime ){
stiData.wTimeType = PLA_TT_TTYPE_START;
pdhStatus = PlaiWriteRegistryPlaTime ( hkeyQuery, szStart, &stiData );
}
if( pInfo->EndTime ){
stiData.wTimeType = PLA_TT_TTYPE_STOP;
pdhStatus = PlaiWriteRegistryPlaTime ( hkeyQuery, szStop, &stiData );
}
break;
case PLA_AUTO_MODE_AT:
{
SYSTEMTIME stLocalTime;
FILETIME ftLocalTime;
LONGLONG llLocalTime;
// get local time
GetLocalTime (&stLocalTime);
SystemTimeToFileTime (&stLocalTime, &ftLocalTime);
llLocalTime =
(((ULONGLONG) ftLocalTime.dwHighDateTime) << 32) +
ftLocalTime.dwLowDateTime;
if( pInfo->StartTime && pInfo->EndTime ){
if( pInfo->StartTime > pInfo->EndTime ){
return PDH_PLA_ERROR_SCHEDULE_OVERLAP;
}
}
stiData.wDataType = PLA_TT_DTYPE_DATETIME;
stiData.dwAutoMode = PLA_AUTO_MODE_AT;
if( pInfo->StartTime ){
stiData.wTimeType = PLA_TT_TTYPE_START;
stiData.llDateTime = pInfo->StartTime;
pdhStatus = PlaiWriteRegistryPlaTime ( hkeyQuery, szStart, &stiData );
if( ! pInfo->EndTime && pInfo->StartTime < llLocalTime ){
PLA_TIME_INFO stiStopData;
pdhStatus = PlaiReadRegistryPlaTime( hkeyQuery, szStop, &stiStopData );
if( ERROR_SUCCESS == pdhStatus && stiStopData.dwAutoMode == PLA_AUTO_MODE_NONE ){
stiStopData.llDateTime = MAX_TIME_VALUE;
PlaiWriteRegistryPlaTime( hkeyQuery, szStop, &stiStopData );
}
}else if( ! pInfo->EndTime ){
PLA_TIME_INFO stiStopData;
pdhStatus = PlaiReadRegistryPlaTime ( hkeyQuery, szStop, &stiStopData );
if( ERROR_SUCCESS == pdhStatus ){
if( PLA_AUTO_MODE_NONE == stiStopData.dwAutoMode ){
stiData.wTimeType = PLA_TT_TTYPE_STOP;
stiData.llDateTime = MAX_TIME_VALUE;
stiData.dwAutoMode = PLA_AUTO_MODE_NONE;
pdhStatus = PlaiWriteRegistryPlaTime ( hkeyQuery, szStop, &stiData );
}
}
}
}
if( pInfo->EndTime ){
if( pInfo->EndTime < llLocalTime ){
return PDH_PLA_ERROR_SCHEDULE_ELAPSED;
}
stiData.wTimeType = PLA_TT_TTYPE_STOP;
stiData.llDateTime = pInfo->EndTime;
pdhStatus = PlaiWriteRegistryPlaTime ( hkeyQuery, szStop, &stiData );
}
}
break;
case PLA_AUTO_MODE_AFTER:
stiData.wTimeType = PLA_TT_TTYPE_STOP;
stiData.wDataType = PLA_TT_DTYPE_UNITS;
stiData.dwAutoMode = PLA_AUTO_MODE_AFTER;
stiData.dwValue = (DWORD)pInfo->EndTime;
stiData.dwUnitType = pInfo->SampleCount;
pdhStatus = PlaiWriteRegistryPlaTime ( hkeyQuery, szStop, &stiData );
break;
default:
return PDH_INVALID_ARGUMENT;
}
return pdhStatus;
}
PDH_FUNCTION
PlaiRemoveRepeat( HKEY hkeyQuery )
{
PLA_TIME_INFO info;
PDH_STATUS pdhStatus;
ZeroMemory( &info, sizeof( PLA_TIME_INFO ) );
pdhStatus = PlaiWriteRegistryPlaTime ( hkeyQuery, szRepeatSchedule, &info );
return pdhStatus;
}
PDH_FUNCTION
PdhPlaScheduleA(
LPSTR strName,
LPSTR strComputer,
DWORD fType,
PPDH_TIME_INFO pInfo
)
{
PDH_STATUS pdhStatus;
LPWSTR wstrName = NULL;
LPWSTR wstrComputer = NULL;
VALIDATE_QUERY( strName );
pdhStatus = Plaiatow( strComputer, wstrComputer );
if( ERROR_SUCCESS == pdhStatus ){
pdhStatus = Plaiatow( strName, wstrName );
if( ERROR_SUCCESS == pdhStatus ){
pdhStatus = PdhPlaScheduleW( wstrName, wstrComputer, fType, pInfo );
}
}
G_FREE( wstrComputer );
G_FREE( wstrName );
return pdhStatus;
}
PDH_FUNCTION
PdhPlaScheduleW(
LPWSTR strName,
LPWSTR strComputer,
DWORD fType,
PPDH_TIME_INFO pInfo
)
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
HKEY hkeyQuery = NULL;
VALIDATE_QUERY( strName );
LPWSTR szName = PlaiStringDuplicate( strName );
LPWSTR szComputer = PlaiStringDuplicate( strComputer );
CHECK_NAMES( szName, szComputer, strComputer );
PDH_TIME_INFO TimeInfo;
__try {
if( NULL != pInfo ){
memcpy( &TimeInfo, pInfo, sizeof(PDH_TIME_INFO) );
}else{
pdhStatus = PDH_INVALID_ARGUMENT;
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
CHECK_STATUS( pdhStatus );
pdhStatus = PlaiConnectAndLockQuery ( szComputer, szName, hkeyQuery );
if( ERROR_SUCCESS == pdhStatus ){
pdhStatus = PlaiSchedule( szComputer, hkeyQuery, fType, &TimeInfo );
RELEASE_MUTEX(hPdhPlaMutex);
}
if ( NULL != hkeyQuery ) {
RegCloseKey ( hkeyQuery );
}
if( SUCCEEDED( pdhStatus ) ){
pdhStatus = PlaiSynchronize( szComputer );
PlaiUpdateServiceMode( szComputer );
}
__try {
memcpy( pInfo, &TimeInfo, sizeof(PDH_TIME_INFO) );
} __except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
cleanup:
G_FREE( szName );
G_FREE( szComputer );
return pdhStatus;
}
/*****************************************************************************\
PdhPlaGetSchedule
Arguments:
LPTSTR strName
Log Name
LPTSTR strComputer
Computer to connect to
Return:
ERROR_SUCCESS
\*****************************************************************************/
PDH_FUNCTION
PdhPlaGetScheduleA(
LPSTR strName,
LPSTR strComputer,
LPDWORD pdwTypeStart,
LPDWORD pdwTypeStop,
PPDH_TIME_INFO pInfo
)
{
return PDH_NOT_IMPLEMENTED;
}
PDH_FUNCTION
PdhPlaGetScheduleW(
LPWSTR strName,
LPWSTR strComputer,
LPDWORD pdwTypeStart,
LPDWORD pdwTypeStop,
PPDH_TIME_INFO pInfo
)
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
HKEY hkeyQuery = NULL;
BOOL bMutex = FALSE;
VALIDATE_QUERY( strName );
LPWSTR szName = PlaiStringDuplicate( strName );
LPWSTR szComputer = PlaiStringDuplicate( strComputer );
CHECK_NAMES( szName, szComputer, strComputer );
DWORD dwTypeStart;
DWORD dwTypeStop;
PDH_TIME_INFO TimeInfo;
pdhStatus = PlaiConnectAndLockQuery ( szComputer, szName, hkeyQuery, FALSE );
if ( ERROR_SUCCESS == pdhStatus ) {
PLA_TIME_INFO ptiStartInfo;
PLA_TIME_INFO ptiStopInfo;
PLA_TIME_INFO ptiRepeatInfo;
ZeroMemory( &TimeInfo, sizeof(PDH_TIME_INFO) );
bMutex = TRUE;
pdhStatus = PlaiReadRegistryPlaTime ( hkeyQuery, szRepeatSchedule, &ptiRepeatInfo );
if( ERROR_SUCCESS == pdhStatus && PLA_AUTO_MODE_CALENDAR == ptiRepeatInfo.dwAutoMode ){
dwTypeStart = PLA_AUTO_MODE_CALENDAR;
pdhStatus = PlaiReadRegistryPlaTime ( hkeyQuery, szRepeatScheduleBegin, &ptiStartInfo );
if( ERROR_SUCCESS != pdhStatus ){
pdhStatus = PlaiReadRegistryPlaTime ( hkeyQuery, szStart, &ptiStartInfo );
}
CHECK_STATUS( pdhStatus );
pdhStatus = PlaiReadRegistryPlaTime ( hkeyQuery, szRepeatScheduleEnd, &ptiStopInfo );
if( ERROR_SUCCESS != pdhStatus ){
pdhStatus = PlaiReadRegistryPlaTime ( hkeyQuery, szStop, &ptiStopInfo );
}
CHECK_STATUS( pdhStatus );
dwTypeStop = ptiStopInfo.dwAutoMode;
}else{
pdhStatus = PlaiReadRegistryPlaTime ( hkeyQuery, szStart, &ptiStartInfo );
CHECK_STATUS( pdhStatus );
dwTypeStart = ptiStartInfo.dwAutoMode;
pdhStatus = PlaiReadRegistryPlaTime ( hkeyQuery, szStop, &ptiStopInfo );
CHECK_STATUS( pdhStatus );
dwTypeStop = ptiStopInfo.dwAutoMode;
}
__try {
pInfo->StartTime = ptiStartInfo.llDateTime;
pInfo->EndTime = ptiStopInfo.llDateTime;
*pdwTypeStart = dwTypeStart;
*pdwTypeStop = dwTypeStop;
} __except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
cleanup:
if( bMutex ){
RELEASE_MUTEX(hPdhPlaMutex);
}
if ( NULL != hkeyQuery ) {
RegCloseKey ( hkeyQuery );
}
G_FREE( szName );
G_FREE( szComputer );
return pdhStatus;
}
/*****************************************************************************\
PdhPlaStart
Starts a log query
Arguments:
LPTSTR strName
Log Name
LPTSTR strComputer
Computer to connect to
Return:
PDH_PLA_COLLECTION_ALREADY_RUNNING
The Query is currently running, no action taken
PDH_INVALID_ARGUMENT
The query does not exist
PDH_PLA_ERROR_SCHEDULE_ELAPSED
The query was scheduled to stop in the past, no action taken
ERROR_SUCCESS
\*****************************************************************************/
PDH_FUNCTION
PdhPlaStartA( LPSTR strName, LPSTR strComputer )
{
PDH_STATUS pdhStatus;
LPWSTR wstrName = NULL;
LPWSTR wstrComputer = NULL;
VALIDATE_QUERY( strName );
pdhStatus = Plaiatow( strComputer, wstrComputer );
if( ERROR_SUCCESS == pdhStatus ){
pdhStatus = Plaiatow( strName, wstrName );
if( ERROR_SUCCESS == pdhStatus ){
pdhStatus = PdhPlaStartW( wstrName, wstrComputer );
}
}
G_FREE( wstrComputer );
G_FREE( wstrName );
return pdhStatus;
}
PDH_FUNCTION
PdhPlaStartW( LPWSTR strName, LPWSTR strComputer )
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
HKEY hkeyQuery = NULL;
VALIDATE_QUERY( strName );
LPWSTR szName = PlaiStringDuplicate( strName );
LPWSTR szComputer = PlaiStringDuplicate( strComputer );
CHECK_NAMES( szName, szComputer, strComputer );
pdhStatus = PlaiConnectAndLockQuery ( szComputer, szName, hkeyQuery );
if ( ERROR_SUCCESS == pdhStatus ) {
PLA_TIME_INFO stiData;
PLA_TIME_INFO stiStopData;
DWORD dwRegValue;
// Make sure its not already running
pdhStatus = PlaiReadRegistryDwordValue(
hkeyQuery,
szCurrentState,
&dwRegValue );
if( ERROR_SUCCESS == pdhStatus ){
if( PLA_QUERY_RUNNING == dwRegValue ){
DWORD dwState;
PlaiGetServiceState( szComputer, dwState );
if( dwState != SERVICE_STOPPED ){
RegCloseKey( hkeyQuery );
RELEASE_MUTEX(hPdhPlaMutex);
return PDH_PLA_COLLECTION_ALREADY_RUNNING;
}
}
}
//Make sure it was not set to stop in the past
pdhStatus = PlaiReadRegistryPlaTime ( hkeyQuery, szStop, &stiStopData );
if( ERROR_SUCCESS == pdhStatus ) {
if ( PLA_AUTO_MODE_AT == stiStopData.dwAutoMode ) {
SYSTEMTIME stLocalTime;
FILETIME ftLocalTime;
LONGLONG llLocalTime;
// get local time
GetLocalTime (&stLocalTime);
SystemTimeToFileTime (&stLocalTime, &ftLocalTime);
llLocalTime =
(((ULONGLONG) ftLocalTime.dwHighDateTime) << 32) +
ftLocalTime.dwLowDateTime;
if ( llLocalTime > stiStopData.llDateTime ) {
RELEASE_MUTEX(hPdhPlaMutex);
RegCloseKey( hkeyQuery );
return PDH_PLA_ERROR_SCHEDULE_ELAPSED;
}
}
}
memset (&stiData, 0, sizeof(stiData));
stiData.wTimeType = PLA_TT_TTYPE_START;
stiData.wDataType = PLA_TT_DTYPE_DATETIME;
stiData.dwAutoMode = PLA_AUTO_MODE_NONE;
stiData.llDateTime = MIN_TIME_VALUE;
PlaiRemoveRepeat( hkeyQuery );
pdhStatus = PlaiWriteRegistryPlaTime ( hkeyQuery, szStart, &stiData );
if( PLA_AUTO_MODE_NONE == stiStopData.dwAutoMode ){
stiData.wTimeType = PLA_TT_TTYPE_STOP;
stiData.llDateTime = MAX_TIME_VALUE;
pdhStatus = PlaiWriteRegistryPlaTime ( hkeyQuery, szStop, &stiData );
}
if ( ERROR_SUCCESS == pdhStatus ) {
dwRegValue = PLA_QUERY_START_PENDING;
pdhStatus = PlaiWriteRegistryDwordValue (
hkeyQuery,
szCurrentState,
&dwRegValue );
}
// Set LastModified
if ( ERROR_SUCCESS == pdhStatus ) {
pdhStatus = PlaiWriteRegistryLastModified ( hkeyQuery );
}
RELEASE_MUTEX(hPdhPlaMutex);
// Start the service on the target machine
if ( SUCCEEDED( pdhStatus ) ) {
pdhStatus = PlaiSynchronize( szComputer );
if( ERROR_SUCCESS == pdhStatus ){
DWORD dwTimeOut = 25;
while( --dwTimeOut > 0 ){
pdhStatus = PlaiReadRegistryDwordValue(
hkeyQuery,
szCurrentState,
&dwRegValue
);
if( ERROR_SUCCESS == pdhStatus && dwRegValue != PLA_QUERY_RUNNING ){
pdhStatus = PDH_PLA_ERROR_NOSTART;
}else{
pdhStatus = ERROR_SUCCESS;
break;
}
_sleep(200);
}
}
}
}
if ( NULL != hkeyQuery ) {
RegCloseKey ( hkeyQuery );
}
cleanup:
G_FREE( szName );
G_FREE( szComputer );
return pdhStatus;
}
/*****************************************************************************\
PdhPlaStop
Stops a log query
Arguments:
LPTSTR strName
Log Name
LPTSTR strComputer
Computer to connect to
Return:
PDH_INVALID_ARGUMENT
The query does not exist
ERROR_SUCCESS
\*****************************************************************************/
PDH_FUNCTION
PdhPlaStopA( LPSTR strName, LPSTR strComputer )
{
PDH_STATUS pdhStatus;
LPWSTR wstrName = NULL;
LPWSTR wstrComputer = NULL;
VALIDATE_QUERY( strName );
pdhStatus = Plaiatow( strComputer, wstrComputer );
if( ERROR_SUCCESS == pdhStatus ){
pdhStatus = Plaiatow( strName, wstrName );
if( ERROR_SUCCESS == pdhStatus ){
pdhStatus = PdhPlaStopW( wstrName, wstrComputer );
}
}
G_FREE( wstrComputer );
G_FREE( wstrName );
return pdhStatus;
}
PDH_FUNCTION
PdhPlaStopW( LPWSTR strName, LPWSTR strComputer )
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
HKEY hkeyQuery = NULL;
VALIDATE_QUERY( strName );
LPWSTR szName = PlaiStringDuplicate( strName );
LPWSTR szComputer = PlaiStringDuplicate( strComputer );
CHECK_NAMES( szName, szComputer, strComputer );
pdhStatus = PlaiConnectAndLockQuery( szComputer, szName, hkeyQuery );
if ( ERROR_SUCCESS == pdhStatus ) {
PLA_TIME_INFO stiData;
DWORD dwRestartMode = 0;
DWORD dwState;
pdhStatus = PlaiReadRegistryDwordValue(
hkeyQuery,
szCurrentState,
&dwState );
if( ERROR_SUCCESS == pdhStatus ){
if( PLA_QUERY_STOPPED != dwState ){
PlaiGetServiceState( szComputer, dwState );
if( dwState == SERVICE_STOPPED ){
dwState = PLA_QUERY_STOPPED;
PlaiWriteRegistryDwordValue ( hkeyQuery, szCurrentState, &dwState );
}
}
}
// If query is set to restart on end, clear the restart flag.
pdhStatus = PlaiReadRegistryDwordValue ( hkeyQuery, szRestart, &dwRestartMode );
if ( ERROR_SUCCESS == pdhStatus && PLA_AUTO_MODE_NONE != dwRestartMode ) {
dwRestartMode = PLA_AUTO_MODE_NONE;
pdhStatus = PlaiWriteRegistryDwordValue ( hkeyQuery, szRestart, &dwRestartMode );
}
PlaiRemoveRepeat( hkeyQuery );
// Set stop mode to manual, stop time to MIN_TIME_VALUE
if ( ERROR_SUCCESS == pdhStatus ) {
memset (&stiData, 0, sizeof(stiData));
stiData.wTimeType = PLA_TT_TTYPE_STOP;
stiData.wDataType = PLA_TT_DTYPE_DATETIME;
stiData.dwAutoMode = PLA_AUTO_MODE_NONE;
stiData.llDateTime = MIN_TIME_VALUE;
pdhStatus = PlaiWriteRegistryPlaTime ( hkeyQuery, szStop, &stiData );
}
// If start time mode set to manual, set the value to MAX_TIME_VALUE
if ( ERROR_SUCCESS == pdhStatus ) {
pdhStatus = PlaiReadRegistryPlaTime ( hkeyQuery, szStart, &stiData );
if ( ERROR_SUCCESS == pdhStatus && PLA_AUTO_MODE_NONE == stiData.dwAutoMode ) {
stiData.llDateTime = MAX_TIME_VALUE;
pdhStatus = PlaiWriteRegistryPlaTime ( hkeyQuery, szStart, &stiData );
}
}
PlaiWriteRegistryLastModified ( hkeyQuery );
RELEASE_MUTEX(hPdhPlaMutex);
if ( SUCCEEDED( pdhStatus ) ) {
pdhStatus = PlaiSynchronize ( szComputer );
}
}
cleanup:
if ( NULL != hkeyQuery ) {
RegCloseKey ( hkeyQuery );
}
G_FREE( szName );
G_FREE( szComputer );
return pdhStatus;
}
/*****************************************************************************\
PdhPlaCreate
Creates a new log query
Arguments:
LPTSTR strName
Log Name
LPTSTR strComputer
Computer to connect to
DWORD fType
PLA_COUNTER_LOG
PLA_TRACE_LOG
Return:
ERROR_ALREADY_EXISTS
The Query is currently running, no action taken
ERROR_SUCCESS
\*****************************************************************************/
PDH_FUNCTION
PlaiInitializeNewQuery(
HKEY hkeyLogQueries,
HKEY& rhKeyQuery,
LPCWSTR strComputer,
LPCWSTR strName
)
{
DWORD dwStatus = ERROR_SUCCESS;
PDH_STATUS pdhStatus = ERROR_SUCCESS;
DWORD dwDisposition = 0;
DWORD dwValue;
PLA_TIME_INFO stiData;
PLA_VERSION version;
pdhStatus = PdhiPlaGetVersion( strComputer, &version );
if( ERROR_SUCCESS == pdhStatus && version.dwBuild > 2195 ){
GUID guid;
UNICODE_STRING strGUID;
dwStatus = UuidCreate( &guid );
if( !( dwStatus == RPC_S_OK || dwStatus == RPC_S_UUID_LOCAL_ONLY ) ){
return PlaiErrorToPdhStatus( dwStatus );
}
dwStatus = RtlStringFromGUID( guid, &strGUID );
if( ERROR_SUCCESS != dwStatus ){
return PlaiErrorToPdhStatus( dwStatus );
}
dwStatus = RegCreateKeyExW (
hkeyLogQueries,
strGUID.Buffer,
0,
NULL,
0,
KEY_READ|KEY_WRITE,
NULL,
&rhKeyQuery,
&dwDisposition
);
RtlFreeUnicodeString( &strGUID );
pdhStatus = PlaiErrorToPdhStatus( dwStatus );
}else{
dwStatus = RegCreateKeyExW (
hkeyLogQueries,
strName,
0,
NULL,
0,
KEY_READ|KEY_WRITE,
NULL,
&rhKeyQuery,
&dwDisposition
);
pdhStatus = PlaiErrorToPdhStatus( dwStatus );
}
if ( ERROR_SUCCESS == pdhStatus ) {
PlaiWriteRegistryStringValue( rhKeyQuery, szCollection, REG_SZ, strName, 0 );
dwValue = PLA_QUERY_STOPPED;
pdhStatus = PlaiWriteRegistryDwordValue (
rhKeyQuery,
szCurrentState,
&dwValue );
if ( ERROR_SUCCESS == pdhStatus ) {
// Initialize the log type to "new" to indicate partially created logs
dwValue = PLA_NEW_LOG;
pdhStatus = PlaiWriteRegistryDwordValue (
rhKeyQuery,
szLogType,
&dwValue );
PlaiWriteRegistryStringValue( rhKeyQuery, szLogBaseName, REG_SZ, strName, 0 );
memset (&stiData, 0, sizeof(stiData));
stiData.wTimeType = PLA_TT_TTYPE_START;
stiData.wDataType = PLA_TT_DTYPE_DATETIME;
stiData.dwAutoMode = PLA_AUTO_MODE_NONE;
stiData.llDateTime = MIN_TIME_VALUE;
pdhStatus = PlaiWriteRegistryPlaTime ( rhKeyQuery, szStart, &stiData );
stiData.wTimeType = PLA_TT_TTYPE_STOP;
pdhStatus = PlaiWriteRegistryPlaTime ( rhKeyQuery, szStop, &stiData );
memset (&stiData, 0, sizeof(stiData));
stiData.dwAutoMode = PLA_AUTO_MODE_NONE;
PlaiWriteRegistryPlaTime( rhKeyQuery, szCreateNewFile, &stiData );
dwValue = 0;
PlaiWriteRegistryDwordValue( rhKeyQuery, szRestart, &dwValue );
dwValue = PLA_QUERY_STOPPED;
PlaiWriteRegistryDwordValue( rhKeyQuery, szCurrentState, &dwValue );
dwValue = PLA_DISK_MAX_SIZE;
PlaiWriteRegistryDwordValue( rhKeyQuery, szLogMaxSize, &dwValue );
dwValue = 1;
PlaiWriteRegistryDwordValue( rhKeyQuery, szLogSerialNumber, &dwValue );
dwValue = 1;
PlaiWriteRegistryDwordValue( rhKeyQuery, szLogAutoFormat, &dwValue );
PlaiWriteRegistryStringValue( rhKeyQuery, szComment, REG_SZ, NULL, 0 );
PlaiWriteRegistryStringValue( rhKeyQuery, szEOFCmd, REG_SZ, NULL, 0 );
if( PlaiIsStringEmpty( (LPWSTR)strComputer ) ){
LPWSTR strDrive = _wgetenv( L"SystemDrive" );
if( strDrive != NULL && wcslen(strDrive) < 5 ){
WCHAR buffer[16];
StringCchPrintf( buffer, 16, L"%s\\PerfLogs", strDrive );
PlaiWriteRegistryStringValue( rhKeyQuery, szLogFolder, REG_SZ, buffer, 0 );
}
}else{
PlaiWriteRegistryStringValue( rhKeyQuery, szLogFolder, REG_SZ, L"%SystemDrive%\\PerfLogs", 0 );
}
}
}
return pdhStatus;
}
PDH_FUNCTION
PlaiCreateCounterQuery( HKEY hkeyQuery )
{
PDH_STATUS pdhStatus;
DWORD dwValue;
dwValue = PLA_BIN_FILE;
pdhStatus = PlaiWriteRegistryDwordValue( hkeyQuery, szLogFileType, &dwValue );
PLA_TIME_INFO stiData;
stiData.wTimeType = PLA_TT_TTYPE_SAMPLE;
stiData.dwAutoMode = PLA_AUTO_MODE_AFTER;
stiData.wDataType = PLA_TT_DTYPE_UNITS;
stiData.dwUnitType = PLA_TT_UTYPE_SECONDS;
stiData.dwValue = 0x000F;
pdhStatus = PlaiWriteRegistryPlaTime( hkeyQuery, szSampleInterval, &stiData );
PlaiWriteRegistryStringValue( hkeyQuery, szPerfCounterList, REG_MULTI_SZ, NULL, 0 );
pdhStatus = PlaiWriteRegistryLastModified ( hkeyQuery );
dwValue = PLA_DATASTORE_SIZE_KB|PLA_DATASTORE_APPEND;
PlaiWriteRegistryDwordValue( hkeyQuery, szDatastoreAttributes, &dwValue );
PlaiWriteRegistryStringValue(hkeyQuery, szPerfCounterList, REG_MULTI_SZ, NULL, 0 );
return ERROR_SUCCESS;
}
PDH_FUNCTION
PlaiCreateTraceQuery( HKEY hkeyQuery )
{
PDH_STATUS pdhStatus;
DWORD dwValue;
dwValue = 0;
pdhStatus = PlaiWriteRegistryDwordValue( hkeyQuery, szTraceProviderCount, &dwValue );
dwValue = 128;
PlaiWriteRegistryDwordValue( hkeyQuery, szTraceBufferSize, &dwValue );
dwValue = 8;
PlaiWriteRegistryDwordValue( hkeyQuery, szTraceBufferMin, &dwValue );
dwValue = 32;
PlaiWriteRegistryDwordValue( hkeyQuery, szTraceBufferMax, &dwValue );
dwValue = 0;
PlaiWriteRegistryDwordValue( hkeyQuery, szTraceFlushInterval, &dwValue );
dwValue = 0;
PlaiWriteRegistryDwordValue( hkeyQuery, szTraceMode, &dwValue );
PlaiWriteRegistryStringValue( hkeyQuery, szTraceProviderList, REG_MULTI_SZ, NULL, 0 );
dwValue =
PLA_TLI_ENABLE_KERNEL_TRACE |
PLA_TLI_ENABLE_PROCESS_TRACE |
PLA_TLI_ENABLE_THREAD_TRACE |
PLA_TLI_ENABLE_DISKIO_TRACE |
PLA_TLI_ENABLE_NETWORK_TCPIP_TRACE;
dwValue = PLA_DATASTORE_SIZE_MB|PLA_DATASTORE_APPEND;
PlaiWriteRegistryDwordValue( hkeyQuery, szDatastoreAttributes, &dwValue );
PlaiWriteRegistryDwordValue( hkeyQuery, szTraceFlags, &dwValue );
dwValue = PLA_SEQ_TRACE_FILE;
PlaiWriteRegistryDwordValue( hkeyQuery, szLogFileType, &dwValue );
PlaiWriteRegistryLastModified ( hkeyQuery );
return ERROR_SUCCESS;
}
PDH_FUNCTION
PdhPlaCreateA( LPSTR /*strName*/, LPSTR /*strComputer*/, PPDH_PLA_INFO_A /*pInfo*/ )
{
return PDH_NOT_IMPLEMENTED;
}
PDH_FUNCTION
PdhPlaCreateW( LPWSTR strName, LPWSTR strComputer, PPDH_PLA_INFO_W pInfo )
{
PDH_STATUS pdhStatus;
PDH_STATUS pdhWarning = ERROR_SUCCESS;
HKEY hkeyQuery = NULL;
HKEY rhkeyLogQueries = NULL;
BOOL bMutex = FALSE;
VALIDATE_QUERY( strName );
LPWSTR szName = PlaiStringDuplicate( strName );
LPWSTR szComputer = PlaiStringDuplicate( strComputer );
CHECK_NAMES( szName, szComputer, strComputer );
pdhStatus = PlaiScanForInvalidChar( szName );
CHECK_STATUS(pdhStatus);
pdhStatus = PlaiConnectAndLockQuery( szComputer, szName, hkeyQuery );
if( ERROR_SUCCESS == pdhStatus ){
bMutex = TRUE;
pdhStatus = PDH_PLA_ERROR_ALREADY_EXISTS;
goto cleanup;
}
pdhStatus = PdhPlaValidateInfoW( szName, szComputer, pInfo );
switch( SEVERITY(pdhStatus) ){
case STATUS_SEVERITY_ERROR:
goto cleanup;
case STATUS_SEVERITY_WARNING:
pdhWarning = pdhStatus;
pdhStatus = ERROR_SUCCESS;
}
pdhStatus = PlaiConnectToRegistry( szComputer, rhkeyLogQueries, TRUE );
if( ERROR_SUCCESS == pdhStatus ){
DWORD dwStatus;
dwStatus = WAIT_FOR_AND_LOCK_MUTEX(hPdhPlaMutex);
if( ERROR_SUCCESS == dwStatus || WAIT_ABANDONED == dwStatus ){
bMutex = TRUE;
pdhStatus = PlaiInitializeNewQuery (
rhkeyLogQueries,
hkeyQuery,
szComputer,
szName
);
switch( pInfo->dwType ){
case PLA_COUNTER_LOG:
pdhStatus = PlaiCreateCounterQuery( hkeyQuery );
break;
case PLA_TRACE_LOG:
pdhStatus = PlaiCreateTraceQuery( hkeyQuery );
break;
}
}else{
pdhStatus = PlaiErrorToPdhStatus( dwStatus );
}
}
if( ERROR_SUCCESS == pdhStatus ){
pdhStatus = PlaiSetInfo( szComputer, hkeyQuery, pInfo );
}
if( bMutex ){
RELEASE_MUTEX(hPdhPlaMutex);
bMutex = FALSE;
}
__try {
if( ERROR_SUCCESS == pdhStatus && (pInfo->dwMask & PLA_INFO_FLAG_USER) ){
pdhStatus = PdhPlaSetRunAsW( szName, szComputer, pInfo->strUser, pInfo->strPassword );
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
if( ERROR_SUCCESS == pdhStatus ){
DWORD dwStatus;
dwStatus = WAIT_FOR_AND_LOCK_MUTEX(hPdhPlaMutex);
if( ERROR_SUCCESS == dwStatus || WAIT_ABANDONED == dwStatus ){
DWORD dwValue;
bMutex = TRUE;
switch( pInfo->dwType ){
case PLA_COUNTER_LOG:
dwValue = PLA_COUNTER_LOG;
pdhStatus = PlaiWriteRegistryDwordValue( hkeyQuery, szLogType, &dwValue );
break;
case PLA_TRACE_LOG:
dwValue = PLA_TRACE_LOG;
pdhStatus = PlaiWriteRegistryDwordValue( hkeyQuery, szLogType, &dwValue );
break;
}
}else{
pdhStatus = PlaiErrorToPdhStatus( dwStatus );
}
}
cleanup:
if( bMutex ){
RELEASE_MUTEX(hPdhPlaMutex);
}
if ( NULL != hkeyQuery ) {
RegCloseKey ( hkeyQuery );
}
if( SUCCEEDED( pdhStatus ) ){
pdhStatus = PlaiSynchronize( szComputer );
DWORD dwMask;
__try {
dwMask = pInfo->dwMask;
} __except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
if( ERROR_SUCCESS == pdhStatus && (dwMask & PLA_INFO_FLAG_BEGIN) ){
PlaiUpdateServiceMode( szComputer );
}
}else if( PDH_PLA_ERROR_ALREADY_EXISTS != pdhStatus ){
PdhPlaDeleteW( szName, szComputer );
}
if( ERROR_SUCCESS == pdhStatus ){
pdhStatus = pdhWarning;
}
G_FREE( szName );
G_FREE( szComputer );
return pdhStatus;
}
/*****************************************************************************\
PdhPlaDelete
Deletes an existing log query
Arguments:
LPTSTR strName
Log Name
LPTSTR strComputer
Computer to connect to
Return:
ERROR_SUCCESS
\*****************************************************************************/
PDH_FUNCTION
PdhPlaDeleteA( LPSTR strName, LPSTR strComputer )
{
PDH_STATUS pdhStatus;
LPWSTR wstrName = NULL;
LPWSTR wstrComputer = NULL;
VALIDATE_QUERY( strName );
pdhStatus = Plaiatow( strComputer, wstrComputer );
if( ERROR_SUCCESS == pdhStatus ){
pdhStatus = Plaiatow( strName, wstrName );
if( ERROR_SUCCESS == pdhStatus ){
pdhStatus = PdhPlaDeleteW( wstrName, wstrComputer );
}
}
G_FREE( wstrComputer );
G_FREE( wstrName );
return pdhStatus;
}
PDH_FUNCTION
PdhPlaDeleteW( LPWSTR strName, LPWSTR strComputer )
{
DWORD dwStatus = ERROR_SUCCESS;
PDH_STATUS pdhStatus;
HKEY hkeyLogQueries = NULL;
VALIDATE_QUERY( strName );
LPWSTR szName = PlaiStringDuplicate( strName );
LPWSTR szComputer = PlaiStringDuplicate( strComputer );
CHECK_NAMES( szName, szComputer, strComputer );
pdhStatus = PlaiConnectToRegistry ( szComputer, hkeyLogQueries, TRUE );
if( ERROR_SUCCESS == pdhStatus ){
dwStatus = WAIT_FOR_AND_LOCK_MUTEX( hPdhPlaMutex );
if( ERROR_SUCCESS == dwStatus || WAIT_ABANDONED == dwStatus ){
DWORD nCollections = 0;
DWORD nMaxSubKeyLength = 0;
dwStatus = RegQueryInfoKey(
hkeyLogQueries,
NULL,
NULL,
NULL,
&nCollections,
&nMaxSubKeyLength,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
);
if( ERROR_SUCCESS == dwStatus ){
LPWSTR strCollection;
LPWSTR strQueryName = NULL;
DWORD dwQueryName = 0;
HKEY hkeyQuery = NULL;
DWORD dwSize = (sizeof(WCHAR)*(nMaxSubKeyLength+1));
strCollection = (LPWSTR)G_ALLOC( dwSize );
if( strCollection ){
BOOL bFound = FALSE;
for( ULONG i = 0; i<nCollections; i++ ){
dwStatus = RegEnumKey( hkeyLogQueries, i, strCollection, dwSize );
if( ERROR_SUCCESS == dwStatus ) {
dwStatus = RegOpenKeyExW (
hkeyLogQueries,
strCollection,
0,
KEY_READ|KEY_WRITE,
&hkeyQuery
);
if( ERROR_SUCCESS == dwStatus && !PlaiIsStringEmpty( strCollection ) ){
if( !_wcsicmp( strCollection, strName ) ){
bFound = TRUE;
}else{
PlaiReadRegistryStringValue( hkeyQuery, szCollection, READ_REG_MUI, &strQueryName, &dwQueryName );
if( !PlaiIsStringEmpty( strQueryName ) ){
if( !_wcsicmp( strQueryName, szName ) ){
bFound = TRUE;
}
}
}
if( bFound ){
DWORD dwState;
dwStatus = PlaiReadRegistryDwordValue(
hkeyQuery,
szCurrentState,
&dwState );
if( ERROR_SUCCESS == dwStatus ){
if( PLA_QUERY_RUNNING == dwState ){
PlaiGetServiceState( szComputer, dwState );
if( dwState != SERVICE_STOPPED ){
dwStatus = ERROR_SERVICE_ALREADY_RUNNING;
}
}
}
if( ERROR_SUCCESS == dwStatus ){
RegCloseKey( hkeyQuery );
dwStatus = RegDeleteKey( hkeyLogQueries, strCollection );
}
break;
}
dwStatus = ERROR_FILE_NOT_FOUND;
if ( NULL != hkeyQuery ) {
RegCloseKey ( hkeyQuery );
}
}
}
}
G_FREE( strQueryName );
G_FREE( strCollection );
}else{
dwStatus = ERROR_OUTOFMEMORY;
}
}
}
RegCloseKey ( hkeyLogQueries );
RELEASE_MUTEX(hPdhPlaMutex);
}else{
return pdhStatus;
}
if( ERROR_SUCCESS == dwStatus ){
PlaiSynchronize( szComputer );
PlaiUpdateServiceMode( szComputer );
}
cleanup:
G_FREE( szName );
G_FREE( szComputer );
return PlaiErrorToPdhStatus( dwStatus );
}
/*****************************************************************************\
PdhPlaSetItemList
Sets the list of Items for a log query
Arguments:
LPTSTR strName
Log Name
LPTSTR strComputer
Computer to connect to
LPTSTR mszItems
Multistring of the Items for the query to collect. Any
existing Items will be overwritten.
ULONG length
Length of the mszItems buffer
Return:
PDH_INVALID_ARGUMENT
The query does not exist or pItems->dwType != Log Type
ERROR_SUCCESS
\*****************************************************************************/
PDH_FUNCTION
PlaiIsKernel( LPWSTR mszGuid, BOOL* pbKernel, ULONG* pnCount )
{
DWORD dwStatus;
LPTSTR strGuid = mszGuid;
UNICODE_STRING strKernel;
*pbKernel = FALSE;
*pnCount = 0;
dwStatus = RtlStringFromGUID( SystemTraceControlGuid, &strKernel );
if( ERROR_SUCCESS != dwStatus ){
return PlaiErrorToPdhStatus( dwStatus );
}
if( NULL != mszGuid ){
while( *strGuid != L'\0' ){
if( ! wcscmp( strGuid, strKernel.Buffer ) ){
*pbKernel = TRUE;
}
strGuid += (wcslen( strGuid) + 1 );
(*pnCount)++;
}
}
RtlFreeUnicodeString( &strKernel );
return PlaiErrorToPdhStatus( dwStatus );
}
PDH_FUNCTION
PlaiSetItemList(
HKEY hkeyQuery,
PPDH_PLA_ITEM_W pItems
)
{
PDH_STATUS pdhStatus;
DWORD dwValue;
pdhStatus = PlaiReadRegistryDwordValue( hkeyQuery, szLogType, &dwValue );
__try {
if( ERROR_SUCCESS == pdhStatus &&
(dwValue != pItems->dwType &&
PLA_NEW_LOG != dwValue) ){
pdhStatus = PDH_PLA_ERROR_TYPE_MISMATCH;
}
if( ERROR_SUCCESS == pdhStatus ){
switch( pItems->dwType ){
case PLA_TRACE_LOG:
{
BOOL bKernel;
ULONG nCount;
pdhStatus = PlaiIsKernel( pItems->strProviders, &bKernel, &nCount );
if( ERROR_SUCCESS != pdhStatus ){
return pdhStatus;
}
if( bKernel ){
if( nCount == 1 ){
DWORD dwFlags = Plaihextoi( pItems->strFlags );
DWORD dwInternal = 0;
pdhStatus = PlaiTranslateKernelFlags( &dwInternal, &dwFlags );
pdhStatus = PlaiWriteRegistryDwordValue(
hkeyQuery,
szTraceFlags,
&dwInternal
);
pdhStatus = PlaiWriteRegistryStringValue(
hkeyQuery,
szTraceProviderList,
REG_MULTI_SZ,
NULL,
0
);
}else{
return PDH_INVALID_ARGUMENT;
}
}else{
DWORD dwFlags = 0;
pdhStatus = PlaiWriteRegistryDwordValue(
hkeyQuery,
szTraceFlags,
&dwFlags
);
pdhStatus = PlaiWriteRegistryStringValue(
hkeyQuery,
szTraceProviderList,
REG_MULTI_SZ,
pItems->strProviders,
PlaMszStrLenW( pItems->strProviders )
);
}
pdhStatus = PlaiWriteRegistryStringValue(
hkeyQuery,
szTraceProviderFlags,
REG_MULTI_SZ,
pItems->strFlags,
PlaMszStrLenW( pItems->strFlags )
);
pdhStatus = PlaiWriteRegistryStringValue(
hkeyQuery,
szTraceProviderLevels,
REG_MULTI_SZ,
pItems->strLevels,
PlaMszStrLenW( pItems->strLevels )
);
break;
}
case PLA_COUNTER_LOG:
{
if( PLA_ENGLISH ){
pdhStatus = PlaiWriteRegistryStringValue(
hkeyQuery,
szPerfCounterList,
REG_MULTI_SZ,
pItems->strCounters,
PlaMszStrLenW( pItems->strCounters )
);
}else{
LPWSTR strCounter = pItems->strCounters;
pdhStatus = PlaiWriteRegistryStringValue(
hkeyQuery,
szPerfCounterList,
REG_MULTI_SZ,
L"\0",
sizeof(WCHAR)
);
if( ERROR_SUCCESS == pdhStatus && NULL != strCounter ){
PDH_PLA_ITEM_W Counter;
Counter.dwType = PLA_COUNTER_LOG;
while( *strCounter != L'\0' ){
Counter.strCounters = strCounter;
pdhStatus = PlaiAddItem( hkeyQuery, &Counter );
if( ERROR_SUCCESS != pdhStatus ){
break;
}
strCounter += (wcslen(strCounter)+1);
}
}
}
}
break;
}
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
return pdhStatus;
}
PDH_FUNCTION
PdhPlaSetItemListA(
LPSTR /*strName*/,
LPSTR /*strComputer*/,
PPDH_PLA_ITEM_A /*pItems*/
)
{
return PDH_NOT_IMPLEMENTED;
}
PDH_FUNCTION
PdhPlaSetItemListW(
LPWSTR strName,
LPWSTR strComputer,
PPDH_PLA_ITEM_W pItems
)
{
PDH_STATUS pdhStatus;
HKEY hkeyQuery = NULL;
VALIDATE_QUERY( strName );
LPWSTR szName = PlaiStringDuplicate( strName );
LPWSTR szComputer = PlaiStringDuplicate( strComputer );
CHECK_NAMES( szName, szComputer, strComputer );
pdhStatus = PlaiConnectAndLockQuery( szComputer, szName, hkeyQuery );
if( ERROR_SUCCESS == pdhStatus ){
pdhStatus = PlaiSetItemList( hkeyQuery, pItems );
}
RELEASE_MUTEX(hPdhPlaMutex);
if ( NULL != hkeyQuery ) {
RegCloseKey ( hkeyQuery );
}
cleanup:
G_FREE( szName );
G_FREE( szComputer );
return pdhStatus;
}
/*****************************************************************************\
PdhPlaAddItem
Sets the list of items ( counters or providers ) for a log query
Arguments:
LPTSTR strName
Log Name
LPTSTR strComputer
Computer to connect to
LPTSTR strItem
A single item to be added to the list of Items or providers
the query will collect
Return:
PDH_MEMORY_ALLOCATION_FAILURE
The total list of items will not fit in the available
memory.
PDH_PLA_COLLECTION_NOT_FOUND
The query does not exist
ERROR_SUCCESS
\*****************************************************************************/
PDH_FUNCTION
PlaiRegAddItem(
HKEY hkeyQuery,
LPCWSTR strList,
LPWSTR strItem
)
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
LPWSTR strOldList = NULL;
LPWSTR strNewList = NULL;
DWORD dwNewDataSize = ( wcslen( strItem ) ) * sizeof(WCHAR);
DWORD dwOldDataSize = 0;
DWORD dwTermSize = sizeof(WCHAR) * 2;
if( PlaiIsStringEmpty( strItem ) ){
return PDH_INVALID_ARGUMENT;
}
if( ERROR_SUCCESS == pdhStatus ){
pdhStatus = PlaiReadRegistryStringValue( hkeyQuery, strList, 0, &strOldList, &dwOldDataSize );
strNewList = (LPWSTR)G_ALLOC( dwOldDataSize + dwNewDataSize + dwTermSize);
if( NULL == strNewList ){
G_FREE( strOldList );
return PDH_MEMORY_ALLOCATION_FAILURE;
}
ZeroMemory( strNewList, dwOldDataSize + dwNewDataSize + dwTermSize );
if( dwOldDataSize ){
memcpy( strNewList, strOldList, dwOldDataSize );
memcpy( (((PUCHAR)strNewList) + (dwOldDataSize-sizeof(WCHAR))), strItem, dwNewDataSize );
}else{
memcpy( strNewList, strItem, dwNewDataSize );
}
pdhStatus = PlaiWriteRegistryStringValue(
hkeyQuery,
strList,
REG_MULTI_SZ,
strNewList,
(dwOldDataSize + dwNewDataSize + sizeof(WCHAR))
);
}
G_FREE( strOldList );
G_FREE( strNewList );
return pdhStatus;
}
PDH_FUNCTION
PlaiAddItem(
HKEY hkeyQuery,
PPDH_PLA_ITEM_W pItem
)
{
PDH_STATUS pdhStatus;
DWORD dwValue;
pdhStatus = PlaiReadRegistryDwordValue( hkeyQuery, szLogType, &dwValue );
__try {
if( ERROR_SUCCESS == pdhStatus && dwValue != pItem->dwType && PLA_NEW_LOG != dwValue ){
pdhStatus = PDH_PLA_ERROR_TYPE_MISMATCH;
}
if( ERROR_SUCCESS == pdhStatus ){
switch( pItem->dwType ){
case PLA_TRACE_LOG:
{
BOOL bKernel;
ULONG nCount;
pdhStatus = PlaiIsKernel( pItem->strProviders, &bKernel, &nCount );
if( ERROR_SUCCESS == pdhStatus ){
if( bKernel ){
DWORD dwFlags = Plaihextoi( pItem->strFlags );
pdhStatus = PlaiWriteRegistryDwordValue(
hkeyQuery,
szTraceFlags,
&dwFlags
);
pdhStatus = PlaiWriteRegistryStringValue(
hkeyQuery,
szTraceProviderList,
REG_MULTI_SZ,
NULL,
0
);
}else{
DWORD dwFlags = 0;
pdhStatus = PlaiWriteRegistryDwordValue(
hkeyQuery,
szTraceFlags,
&dwFlags
);
pdhStatus = PlaiRegAddItem( hkeyQuery, szTraceProviderList, pItem->strProviders );
if( ERROR_SUCCESS == pdhStatus ){
pdhStatus = PlaiRegAddItem( hkeyQuery, szTraceProviderFlags, pItem->strFlags );
if( ERROR_SUCCESS == pdhStatus ){
pdhStatus = PlaiRegAddItem( hkeyQuery, szTraceProviderLevels, pItem->strLevels );
}
}
}
}
}
break;
case PLA_COUNTER_LOG:
{
if( PLA_ENGLISH ){
pdhStatus = PlaiRegAddItem( hkeyQuery, szPerfCounterList, pItem->strCounters );
}else{
LPWSTR strLocaleCounter = pItem->strCounters;
LPWSTR strEnglishCounter = NULL;
DWORD dwSize = MAX_PATH;
strEnglishCounter = (LPWSTR)G_ALLOC( dwSize*sizeof(WCHAR) );
if( NULL != strEnglishCounter ){
pdhStatus = PdhTranslate009CounterW( strLocaleCounter, strEnglishCounter, &dwSize );
if( PDH_MORE_DATA == pdhStatus ){
LPTSTR strBuffer = (LPWSTR)G_REALLOC( strEnglishCounter, (dwSize*sizeof(WCHAR)) );
if( NULL != strBuffer ){
strEnglishCounter = strBuffer;
pdhStatus = PdhTranslate009CounterW( strLocaleCounter, strEnglishCounter, &dwSize );
}else{
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
}
}
if( ERROR_SUCCESS == pdhStatus ){
pdhStatus = PlaiRegAddItem( hkeyQuery, szPerfCounterList, strEnglishCounter );
}else{
pdhStatus = PlaiRegAddItem( hkeyQuery, szPerfCounterList, pItem->strCounters );
}
G_FREE( strEnglishCounter );
}else{
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
}
}
}
}
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
return pdhStatus;
}
PDH_FUNCTION
PdhPlaAddItemA(
LPSTR strName,
LPSTR strComputer,
PPDH_PLA_ITEM_A pItem
)
{
return PDH_NOT_IMPLEMENTED;
}
PDH_FUNCTION
PdhPlaAddItemW(
LPWSTR strName,
LPWSTR strComputer,
PPDH_PLA_ITEM_W pItem
)
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
HKEY hkeyQuery = NULL;
VALIDATE_QUERY( strName );
LPWSTR szName = PlaiStringDuplicate( strName );
LPWSTR szComputer = PlaiStringDuplicate( strComputer );
CHECK_NAMES( szName, szComputer, strComputer );
pdhStatus = PlaiConnectAndLockQuery( szComputer, szName, hkeyQuery );
if( ERROR_SUCCESS == pdhStatus ){
pdhStatus = PlaiAddItem( hkeyQuery, pItem );
RELEASE_MUTEX(hPdhPlaMutex);
}
cleanup:
if ( NULL != hkeyQuery ) {
RegCloseKey ( hkeyQuery );
}
G_FREE( szName );
G_FREE( szComputer );
return pdhStatus;
}
/*****************************************************************************\
PdhPlaRemoveAllItems
Removes all entries for the list of Items the log query will collect
Arguments:
LPTSTR strName
Log Name
LPTSTR strComputer
Computer to connect to
Return:
PDH_INVALID_ARGUMENT
The query does not exist
ERROR_SUCCESS
\*****************************************************************************/
PDH_FUNCTION
PdhPlaRemoveAllItemsA( LPSTR strName, LPSTR strComputer )
{
PDH_STATUS pdhStatus;
LPWSTR wstrName = NULL;
LPWSTR wstrComputer = NULL;
VALIDATE_QUERY( strName );
pdhStatus = Plaiatow( strComputer, wstrComputer );
if( ERROR_SUCCESS == pdhStatus ){
pdhStatus = Plaiatow( strName, wstrName );
if( ERROR_SUCCESS == pdhStatus ){
pdhStatus = PdhPlaRemoveAllItemsW( wstrName, wstrComputer );
}
}
G_FREE( wstrComputer );
G_FREE( wstrName );
return pdhStatus;
}
PDH_FUNCTION
PdhPlaRemoveAllItemsW(
LPWSTR strName,
LPWSTR strComputer
)
{
PDH_STATUS pdhStatus;
HKEY hkeyQuery = NULL;
VALIDATE_QUERY( strName );
LPWSTR szName = PlaiStringDuplicate( strName );
LPWSTR szComputer = PlaiStringDuplicate( strComputer );
CHECK_NAMES( szName, szComputer, strComputer );
pdhStatus = PlaiConnectAndLockQuery( szComputer, szName, hkeyQuery );
if( ERROR_SUCCESS == pdhStatus ){
DWORD dwValue;
pdhStatus = PlaiReadRegistryDwordValue( hkeyQuery, szLogType, &dwValue );
if( ERROR_SUCCESS == pdhStatus ){
switch( dwValue ){
case PLA_TRACE_LOG:
pdhStatus = PlaiWriteRegistryStringValue(
hkeyQuery,
szTraceProviderList,
REG_MULTI_SZ, L"\0",
sizeof(WCHAR)
);
pdhStatus = PlaiWriteRegistryStringValue(
hkeyQuery,
szTraceProviderFlags,
REG_MULTI_SZ, L"\0",
sizeof(WCHAR)
);
pdhStatus = PlaiWriteRegistryStringValue(
hkeyQuery,
szTraceProviderLevels,
REG_MULTI_SZ, L"\0",
sizeof(WCHAR)
);
break;
case PLA_COUNTER_LOG:
pdhStatus = PlaiWriteRegistryStringValue(
hkeyQuery,
szPerfCounterList,
REG_MULTI_SZ,
L"\0",
sizeof(WCHAR)
);
break;
}
}
RELEASE_MUTEX(hPdhPlaMutex);
}
cleanup:
if ( NULL != hkeyQuery ) {
RegCloseKey ( hkeyQuery );
}
G_FREE( szName );
G_FREE( szComputer );
return pdhStatus;
}
/*****************************************************************************\
PdhPlaGetInfo
Fills the PDH_PLA_INFO structure with the properties of the requested
log query.
Arguments:
LPTSTR strName
Log Name
LPTSTR strComputer
Computer to connect to
PPDH_PLA_INFO pInfo
Information block
Return:
PDH_INVALID_ARGUMENT
The query does not exist
ERROR_SUCCESS
\*****************************************************************************/
PDH_FUNCTION
PlaiAssignInfoString(
LPWSTR strName,
HKEY hkeyQuery,
PPDH_PLA_INFO_W pInfo,
LPDWORD dwTotalSize,
LPWSTR& strCopy,
DWORD dwBufferSize,
DWORD dwMask,
DWORD dwQueryMask,
LPCTSTR szKey,
DWORD dwRegFlag
)
{
LPWSTR strKeyValue = NULL;
LPWSTR strInfo = NULL;
PDH_STATUS pdhStatus = ERROR_SUCCESS;
DWORD dwKeySize = 0;
BOOL bRead = TRUE;
VALIDATE_QUERY( strName );
if( pInfo != NULL ){
if( !(dwQueryMask & dwMask) ){
bRead = FALSE;
}
}
if( bRead ){
pdhStatus = PlaiReadRegistryStringValue( hkeyQuery, szKey, dwRegFlag, &strKeyValue, &dwKeySize );
if( (ERROR_SUCCESS == pdhStatus) &&
(!PlaiIsStringEmpty(strKeyValue)) &&
(dwKeySize > sizeof(WCHAR)) ){
*dwTotalSize += dwKeySize;
}else if( dwMask == PLA_INFO_FLAG_USER ){
G_FREE( strKeyValue );
strKeyValue = (LPWSTR)G_ALLOC(PLA_ACCOUNT_BUFFER*sizeof(WCHAR) );
if( strKeyValue != NULL ){
dwKeySize = LoadStringW(
(HINSTANCE)ThisDLLHandle,
IDS_DEFAULT_ACCOUNT,
strKeyValue,
PLA_ACCOUNT_BUFFER
);
if( dwKeySize ){
dwKeySize = BYTE_SIZE( strKeyValue ) + sizeof(WCHAR);
*dwTotalSize += dwKeySize;
}
}else{
bRead = FALSE;
}
}else if( (dwMask == PLA_INFO_FLAG_LOGGERNAME) ||
((dwMask == PLA_INFO_FLAG_FILENAME) && (ERROR_SUCCESS != pdhStatus)) ){
G_FREE( strKeyValue );
dwKeySize = BYTE_SIZE( strName ) + sizeof(WCHAR);
*dwTotalSize += dwKeySize;
strKeyValue = (LPWSTR)G_ALLOC(dwKeySize);
if( NULL != strKeyValue && !PlaiIsStringEmpty( strName ) ){
StringCbCopy( strKeyValue, dwKeySize, strName );
}else{
bRead = FALSE;
}
}else{
dwKeySize = 0;
}
}
if( pInfo != NULL && bRead ){
if( dwKeySize && (dwBufferSize >= *dwTotalSize) ){
memcpy( (void*)strCopy, (void*)strKeyValue, dwKeySize );
strInfo = strCopy;
strCopy = (LPWSTR)((PUCHAR)strCopy + dwKeySize );
}
__try{
switch( dwMask ){
case PLA_INFO_FLAG_COUNTERS:
pInfo->dwMask |= PLA_INFO_FLAG_COUNTERS;
pInfo->Perf.piCounterList.strCounters = strInfo;
break;
case PLA_INFO_FLAG_SQLNAME:
pInfo->dwMask |= PLA_INFO_FLAG_SQLNAME;
pInfo->strSqlName = strInfo;
break;
case PLA_INFO_FLAG_FILENAME:
pInfo->dwMask |= PLA_INFO_FLAG_FILENAME;
pInfo->strBaseFileName = strInfo;
break;
case PLA_INFO_FLAG_PROVIDERS:
pInfo->dwMask |= PLA_INFO_FLAG_PROVIDERS;
pInfo->Trace.piProviderList.strProviders = strInfo;
break;
case PLA_INFO_FLAG_LOGGERNAME:
pInfo->dwMask |= PLA_INFO_FLAG_LOGGERNAME;
pInfo->Trace.strLoggerName = strInfo;
break;
case PLA_INFO_FLAG_USER:
pInfo->dwMask |= PLA_INFO_FLAG_USER;
pInfo->strUser = strInfo;
break;
case PLA_INFO_FLAG_DEFAULTDIR:
pInfo->dwMask |= PLA_INFO_FLAG_DEFAULTDIR;
pInfo->strDefaultDir = strInfo;
break;
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
}
}
G_FREE( strKeyValue );
return ERROR_SUCCESS;
}
PDH_FUNCTION
PdhPlaGetInfoA(
LPSTR /*strName*/,
LPSTR /*strComputer*/,
LPDWORD /*pdwBufferSize*/,
PPDH_PLA_INFO_A /*pInfo*/
)
{
return PDH_NOT_IMPLEMENTED;
}
PDH_FUNCTION
PdhPlaGetInfoW(
LPWSTR strName,
LPWSTR strComputer,
LPDWORD pdwBufferSize,
PPDH_PLA_INFO_W pInfo
)
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
HKEY hkeyQuery = NULL;
DWORD dwSize = 0;
LPWSTR strCopy = NULL;
LPWSTR strKey = NULL;
DWORD dwKeySize = 0;
DWORD dwMask = 0;
VALIDATE_QUERY( strName );
DWORD dwBufferSize;
__try {
dwBufferSize = *pdwBufferSize;
if( pInfo != NULL ){
dwMask = pInfo->dwMask;
pInfo->dwMask = 0;
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
CHECK_STATUS( pdhStatus );
LPWSTR szName = PlaiStringDuplicate( strName );
LPWSTR szComputer = PlaiStringDuplicate( strComputer );
CHECK_NAMES( szName, szComputer, strComputer );
pdhStatus = PlaiConnectAndLockQuery( szComputer, szName, hkeyQuery, FALSE );
if( ERROR_SUCCESS == pdhStatus ){
DWORD dwType = 0;
dwSize = sizeof(PDH_PLA_INFO_W);
if( pInfo == NULL ){
dwBufferSize = 0;
}else{
strCopy = (LPWSTR)( (PUCHAR)pInfo+ sizeof(PDH_PLA_INFO_W) );
}
PlaiReadRegistryDwordValue( hkeyQuery, szLogType, &dwType );
if( pInfo != NULL ){
__try {
if( dwMask & PLA_INFO_FLAG_TYPE ){
pInfo->dwMask |= PLA_INFO_FLAG_TYPE;
pInfo->dwType = dwType;
}
if( dwMask & PLA_INFO_FLAG_AUTOFORMAT ){
pdhStatus = PlaiReadRegistryDwordValue( hkeyQuery, szLogAutoFormat, &pInfo->dwAutoNameFormat );
if( ERROR_SUCCESS == pdhStatus ){
pInfo->dwMask |= PLA_INFO_FLAG_AUTOFORMAT;
}
}
if( dwMask & PLA_INFO_FLAG_SRLNUMBER ){
pdhStatus = PlaiReadRegistryDwordValue( hkeyQuery, szLogSerialNumber, &pInfo->dwLogFileSerialNumber );
if( ERROR_SUCCESS == pdhStatus ){
pInfo->dwMask |= PLA_INFO_FLAG_SRLNUMBER;
}
}
if( dwMask & PLA_INFO_FLAG_REPEAT ){
pdhStatus = PlaiReadRegistryPlaTime( hkeyQuery, szRepeatSchedule, &pInfo->ptRepeat );
if( ERROR_SUCCESS == pdhStatus ){
pInfo->dwMask |= PLA_INFO_FLAG_REPEAT;
}
}
if( dwMask & PLA_INFO_FLAG_STATUS ){
pdhStatus = PlaiReadRegistryDwordValue( hkeyQuery, szCurrentState, &pInfo->dwStatus );
if( ERROR_SUCCESS == pdhStatus ){
pInfo->dwMask |= PLA_INFO_FLAG_STATUS;
}
}
if( dwMask & PLA_INFO_FLAG_FORMAT ){
pdhStatus = PlaiReadRegistryDwordValue( hkeyQuery, szLogFileType, &pInfo->dwFileFormat );
if( ERROR_SUCCESS == pdhStatus ){
pInfo->dwMask |= PLA_INFO_FLAG_FORMAT;
}
}
if( dwMask & PLA_INFO_FLAG_DATASTORE ){
pdhStatus = PlaiReadRegistryDwordValue( hkeyQuery, szDatastoreAttributes, &pInfo->dwDatastoreAttributes );
if( ERROR_SUCCESS == pdhStatus ){
pInfo->dwMask |= PLA_INFO_FLAG_DATASTORE;
}
}
if( dwMask & PLA_INFO_FLAG_CRTNEWFILE ){
pdhStatus = PlaiReadRegistryPlaTime( hkeyQuery, szCreateNewFile, &pInfo->ptCreateNewFile);
if( ERROR_SUCCESS == pdhStatus ){
pInfo->dwMask |= PLA_INFO_FLAG_CRTNEWFILE;
}
}
if( dwMask & PLA_INFO_FLAG_END ){
pdhStatus = PlaiReadRegistryPlaTime( hkeyQuery, szStop, &pInfo->ptLogEndTime );
if( ERROR_SUCCESS == pdhStatus ){
pInfo->dwMask |= PLA_INFO_FLAG_END;
}
}
if( dwMask & PLA_INFO_FLAG_BEGIN ){
pdhStatus = PlaiReadRegistryPlaTime( hkeyQuery, szStart, &pInfo->ptLogBeginTime );
if( ERROR_SUCCESS == pdhStatus ){
pInfo->dwMask |= PLA_INFO_FLAG_BEGIN;
}
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
pdhStatus = PlaiAssignInfoString( szName, hkeyQuery, pInfo, &dwSize, strCopy, dwBufferSize,
PLA_INFO_FLAG_FILENAME, dwMask, szLogBaseName, READ_REG_MUI );
pdhStatus = PlaiAssignInfoString( szName, hkeyQuery, pInfo, &dwSize, strCopy, dwBufferSize,
PLA_INFO_FLAG_USER, dwMask, szRunAs, 0 );
pdhStatus = PlaiAssignInfoString( szName, hkeyQuery, pInfo, &dwSize, strCopy, dwBufferSize,
PLA_INFO_FLAG_DEFAULTDIR, dwMask, szLogFolder, READ_REG_MUI );
__try {
switch( dwType ){
case PLA_TRACE_LOG: // Trace Fields
if( NULL != pInfo ){
if( dwMask & PLA_INFO_FLAG_MODE ){
pdhStatus = PlaiReadRegistryDwordValue( hkeyQuery, szTraceMode, &pInfo->Trace.dwMode );
if( ERROR_SUCCESS == pdhStatus ){
pInfo->dwMask |= PLA_INFO_FLAG_MODE;
}
}
if( dwMask & PLA_INFO_FLAG_BUFFERSIZE ){
pdhStatus = PlaiReadRegistryDwordValue( hkeyQuery, szTraceBufferSize, &pInfo->Trace.dwBufferSize );
if( ERROR_SUCCESS == pdhStatus ){
pInfo->dwMask |= PLA_INFO_FLAG_BUFFERSIZE;
}
}
if( dwMask & PLA_INFO_FLAG_PROVIDERS ){
pInfo->Trace.piProviderList.dwType = PLA_TRACE_LOG;
}
}
pdhStatus = PlaiAssignInfoString( szName, hkeyQuery, pInfo, &dwSize, strCopy, dwBufferSize,
PLA_INFO_FLAG_PROVIDERS, dwMask, szTraceProviderList, 0 );
pdhStatus = PlaiAssignInfoString( szName, hkeyQuery, pInfo, &dwSize, strCopy, dwBufferSize,
PLA_INFO_FLAG_LOGGERNAME, dwMask, szTraceLoggerName, 0 );
break;
case PLA_COUNTER_LOG: // Performance Fields
if( NULL != pInfo ){
if( dwMask & PLA_INFO_FLAG_COUNTERS ){
pInfo->Perf.piCounterList.dwType = PLA_COUNTER_LOG;
}
}
pdhStatus = PlaiAssignInfoString( szName, hkeyQuery, pInfo, &dwSize, strCopy, dwBufferSize,
PLA_INFO_FLAG_COUNTERS, dwMask, szPerfCounterList, 0 );
pdhStatus = PlaiAssignInfoString( szName, hkeyQuery, pInfo, &dwSize, strCopy, dwBufferSize,
PLA_INFO_FLAG_SQLNAME, dwMask, szSqlBaseName, 0 );
break;
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
RELEASE_MUTEX(hPdhPlaMutex);
}
if ( NULL != hkeyQuery ) {
RegCloseKey ( hkeyQuery );
}
__try {
*pdwBufferSize = dwSize;
} __except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
cleanup:
G_FREE( szName );
G_FREE( szComputer );
return pdhStatus;
}
/*****************************************************************************\
PdhPlaSetInfo
Sets the information in the log query to the parameters in the
PDH_PLA_INFO block according to the info mask.
Arguments:
LPTSTR strName
Log Name
LPTSTR strComputer
Computer to connect to
PPDH_PLA_INFO pInfo
Information block
Return:
PDH_INVALID_ARGUMENT
The query does not exist or pInfo is NULL
ERROR_SUCCESS
\*****************************************************************************/
PDH_FUNCTION
PlaiSetInfo(
LPWSTR strComputer,
HKEY hkeyQuery,
PPDH_PLA_INFO_W pInfo
)
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
DWORD dwType = 0;
DWORD dwFormat = 0;
DWORD dwDatastoreAttributes = 0;
__try {
// General Fields
if( pInfo->dwMask & PLA_INFO_FLAG_AUTOFORMAT ){
pdhStatus = PlaiWriteRegistryDwordValue( hkeyQuery, szLogAutoFormat, &pInfo->dwAutoNameFormat );
}
if( pInfo->dwMask & PLA_INFO_FLAG_REPEAT ){
pdhStatus = PlaiWriteRegistryPlaTime( hkeyQuery, szRepeatSchedule, &pInfo->ptRepeat );
}
if( pInfo->dwMask & PLA_INFO_FLAG_RUNCOMMAND ){
pdhStatus = PlaiWriteRegistryStringValue( hkeyQuery, szEOFCmd, REG_SZ, pInfo->strCommandFileName, 0 );
}
if( pInfo->dwMask & PLA_INFO_FLAG_CRTNEWFILE ){
pdhStatus = PlaiWriteRegistryPlaTime( hkeyQuery, szCreateNewFile, &pInfo->ptCreateNewFile );
}
if( pInfo->dwMask & PLA_INFO_FLAG_MAXLOGSIZE ){
pdhStatus = PlaiWriteRegistryDwordValue( hkeyQuery, szLogMaxSize, &pInfo->dwMaxLogSize );
}
if( pInfo->dwMask & (PLA_INFO_FLAG_SQLNAME|PLA_INFO_FLAG_FILENAME|PLA_INFO_FLAG_DEFAULTDIR) ){
if( pInfo->dwMask & PLA_INFO_FLAG_FORMAT ){
dwFormat = pInfo->dwFileFormat;
pdhStatus = ERROR_SUCCESS;
}else{
pdhStatus = PlaiReadRegistryDwordValue( hkeyQuery, szLogFileType, &dwFormat );
}
if( (ERROR_SUCCESS == pdhStatus) && (PLA_SQL_LOG == dwFormat) ){
if( pInfo->dwMask & PLA_INFO_FLAG_SQLNAME ){
pdhStatus = PlaiWriteRegistryStringValue( hkeyQuery, szSqlBaseName, REG_SZ, pInfo->strSqlName, 0 );
}else if( pInfo->dwMask & PLA_INFO_FLAG_FILENAME ){
pdhStatus = PlaiWriteRegistryStringValue( hkeyQuery, szSqlBaseName, REG_SZ, pInfo->strBaseFileName, 0 );
}else if( pInfo->dwMask & PLA_INFO_FLAG_DEFAULTDIR ){
pdhStatus = PlaiWriteRegistryStringValue( hkeyQuery, szSqlBaseName, REG_SZ, pInfo->strDefaultDir, 0 );
}
}else{
if( pInfo->dwMask & PLA_INFO_FLAG_SQLNAME ){
pdhStatus = PlaiWriteRegistryStringValue( hkeyQuery, szSqlBaseName, REG_SZ, pInfo->strSqlName, 0 );
}
if( pInfo->dwMask & PLA_INFO_FLAG_FILENAME ){
pdhStatus = PlaiWriteRegistryStringValue( hkeyQuery, szLogBaseName, REG_SZ, pInfo->strBaseFileName, 0 );
}
if( pInfo->dwMask & PLA_INFO_FLAG_DEFAULTDIR ){
pdhStatus = PlaiWriteRegistryStringValue( hkeyQuery, szLogFolder, REG_SZ, pInfo->strDefaultDir, 0 );
}
}
}
if( pInfo->dwMask & PLA_INFO_FLAG_TYPE ){
// Do not write it to the registry because it may be a new collection
dwType = pInfo->dwType;
}else{
PlaiReadRegistryDwordValue( hkeyQuery, szLogType, &dwType );
}
switch( dwType ){
case PLA_TRACE_LOG: // Trace Fields
if( pInfo->dwMask & PLA_INFO_FLAG_FORMAT ){
dwFormat = pInfo->dwFileFormat;
switch( dwFormat ){
case PLA_BIN_FILE: dwFormat = PLA_SEQ_TRACE_FILE; break;
case PLA_BIN_CIRC_FILE: dwFormat = PLA_CIRC_TRACE_FILE; break;
}
pdhStatus = PlaiWriteRegistryDwordValue( hkeyQuery, szLogFileType, &dwFormat );
}else{
PlaiReadRegistryDwordValue( hkeyQuery, szLogFileType, &dwFormat );
}
if( pInfo->dwMask & PLA_INFO_FLAG_DATASTORE ){
if( ! (pInfo->dwDatastoreAttributes & PLA_DATASTORE_APPEND_MASK ) ){
if( dwFormat == PLA_SEQ_TRACE_FILE ){
pInfo->dwDatastoreAttributes |= PLA_DATASTORE_APPEND;
}else{
pInfo->dwDatastoreAttributes |= PLA_DATASTORE_OVERWRITE;
}
}
if( ! (pInfo->dwDatastoreAttributes & PLA_DATASTORE_SIZE_MASK ) ){
pInfo->dwDatastoreAttributes |= PLA_DATASTORE_SIZE_MB;
}
pdhStatus = PlaiWriteRegistryDwordValue( hkeyQuery, szDatastoreAttributes, &pInfo->dwDatastoreAttributes );
}
if( pInfo->dwMask & PLA_INFO_FLAG_BUFFERSIZE ){
pdhStatus = PlaiWriteRegistryDwordValue( hkeyQuery, szTraceBufferSize, &pInfo->Trace.dwBufferSize );
}
if( pInfo->dwMask & PLA_INFO_FLAG_MINBUFFERS ){
pdhStatus = PlaiWriteRegistryDwordValue( hkeyQuery, szTraceBufferMin, &pInfo->Trace.dwMinimumBuffers );
}
if( pInfo->dwMask & PLA_INFO_FLAG_MAXBUFFERS ){
pdhStatus = PlaiWriteRegistryDwordValue( hkeyQuery, szTraceBufferMax, &pInfo->Trace.dwMaximumBuffers );
}
if( pInfo->dwMask & PLA_INFO_FLAG_FLUSHTIMER ){
pdhStatus = PlaiWriteRegistryDwordValue( hkeyQuery, szTraceFlushInterval, &pInfo->Trace.dwFlushTimer );
}
if( pInfo->dwMask & PLA_INFO_FLAG_MODE ){
pdhStatus = PlaiWriteRegistryDwordValue( hkeyQuery, szTraceMode, &pInfo->Trace.dwMode );
}
if( pInfo->dwMask & PLA_INFO_FLAG_LOGGERNAME ){
pdhStatus = PlaiWriteRegistryStringValue( hkeyQuery, szTraceLoggerName, REG_SZ, pInfo->Trace.strLoggerName, 0 );
}
if( pInfo->dwMask & PLA_INFO_FLAG_PROVIDERS ){
pdhStatus = PlaiSetItemList( hkeyQuery, &pInfo->Trace.piProviderList );
}
break;
case PLA_COUNTER_LOG: // Performance Fields
if( pInfo->dwMask & PLA_INFO_FLAG_FORMAT ){
dwFormat = pInfo->dwFileFormat;
switch( dwFormat ){
case PLA_CIRC_TRACE_FILE: dwFormat = PLA_BIN_CIRC_FILE; break;
case PLA_SEQ_TRACE_FILE: dwFormat = PLA_BIN_FILE; break;
}
pdhStatus = PlaiWriteRegistryDwordValue( hkeyQuery, szLogFileType, &dwFormat );
}else{
PlaiReadRegistryDwordValue( hkeyQuery, szLogFileType, &dwFormat );
}
if( pInfo->dwMask & PLA_INFO_FLAG_DATASTORE ){
if( PLA_SQL_LOG == dwFormat ){
pInfo->dwDatastoreAttributes = (pInfo->dwDatastoreAttributes & 0xFFFFFF00) |
PLA_DATASTORE_APPEND | PLA_DATASTORE_SIZE_ONE_RECORD;
}else{
if( ! (pInfo->dwDatastoreAttributes & PLA_DATASTORE_APPEND_MASK ) ){
if( dwFormat == PLA_BIN_FILE ){
dwDatastoreAttributes |= PLA_DATASTORE_APPEND;
}else{
dwDatastoreAttributes |= PLA_DATASTORE_OVERWRITE;
}
}
if( ! (pInfo->dwDatastoreAttributes & PLA_DATASTORE_SIZE_MASK ) ){
dwDatastoreAttributes |= PLA_DATASTORE_SIZE_KB;
}
}
pdhStatus = PlaiWriteRegistryDwordValue( hkeyQuery, szDatastoreAttributes, &pInfo->dwDatastoreAttributes );
}
if( pInfo->dwMask & PLA_INFO_FLAG_MAXLOGSIZE ){
DWORD dwMaxSize = pInfo->dwMaxLogSize;
PlaiReadRegistryDwordValue( hkeyQuery, szDatastoreAttributes, &dwDatastoreAttributes );
if( (dwDatastoreAttributes & PLA_DATASTORE_SIZE_MASK) == PLA_DATASTORE_SIZE_KB ){
dwMaxSize *= 1024;
}
pdhStatus = PlaiWriteRegistryDwordValue( hkeyQuery, szLogMaxSize, &dwMaxSize );
}
if( pInfo->dwMask & PLA_INFO_FLAG_INTERVAL ){
pdhStatus = PlaiWriteRegistryPlaTime( hkeyQuery, szSampleInterval, &pInfo->Perf.ptSampleInterval );
}
if( pInfo->dwMask & PLA_INFO_FLAG_COUNTERS ){
pdhStatus = PlaiSetItemList( hkeyQuery, &pInfo->Perf.piCounterList );
}
break;
case PLA_ALERT:
break;
}
if( (pInfo->dwMask & PLA_INFO_FLAG_BEGIN) || (pInfo->dwMask & PLA_INFO_FLAG_END) ){
PDH_TIME_INFO info;
ZeroMemory( &info, sizeof(PDH_TIME_INFO) );
if(pInfo->dwMask & PLA_INFO_FLAG_BEGIN){
info.StartTime = pInfo->ptLogBeginTime.llDateTime;
}
if(pInfo->dwMask & PLA_INFO_FLAG_END){
info.EndTime = pInfo->ptLogEndTime.llDateTime;
}
pdhStatus = PlaiSchedule(
strComputer,
hkeyQuery,
PLA_AUTO_MODE_AT,
&info
);
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
return pdhStatus;
}
PDH_FUNCTION
PdhPlaSetInfoA(
LPSTR /*strName*/,
LPSTR /*strComputer*/,
PPDH_PLA_INFO_A /*pInfo*/
)
{
return PDH_NOT_IMPLEMENTED;
}
PDH_FUNCTION
PdhPlaSetInfoW(
LPWSTR strName,
LPWSTR strComputer,
PPDH_PLA_INFO_W pInfo
)
{
PDH_STATUS pdhStatus;
PDH_STATUS pdhWarning = ERROR_SUCCESS;
HKEY hkeyQuery = NULL;
DWORD dwMask;
VALIDATE_QUERY( strName );
LPWSTR szName = PlaiStringDuplicate( strName );
LPWSTR szComputer = PlaiStringDuplicate( strComputer );
CHECK_NAMES( szName, szComputer, strComputer );
if( NULL == pInfo ){
return PDH_INVALID_ARGUMENT;
}
pdhStatus = PdhPlaValidateInfoW( szName, szComputer, pInfo );
switch( SEVERITY(pdhStatus) ){
case STATUS_SEVERITY_ERROR:
goto cleanup;
case STATUS_SEVERITY_WARNING:
pdhWarning = pdhStatus;
pdhStatus = ERROR_SUCCESS;
}
__try{
dwMask = pInfo->dwMask;
if( dwMask & PLA_INFO_FLAG_USER ){
pdhStatus = PdhPlaSetRunAs( szName, szComputer, pInfo->strUser, pInfo->strPassword );
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
CHECK_STATUS(pdhStatus);
pdhStatus = PlaiConnectAndLockQuery( szComputer, szName, hkeyQuery );
if( ERROR_SUCCESS == pdhStatus ){
if( ERROR_SUCCESS == pdhStatus ){
pdhStatus = PlaiSetInfo( szComputer, hkeyQuery, pInfo );
}
PlaiWriteRegistryLastModified ( hkeyQuery );
RELEASE_MUTEX(hPdhPlaMutex);
if( SUCCEEDED( pdhStatus ) ){
pdhStatus = PlaiSynchronize( szComputer );
if( SUCCEEDED( pdhStatus ) && ( dwMask & PLA_INFO_FLAG_BEGIN) ){
PlaiUpdateServiceMode( szComputer );
}
}
}
cleanup:
if ( NULL != hkeyQuery ) {
RegCloseKey ( hkeyQuery );
}
if( ERROR_SUCCESS == pdhStatus ){
pdhStatus = pdhWarning;
}
G_FREE( szName );
G_FREE( szComputer );
return pdhStatus;
}
/*****************************************************************************\
PdhPlaValidateInfo
Checks the PDH_PLA_INFO structure for valid fields. Only checks the fields
specified by the mask. Returns on first invalid field and set the mask
to the invalid field
Arguments:
LPTSTR strName
Log Name, if NULL checks for valid argument only
LPTSTR strComputer
Computer to connect to
PPDH_PLA_INFO pInfo
Information block
Return:
PDH_INVALID_ARGUMENT
One of the fields is invalid. Specified by the pInfo->dwMask
PDH_LOG_TYPE_NOT_FOUND
There is a mismatch between log type and specified parameters
PDH_INVALID_ARGUMENT
Arguments passed are not valid
ERROR_SUCCESS
\*****************************************************************************/
PDH_FUNCTION
PlaiCheckFile( LPWSTR strFileLocation, BOOL bDirOnly )
{
DWORD dwFile;
DWORD dwStatus = ERROR_SUCCESS;
LPWSTR strFile = NULL;
__try{
if( strFileLocation == NULL ){
return PDH_INVALID_ARGUMENT;
}
dwFile = BYTE_SIZE( strFileLocation ) + sizeof(WCHAR);
strFile = (LPWSTR)G_ALLOC( dwFile );
if( NULL == strFile ){
dwStatus = ERROR_OUTOFMEMORY;
goto cleanup;
}
StringCbCopy( strFile, dwFile, strFileLocation );
if( bDirOnly ){
LPWSTR sz = strFile;
sz += wcslen( strFile );
while( sz > strFile ){
if( *sz == L'\\' ){
*sz = L'\0';
break;
}
sz--;
}
}
dwFile = GetFileAttributes( strFile );
if( (DWORD)-1 == dwFile ){
dwStatus = GetLastError();
}
if( ERROR_SUCCESS == dwStatus && bDirOnly ){
if( ! (dwFile & FILE_ATTRIBUTE_DIRECTORY) ){
dwStatus = ERROR_DIRECTORY;
}
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
dwStatus = ERROR_INVALID_PARAMETER;
}
cleanup:
G_FREE( strFile );
return PlaiErrorToPdhStatus( dwStatus );
}
PDH_FUNCTION
PdhPlaValidateInfoA(
LPSTR /*strName*/,
LPSTR /*strComputer*/,
PPDH_PLA_INFO_A /*pInfo*/
)
{
return PDH_NOT_IMPLEMENTED;
}
#define VALIDATE_TYPE( type, flag ) \
if( dwType != PLA_NEW_LOG && dwType != type ){ \
dwErrorMask |= flag; \
bTypeMismatch = TRUE; \
}else{ \
dwType = type; \
} \
#define PROBE_STRING( sz, flag ) \
__try { \
if( NULL != sz ){ \
size_t string_size = wcslen( sz ); \
}else{ \
dwErrorMask |= flag; \
} \
} __except (EXCEPTION_EXECUTE_HANDLER) { \
dwErrorMask |= flag; \
} \
PDH_FUNCTION
PdhPlaValidateInfoW(
LPWSTR strName,
LPWSTR strComputer,
PPDH_PLA_INFO_W pInfo
)
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
DWORD dwWarningMask = 0;
DWORD dwErrorMask = 0;
DWORD dwType = PLA_NEW_LOG;
DWORD dwFormat = 0;
PVOID pBuffer = NULL;
PPDH_PLA_INFO_W pCurrentInfo = NULL;
BOOL bTypeMismatch = FALSE;
DWORD dwMask;
if( NULL == pInfo ){
return PDH_INVALID_ARGUMENT;
}
LPWSTR szName = PlaiStringDuplicate( strName );
LPWSTR szComputer = PlaiStringDuplicate( strComputer );
CHECK_NAMES( szName, szComputer, strComputer );
__try{
dwMask = pInfo->dwMask;
} __except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
CHECK_STATUS(pdhStatus);
if( szName != NULL ){
DWORD dwInfoSize = 0;
if( wcslen( szName ) > PLA_MAX_COLLECTION_NAME ){
pdhStatus = PDH_PLA_ERROR_NAME_TOO_LONG;
}
CHECK_STATUS(pdhStatus);
pdhStatus = PdhPlaGetInfoW( szName, szComputer, &dwInfoSize, pCurrentInfo );
if( ERROR_SUCCESS == pdhStatus ){
pCurrentInfo = (PPDH_PLA_INFO)G_ALLOC(dwInfoSize);
if( NULL != pCurrentInfo ){
pCurrentInfo->dwMask = PLA_INFO_FLAG_ALL;
pdhStatus = PdhPlaGetInfoW( szName, szComputer, &dwInfoSize, pCurrentInfo );
if( pCurrentInfo->dwMask & PLA_INFO_FLAG_USER ){
if( !PlaiIsStringEmpty( pCurrentInfo->strUser ) ){
WCHAR buffer[PLA_ACCOUNT_BUFFER];
LoadStringW( (HINSTANCE)ThisDLLHandle, IDS_DEFAULT_ACCOUNT, buffer, PLA_ACCOUNT_BUFFER );
if( ! (dwMask & PLA_INFO_FLAG_USER) && wcscmp( buffer, pCurrentInfo->strUser ) != 0 ){
pdhStatus = PDH_ACCESS_DENIED;
}
}
}
if( pCurrentInfo->dwMask & PLA_INFO_FLAG_TYPE ){
dwType = pCurrentInfo->dwType;
}
}
CHECK_STATUS(pdhStatus);
}else{
// collection does not exist yet
pdhStatus = ERROR_SUCCESS;
}
}
__try{
if( dwMask & PLA_INFO_FLAG_TYPE ){
VALIDATE_TYPE( pInfo->dwType, PLA_INFO_FLAG_TYPE );
switch( pInfo->dwType ){
case PLA_COUNTER_LOG:
case PLA_TRACE_LOG:
case PLA_ALERT:
break;
default:
dwErrorMask |= PLA_INFO_FLAG_TYPE;
}
dwType = pInfo->dwType;
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
CHECK_STATUS(pdhStatus);
__try{
if( dwMask & PLA_INFO_FLAG_FORMAT ){
dwFormat = pInfo->dwFileFormat;
switch( dwType ){
case PLA_COUNTER_LOG:
switch( (pInfo->dwFileFormat&0x0000FFFF) ){
case PLA_CSV_FILE:
case PLA_TSV_FILE:
case PLA_BIN_FILE:
case PLA_BIN_CIRC_FILE:
case PLA_SQL_LOG:
break;
default:
dwErrorMask |= PLA_INFO_FLAG_FORMAT;
}
break;
case PLA_TRACE_LOG:
switch( (pInfo->dwFileFormat&0x0000FFFF) ){
// These will get translated to the correct flag
case PLA_BIN_FILE:
case PLA_BIN_CIRC_FILE:
case PLA_CIRC_TRACE_FILE:
case PLA_SEQ_TRACE_FILE:
break;
default:
dwErrorMask |= PLA_INFO_FLAG_FORMAT;
}
break;
default:
switch( (pInfo->dwFileFormat&0x0000FFFF) ){
case PLA_CSV_FILE:
case PLA_TSV_FILE:
case PLA_BIN_FILE:
case PLA_BIN_CIRC_FILE:
case PLA_CIRC_TRACE_FILE:
case PLA_SEQ_TRACE_FILE:
case PLA_SQL_LOG:
break;
default:
dwErrorMask |= PLA_INFO_FLAG_FORMAT;
}
break;
}
}else if( NULL != pCurrentInfo ){
if( pCurrentInfo->dwMask & PLA_INFO_FLAG_FORMAT ){
dwFormat = pCurrentInfo->dwFileFormat;
}
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
CHECK_STATUS(pdhStatus);
if( dwMask & PLA_INFO_FLAG_COUNTERS ){
PPDH_COUNTER_PATH_ELEMENTS pdhElements = NULL;
VALIDATE_TYPE( PLA_COUNTER_LOG, PLA_INFO_FLAG_COUNTERS );
__try {
LPWSTR strCounter = pInfo->Perf.piCounterList.strCounters;
DWORD dwCounters = 0;
if( NULL == strCounter ){
dwErrorMask |= PLA_INFO_FLAG_COUNTERS;
}else{
pBuffer = G_ALLOC(1024);
pdhElements = (PPDH_COUNTER_PATH_ELEMENTS)pBuffer;
if( pdhElements == NULL ){
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
}
CHECK_STATUS(pdhStatus);
while( *strCounter != L'\0' ){
DWORD dwSize = (DWORD)G_SIZE(pBuffer);
ZeroMemory( pdhElements, dwSize );
pdhStatus = PdhParseCounterPath( strCounter, pdhElements, &dwSize, 0 );
switch(pdhStatus){
case PDH_MORE_DATA:
case PDH_MEMORY_ALLOCATION_FAILURE:
case PDH_INSUFFICIENT_BUFFER:
case ERROR_SUCCESS:
pdhStatus = ERROR_SUCCESS;
break;
default:
pInfo->dwReserved1 = dwCounters;
dwErrorMask |= PLA_INFO_FLAG_COUNTERS;
}
if( ERROR_SUCCESS != pdhStatus ){
pdhStatus = ERROR_SUCCESS;
break;
}
dwCounters++;
strCounter += (wcslen(strCounter)+1);
}
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
dwErrorMask |= PLA_INFO_FLAG_COUNTERS;
}
}
if( dwMask & PLA_INFO_FLAG_PROVIDERS ){
VALIDATE_TYPE( PLA_TRACE_LOG, PLA_INFO_FLAG_PROVIDERS );
__try {
LPWSTR strProvider = pInfo->Trace.piProviderList.strProviders;
if( NULL == strProvider ){
dwErrorMask |= PLA_INFO_FLAG_PROVIDERS;
}else{
while( *strProvider != L'\0' ){
strProvider += (wcslen(strProvider)+1);
}
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
dwErrorMask |= PLA_INFO_FLAG_PROVIDERS;
}
}
if( dwMask & PLA_INFO_FLAG_DEFAULTDIR ){
__try {
ULONG dwSize;
dwSize = wcslen( pInfo->strDefaultDir );
if( dwSize > MAX_PATH ){
dwErrorMask |= PLA_INFO_FLAG_DEFAULTDIR;
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
dwErrorMask |= PLA_INFO_FLAG_DEFAULTDIR;
}
}
if( dwMask & PLA_INFO_FLAG_FILENAME ){
__try {
ULONG dwSize;
dwSize = wcslen( pInfo->strBaseFileName );
if( dwSize > PLA_MAX_COLLECTION_NAME ){
dwErrorMask |= PLA_INFO_FLAG_FILENAME;
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
dwErrorMask |= PLA_INFO_FLAG_FILENAME;
}
}
if( dwMask & PLA_INFO_CREATE_FILENAME ){
DWORD dwSize = MAX_PATH;
WCHAR buffer[MAX_PATH];
__try {
DWORD dwOriginalType = 0;
BOOL bHaveType = (pInfo->dwMask & PLA_INFO_FLAG_TYPE);
if( ! bHaveType ){
pInfo->dwMask |= PLA_INFO_FLAG_TYPE;
dwOriginalType = pInfo->dwType;
pInfo->dwType = dwType;
}
pdhStatus = PdhPlaGetLogFileNameW( szName, szComputer, pInfo, 0, &dwSize, buffer );
if( !bHaveType ){
pInfo->dwMask &= ~PLA_INFO_FLAG_TYPE;
pInfo->dwType = dwOriginalType;
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
dwWarningMask |= PLA_INFO_FLAG_FILENAME;
}
switch( pdhStatus ){
case ERROR_SUCCESS:
{
if( PlaiIsLocalComputer( szComputer ) ){
if( PLA_SQL_LOG != dwFormat ){
pdhStatus = PlaiCheckFile( buffer, TRUE );
if( ERROR_SUCCESS != pdhStatus ){
dwWarningMask |= PLA_INFO_FLAG_FILENAME;
pdhStatus = ERROR_SUCCESS;
}
}
}
}
case PDH_INVALID_ARGUMENT:
case PDH_PLA_VALIDATION_ERROR:
case PDH_INSUFFICIENT_BUFFER:
pdhStatus = ERROR_SUCCESS;
break;
case PDH_PLA_ERROR_FILEPATH:
default:
dwErrorMask |= PLA_INFO_FLAG_FILENAME;
pdhStatus = ERROR_SUCCESS;
}
}
__try{
if( dwMask & PLA_INFO_FLAG_MODE ){
VALIDATE_TYPE( PLA_TRACE_LOG, PLA_INFO_FLAG_MODE );
switch( pInfo->Trace.dwMode & 0x0000000F ){
case EVENT_TRACE_FILE_MODE_NONE:
case EVENT_TRACE_FILE_MODE_SEQUENTIAL:
case EVENT_TRACE_FILE_MODE_CIRCULAR:
case EVENT_TRACE_FILE_MODE_NEWFILE:
break;
default:
dwErrorMask = PLA_INFO_FLAG_MODE;
}
if( (pInfo->Trace.dwMode & EVENT_TRACE_REAL_TIME_MODE) &&
(pInfo->Trace.dwMode & EVENT_TRACE_PRIVATE_LOGGER_MODE ) ){
dwErrorMask |= PLA_INFO_FLAG_MODE;
}
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
CHECK_STATUS(pdhStatus);
__try{
if( dwMask & PLA_INFO_FLAG_REPEAT ){
LONGLONG llBegin = 0;
LONGLONG llEnd = 0;
PPDH_PLA_INFO_W pCheckInfo;
if( pInfo->ptRepeat.dwAutoMode == PLA_AUTO_MODE_CALENDAR ){
if( dwMask & PLA_INFO_FLAG_BEGIN ){
pCheckInfo = pInfo;
}else{
pCheckInfo = pCurrentInfo;
}
if( NULL != pCheckInfo ){
if( pCheckInfo->dwMask & PLA_INFO_FLAG_BEGIN ){
if( pCheckInfo->ptLogBeginTime.dwAutoMode != PLA_AUTO_MODE_AT ){
dwErrorMask |= PLA_INFO_FLAG_REPEAT;
}else{
llBegin = pCheckInfo->ptLogBeginTime.llDateTime;
}
}
}
if( dwMask & PLA_INFO_FLAG_END ){
pCheckInfo = pInfo;
}else{
pCheckInfo = pCurrentInfo;
}
if( NULL != pCheckInfo ){
if( pCheckInfo->dwMask & PLA_INFO_FLAG_END ){
if( pCheckInfo->ptLogEndTime.dwAutoMode != PLA_AUTO_MODE_AT ){
dwErrorMask |= PLA_INFO_FLAG_REPEAT;
}else{
llEnd = pCheckInfo->ptLogEndTime.llDateTime;
}
}
}
if( 0 == llBegin || 0 == llEnd || ((llEnd - llBegin) >= FILE_TICS_PER_DAY) ){
dwErrorMask |= PLA_INFO_FLAG_REPEAT;
}
}
}
if( dwMask & PLA_INFO_FLAG_DATASTORE ){
switch( pInfo->dwDatastoreAttributes & PLA_DATASTORE_APPEND_MASK ){
case 0:
case PLA_DATASTORE_APPEND:
if( (dwType == PLA_TRACE_LOG && dwFormat != PLA_SEQ_TRACE_FILE ) ||
(dwType == PLA_COUNTER_LOG && dwFormat != PLA_BIN_FILE ) ){
dwErrorMask |= PLA_INFO_FLAG_DATASTORE;
}
break;
case PLA_DATASTORE_OVERWRITE:
if( dwFormat == PLA_SQL_LOG ){
dwErrorMask |= PLA_INFO_FLAG_DATASTORE;
}
break;
default:
dwErrorMask |= PLA_INFO_FLAG_DATASTORE;
}
switch( pInfo->dwDatastoreAttributes & PLA_DATASTORE_SIZE_MASK ){
case 0:
case PLA_DATASTORE_SIZE_ONE_RECORD:
case PLA_DATASTORE_SIZE_MB:
case PLA_DATASTORE_SIZE_KB:
break;
default:
dwErrorMask |= PLA_INFO_FLAG_DATASTORE;
}
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
CHECK_STATUS(pdhStatus);
if( dwMask & PLA_INFO_FLAG_SQLNAME ){
VALIDATE_TYPE( PLA_COUNTER_LOG, PLA_INFO_FLAG_SQLNAME );
if( dwFormat != 0 && dwFormat != PLA_SQL_LOG ){
dwErrorMask |= PLA_INFO_FLAG_SQLNAME;
}else{
dwFormat = PLA_SQL_LOG;
}
PROBE_STRING( pInfo->strSqlName, PLA_INFO_FLAG_SQLNAME );
}
if( dwMask & PLA_INFO_FLAG_LOGGERNAME ){
VALIDATE_TYPE( PLA_TRACE_LOG, PLA_INFO_FLAG_LOGGERNAME );
PROBE_STRING( pInfo->Trace.strLoggerName, PLA_INFO_FLAG_LOGGERNAME );
}
if( dwMask & PLA_INFO_FLAG_USER ){
PROBE_STRING( pInfo->strUser, PLA_INFO_FLAG_USER );
__try{
if( NULL != pInfo->strPassword ){
size_t size = wcslen( pInfo->strPassword );
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
dwErrorMask |= PLA_INFO_FLAG_USER;
}
}
__try{
if( dwMask & PLA_INFO_FLAG_INTERVAL ){
LONGLONG llMS;
VALIDATE_TYPE( PLA_COUNTER_LOG, PLA_INFO_FLAG_INTERVAL );
pdhStatus = PlaTimeInfoToMilliSeconds (&pInfo->Perf.ptSampleInterval, &llMS );
// 45 days in milliseconds = 1000*60*60*24*45 = 0xE7BE2C00
if( (ERROR_SUCCESS != pdhStatus) || (llMS > (0xE7BE2C00)) || (llMS < 1000) ){
dwErrorMask |= PLA_INFO_FLAG_INTERVAL;
pdhStatus = ERROR_SUCCESS;
}
}
if( dwMask & PLA_INFO_FLAG_BUFFERSIZE ){
VALIDATE_TYPE( PLA_TRACE_LOG, PLA_INFO_FLAG_BUFFERSIZE );
if( pInfo->Trace.dwBufferSize < 1 || pInfo->Trace.dwBufferSize > 1024 ){
dwErrorMask |= PLA_INFO_FLAG_BUFFERSIZE;
}
}
if( dwMask & PLA_INFO_FLAG_MINBUFFERS ){
VALIDATE_TYPE( PLA_TRACE_LOG, PLA_INFO_FLAG_MINBUFFERS );
if( pInfo->Trace.dwMinimumBuffers < 2 || pInfo->Trace.dwMinimumBuffers > 400 ){
dwErrorMask |= PLA_INFO_FLAG_MINBUFFERS;
}
}
if( dwMask & PLA_INFO_FLAG_MAXBUFFERS ){
VALIDATE_TYPE( PLA_TRACE_LOG, PLA_INFO_FLAG_MAXBUFFERS );
if( pInfo->Trace.dwMaximumBuffers < 2 || pInfo->Trace.dwMaximumBuffers > 400 ){
dwErrorMask |= PLA_INFO_FLAG_MAXBUFFERS;
}
}
if( dwMask & PLA_INFO_FLAG_FLUSHTIMER ){
VALIDATE_TYPE( PLA_TRACE_LOG, PLA_INFO_FLAG_FLUSHTIMER );
if( pInfo->Trace.dwFlushTimer < 1 ){
dwErrorMask |= PLA_INFO_FLAG_FLUSHTIMER;
}
}
if( dwMask & PLA_INFO_FLAG_MAXLOGSIZE ){
if( pInfo->dwMaxLogSize != PLA_DISK_MAX_SIZE ){
if( dwType == PLA_COUNTER_LOG ){
if( !( pInfo->dwMaxLogSize >= 1 && pInfo->dwMaxLogSize < 0x00000400) ){
dwErrorMask = PLA_INFO_FLAG_MAXLOGSIZE;
}
}else{
if( !(pInfo->dwMaxLogSize >=1 && pInfo->dwMaxLogSize < 0xFFFFFFFF) ){
dwErrorMask |= PLA_INFO_FLAG_MAXLOGSIZE;
}
}
}
}
if( dwMask & PLA_INFO_FLAG_AUTOFORMAT ){
switch( pInfo->dwAutoNameFormat ){
case PLA_SLF_NAME_NONE:
case PLA_SLF_NAME_MMDDHH:
case PLA_SLF_NAME_NNNNNN:
case PLA_SLF_NAME_YYYYDDD:
case PLA_SLF_NAME_YYYYMM:
case PLA_SLF_NAME_YYYYMMDD:
case PLA_SLF_NAME_YYYYMMDDHH:
case PLA_SLF_NAME_MMDDHHMM:
break;
default:
dwErrorMask |= PLA_INFO_FLAG_AUTOFORMAT;
}
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
CHECK_STATUS(pdhStatus);
if( dwMask & PLA_INFO_FLAG_RUNCOMMAND ){
PROBE_STRING( pInfo->strCommandFileName, PLA_INFO_FLAG_RUNCOMMAND );
__try {
if( NULL == szComputer ){
if( PLA_SQL_LOG != dwFormat ){
pdhStatus = PlaiCheckFile( pInfo->strCommandFileName, FALSE );
if( ERROR_SUCCESS != pdhStatus ){
dwWarningMask |= PLA_INFO_FLAG_RUNCOMMAND;
pdhStatus = ERROR_SUCCESS;
}
}
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
dwErrorMask = PLA_INFO_FLAG_RUNCOMMAND;
}
}
cleanup:
G_FREE( pBuffer );
G_FREE( pCurrentInfo );
G_FREE( szName );
G_FREE( szComputer );
if( 0 != dwWarningMask ){
pInfo->dwReserved2 = dwWarningMask;
pdhStatus = PDH_PLA_VALIDATION_WARNING;
}
if( 0 != dwErrorMask ){
pInfo->dwMask = dwErrorMask;
if( dwErrorMask & PLA_INFO_FLAG_FILENAME ){
pdhStatus = PDH_PLA_ERROR_FILEPATH;
}else{
pdhStatus = PDH_PLA_VALIDATION_ERROR;
}
}
if( TRUE == bTypeMismatch ){
pdhStatus = PDH_PLA_ERROR_TYPE_MISMATCH;
}
return pdhStatus;
}
/*****************************************************************************\
PdhiPlaRunAs
Authenticate as saved user
Arguments:
LPTSTR strKey
Guid string
Return:
PDH_INVALID_ARGUMENT
The query does not exist
ERROR_SUCCESS
\*****************************************************************************/
PDH_FUNCTION
PdhiPlaRunAs(
LPWSTR strName,
LPWSTR strComputer,
HANDLE* hToken
)
{
PDH_STATUS pdhStatus;
LPWSTR strKey = NULL;
LPWSTR strRunAs = NULL;
DWORD dwKeySize = 0;
DWORD dwSize = 0;
HKEY hkeyQuery = NULL;
HANDLE hUserToken = NULL;
VALIDATE_QUERY( strName );
LPWSTR szName = PlaiStringDuplicate( strName );
LPWSTR szComputer = PlaiStringDuplicate( strComputer );
CHECK_NAMES( szName, szComputer, strComputer );
if( hToken != NULL ){
__try{
*hToken = NULL;
} __except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
pdhStatus = PlaiConnectAndLockQuery( szComputer, szName, hkeyQuery );
if( ERROR_SUCCESS == pdhStatus ){
pdhStatus = PlaiReadRegistryStringValue( hkeyQuery, szRunAs, 0, &strRunAs, &dwSize );
if( PDH_PLA_COLLECTION_NOT_FOUND == pdhStatus || PlaiIsStringEmpty(strRunAs) ){
// The key is missing so return success
pdhStatus = ERROR_SUCCESS;
goto cleanup;
}
if( ERROR_SUCCESS == pdhStatus ){
BOOL bResult;
DATA_BLOB crypt;
DATA_BLOB data;
LPWSTR strUser = NULL;
LPWSTR strDomain = NULL;
LPWSTR strPassword = NULL;
LPWSTR strScan = strRunAs;
strUser = strScan;
while( *strScan != L'\0' ){
if( *strScan == L'\\' ){
*strScan = L'\0';
strScan++;
strDomain = strUser;
strUser = strScan;
break;
}
strScan++;
}
pdhStatus = PlaiReadRegistryStringValue( hkeyQuery, szKey, READ_REG_BLOB, &strKey, &dwKeySize );
if( ERROR_SUCCESS == pdhStatus && !PlaiIsStringEmpty( strKey ) ){
HANDLE hNetToken = NULL;
crypt.cbData = dwKeySize;
crypt.pbData = (BYTE*)strKey;
bResult= LogonUserW(
L"NetworkService",
L"NT AUTHORITY",
L"",
LOGON32_LOGON_SERVICE,
LOGON32_PROVIDER_WINNT50,
&hNetToken
);
if( bResult == TRUE ){
bResult = ImpersonateLoggedOnUser( hNetToken );
}
if( bResult != TRUE ){
pdhStatus = PlaiErrorToPdhStatus( GetLastError() );
}
ZeroMemory( &data, sizeof(DATA_BLOB) );
bResult = CryptUnprotectData( &crypt, NULL, NULL, NULL, NULL, CRYPTPROTECT_UI_FORBIDDEN, &data );
if( bResult == FALSE ){
pdhStatus = PlaiErrorToPdhStatus( GetLastError() );
}else{
strPassword = (LPWSTR)data.pbData;
pdhStatus = ERROR_SUCCESS;
}
bResult = RevertToSelf();
if( NULL != hNetToken ){
CloseHandle(hNetToken);
}
}else{
strPassword = _T("");
}
if( ERROR_SUCCESS == pdhStatus ){
bResult= LogonUserW(
strUser,
strDomain,
strPassword,
LOGON32_LOGON_NETWORK_CLEARTEXT,
LOGON32_PROVIDER_DEFAULT,
&hUserToken
);
if( bResult == TRUE ){
bResult = ImpersonateLoggedOnUser( hUserToken );
CloseHandle( hUserToken );
if( bResult == TRUE ){
bResult= LogonUserW(
strUser,
strDomain,
strPassword,
LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT,
&hUserToken
);
if( bResult && hToken != NULL ){
__try{
*hToken = hUserToken;
} __except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
}
}
if( bResult == FALSE ){
pdhStatus = PlaiErrorToPdhStatus( GetLastError() );
}
}
if( data.cbData > 0 ){
ZeroMemory( data.pbData, data.cbData );
LocalFree( data.pbData );
}
}
}
cleanup:
RELEASE_MUTEX(hPdhPlaMutex);
G_FREE( szName );
G_FREE( szComputer );
G_FREE( strRunAs );
G_FREE( strKey );
if ( NULL != hkeyQuery ) {
RegCloseKey ( hkeyQuery );
}
return pdhStatus;
}
/*****************************************************************************\
PdhPlaSetRunAs
Set the security for to run as when the log is active
Arguments:
LPTSTR strName
Log Name
LPTSTR strComputer
Computer to connect to
LPTSTR strUser
User to run as
LPTSTR strPassword
Users password
Return:
PDH_INVALID_ARGUMENT
The query does not exist
ERROR_SUCCESS
\*****************************************************************************/
BOOL
PlaiIsNetworkService( BOOL bLogon )
{
//
// If bLogon is TRUE this function will try to Impersonate the
// NetworkService if you is not already running that way.
// RevertToSelf() should be called after you are done being the
// NetworkService
//
DWORD dwStatus = ERROR_SUCCESS;
BOOL bResult;
HKEY hkeyQuery = NULL;
HANDLE hProcess;
PSID NetworkService = NULL;
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
HANDLE hToken = NULL;
DWORD dwSize;
PTOKEN_OWNER pOwnerInfo = NULL;
bResult = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &hToken );
if( bResult ){
bResult = GetTokenInformation( hToken, TokenOwner, NULL, 0, &dwSize );
dwStatus = GetLastError();
if( ERROR_INSUFFICIENT_BUFFER == dwStatus ){
pOwnerInfo = (PTOKEN_OWNER)G_ALLOC(dwSize);
if( NULL == pOwnerInfo ) {
bResult = FALSE;
goto cleanup;
}
bResult = GetTokenInformation(
hToken,
TokenOwner,
pOwnerInfo,
dwSize,
&dwSize
);
if( bResult ) {
bResult = AllocateAndInitializeSid(
&NtAuthority,
1,
SECURITY_NETWORK_SERVICE_RID,
0,0,0,0,0,0,0,
&NetworkService
);
}
}else{
bResult = FALSE;
goto cleanup;
}
}
if( bResult ){
bResult = EqualSid( NetworkService, pOwnerInfo->Owner );
}
if( (!bResult) && bLogon ){
HANDLE hNetwork = NULL;
bResult= LogonUserW(
L"NetworkService",
L"NT AUTHORITY",
L"",
LOGON32_LOGON_SERVICE,
LOGON32_PROVIDER_WINNT50,
&hNetwork
);
if( bResult ){
bResult = ImpersonateLoggedOnUser( hNetwork );
}
if( INVALID_HANDLE_VALUE != hNetwork ){
CloseHandle( hNetwork );
}
}
cleanup:
G_FREE( pOwnerInfo );
if( INVALID_HANDLE_VALUE != hToken ){
CloseHandle( hToken );
}
if( NULL != NetworkService){
FreeSid(NetworkService);
}
return bResult;
}
PDH_FUNCTION
PlaiSetRunAs(
HKEY hkeyQuery,
LPWSTR strUser,
LPWSTR strPassword
)
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
BOOL bResult = FALSE;
WCHAR buffer[PLA_ACCOUNT_BUFFER];
if( LoadStringW( (HINSTANCE)ThisDLLHandle, IDS_DEFAULT_ACCOUNT, buffer, PLA_ACCOUNT_BUFFER ) ){
bResult = ( wcscmp( buffer, strUser ) == 0 );
}
if( strPassword == NULL || bResult ){
pdhStatus = PlaiWriteRegistryStringValue( hkeyQuery, szKey, REG_SZ, NULL, 0 );
if( bResult ){
pdhStatus = PlaiWriteRegistryStringValue( hkeyQuery, szRunAs, REG_SZ, NULL, 0 );
}
}else{
DATA_BLOB data;
DATA_BLOB crypt;
HANDLE hToken = NULL;
bResult = PlaiIsNetworkService(TRUE);
if( bResult != TRUE ){
pdhStatus = PlaiErrorToPdhStatus( GetLastError() );
}
if( ERROR_SUCCESS == pdhStatus ){
data.cbData = BYTE_SIZE( strPassword ) + (DWORD)sizeof(UNICODE_NULL);
data.pbData = (BYTE*)strPassword;
bResult = CryptProtectData(
&data,
NULL, NULL, NULL, 0,
CRYPTPROTECT_UI_FORBIDDEN,
&crypt
);
if( bResult == TRUE ){
DWORD dwStatus = RegSetValueEx( hkeyQuery, szKey, 0, REG_BINARY, crypt.pbData, crypt.cbData );
pdhStatus = PlaiErrorToPdhStatus( dwStatus );
if( crypt.pbData ){
LocalFree(crypt.pbData);
}
}else{
pdhStatus = PlaiErrorToPdhStatus( GetLastError() );
}
RevertToSelf();
}
}
if( ERROR_SUCCESS == pdhStatus ){
pdhStatus = PlaiWriteRegistryStringValue( hkeyQuery, szRunAs, REG_SZ, strUser, 0 );
}
return pdhStatus;
}
PDH_FUNCTION
PdhiPlaSetRunAs(
LPWSTR strName,
LPWSTR strComputer,
LPWSTR strUser,
LPWSTR strPassword
)
{
//
// Only make this call if you are sure you have no better chance
// of being logged on as the NetworkService account. If you are
// not the NetworkService and can not log on as the NetworkService
// this call will fail.
//
PDH_STATUS pdhStatus;
HKEY hkeyQuery = NULL;
VALIDATE_QUERY( strName );
LPWSTR szName = PlaiStringDuplicate( strName );
LPWSTR szComputer = PlaiStringDuplicate( strComputer );
CHECK_NAMES( szName, szComputer, strComputer );
LPWSTR szUser = PlaiStringDuplicate( strUser );
LPWSTR szPassword = PlaiStringDuplicate( strPassword );
pdhStatus = PlaiConnectAndLockQuery( szComputer, szName, hkeyQuery );
if( ERROR_SUCCESS == pdhStatus ){
pdhStatus = PlaiSetRunAs( hkeyQuery, szUser, szPassword );
RELEASE_MUTEX(hPdhPlaMutex);
}
if ( NULL != hkeyQuery ) {
RegCloseKey ( hkeyQuery );
}
if( NULL != szPassword ){
ZeroMemory( szPassword, wcslen(szPassword)*sizeof(WCHAR) );
}
G_FREE( szUser );
G_FREE( szPassword );
cleanup:
G_FREE( szName );
G_FREE( szComputer );
return pdhStatus;
}
PDH_FUNCTION
PdhPlaSetRunAsA(
LPSTR /*strName*/,
LPSTR /*strComputer*/,
LPSTR /*strUser*/,
LPSTR /*strPassword*/
)
{
return PDH_NOT_IMPLEMENTED;
}
PDH_FUNCTION
PdhPlaSetRunAsW(
LPWSTR strName,
LPWSTR strComputer,
LPWSTR strUser,
LPWSTR strPassword
)
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
BOOL bResult;
VALIDATE_QUERY( strName );
LPWSTR szName = PlaiStringDuplicate( strName );
LPWSTR szComputer = PlaiStringDuplicate( strComputer );
CHECK_NAMES( szName, szComputer, strComputer );
bResult = PlaiIsNetworkService(TRUE);
if( bResult ){
bResult = PlaiIsLocalComputer( szComputer );
}
if( bResult ){
pdhStatus = PdhiPlaSetRunAs( szName, szComputer, strUser, strPassword );
RevertToSelf();
}else{
pdhStatus = PdhPlaWbemSetRunAs( szName, szComputer, strUser, strPassword );
}
cleanup:
G_FREE( szName );
G_FREE( szComputer );
return pdhStatus;
}
/*****************************************************************************\
PdhPlaEnumCollections
Set the security for to run as when the log is active
Arguments:
LPTSTR strComputer
Computer to connect to
LPDWORD pcchBufferSize
[IN] Size of buffer in TCHAR's pointed to by mszCollections.
[OUT] Size required or number of characters written.
LPTSTR mszCollections
Multistring of the existing collections.
Return:
ERROR_SUCCESS
\*****************************************************************************/
PDH_FUNCTION
PdhPlaEnumCollectionsA(
LPSTR /*strComputer*/,
LPDWORD /*pcchBufferSize*/,
LPSTR /*mszCollections*/
)
{
return PDH_NOT_IMPLEMENTED;
}
PDH_FUNCTION
PdhPlaEnumCollectionsW(
LPWSTR strComputer,
LPDWORD pcchBufferSize, /* Character Count */
LPWSTR mszCollections
)
{
DWORD dwStatus;
PDH_STATUS pdhStatus = ERROR_SUCCESS;
HKEY hkeyQueries = NULL;
DWORD cchTotalLength = 0;
DWORD cchBufferLeft = 0;
DWORD nCollections = 0;
DWORD nMaxSubKeyLength = 0;
DWORD dwSize;
LPWSTR strCollection;
LPWSTR str;
__try{
if( mszCollections != NULL && pcchBufferSize > 0 ){
ZeroMemory( mszCollections, *pcchBufferSize * sizeof(WCHAR) );
str = mszCollections;
cchBufferLeft = *pcchBufferSize;
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
CHECK_STATUS( pdhStatus );
LPWSTR szComputer = PlaiStringDuplicate( strComputer );
if( NULL == szComputer && NULL != strComputer ){
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
goto cleanup;
}
dwStatus = WAIT_FOR_AND_LOCK_MUTEX( hPdhPlaMutex );
if( dwStatus != ERROR_SUCCESS && dwStatus != WAIT_ABANDONED ){
return PlaiErrorToPdhStatus( dwStatus );
}
pdhStatus = PlaiConnectToRegistry( szComputer, hkeyQueries, TRUE, FALSE );
CHECK_STATUS( pdhStatus );
dwStatus = RegQueryInfoKey(
hkeyQueries,
NULL,
NULL,
NULL,
&nCollections,
&nMaxSubKeyLength,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
);
CHECK_STATUS( dwStatus );
dwSize = (sizeof(WCHAR)*(nMaxSubKeyLength+1));
strCollection = (LPWSTR)G_ALLOC( dwSize );
if( strCollection ){
for( ULONG i = 0; i<nCollections && ERROR_SUCCESS == dwStatus; i++ ){
LPWSTR strQueryName = NULL;
DWORD dwQueryName = 0;
dwStatus = RegEnumKey( hkeyQueries, i, strCollection, dwSize );
if( ERROR_SUCCESS == dwStatus ){
HKEY hkeyQuery = NULL;
dwStatus = RegOpenKeyExW (
hkeyQueries,
strCollection,
0,
KEY_READ,
&hkeyQuery
);
if( ERROR_SUCCESS == dwStatus ){
DWORD cchNameSize = 0;
LPWSTR szName = NULL;
pdhStatus = PlaiReadRegistryStringValue(
hkeyQuery,
szCollection,
READ_REG_MUI,
&strQueryName,
&dwQueryName
);
__try{
if( pdhStatus == ERROR_SUCCESS &&
strQueryName != NULL &&
dwQueryName > sizeof(WCHAR) ){
cchNameSize = wcslen( strQueryName ) + 1;
szName = strQueryName;
}else{
pdhStatus = ERROR_SUCCESS;
cchNameSize = wcslen( strCollection ) + 1;
szName = strCollection;
}
cchTotalLength += cchNameSize;
if( NULL != mszCollections && cchTotalLength < *pcchBufferSize ){
StringCchCopy( str, cchBufferLeft, szName );
cchBufferLeft -= cchNameSize;
str += ( wcslen(str) + 1 );
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
G_FREE( strQueryName );
}
if( NULL != hkeyQuery ){
RegCloseKey( hkeyQuery );
}
}
}
G_FREE( strCollection );
__try{
if( ERROR_SUCCESS == dwStatus ){
if( (cchTotalLength + 1) > *pcchBufferSize ){
pdhStatus = PDH_INSUFFICIENT_BUFFER;
}
*pcchBufferSize = cchTotalLength + 1;
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}else{
dwStatus = ERROR_OUTOFMEMORY;
}
cleanup:
RELEASE_MUTEX( hPdhPlaMutex );
if ( NULL != hkeyQueries ) {
RegCloseKey ( hkeyQueries );
}
G_FREE( szComputer );
if( ERROR_SUCCESS == pdhStatus ){
return PlaiErrorToPdhStatus( dwStatus );
}else{
return pdhStatus;
}
}
/*****************************************************************************\
PlaTimeInfoToMilliSeconds
Converts the PLA_TIME_INFO structure to ms in a LONGLONG
Arguments:
PLA_TIME_INFO* pTimeInfo
LONGLONG* pllmsecs
Return:
PDH_INVALID_ARGUMENT
The pTimeInfo->wDataType is not PLA_TT_DTYPE_UNITS
ERROR_SUCCESS
\*****************************************************************************/
PDH_FUNCTION
PlaTimeInfoToMilliSeconds (
PLA_TIME_INFO* pTimeInfo,
LONGLONG* pllmsecs)
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
__try{
if( PLA_TT_DTYPE_UNITS != pTimeInfo->wDataType ){
pdhStatus = PDH_INVALID_ARGUMENT;
}else{
switch (pTimeInfo->dwUnitType) {
case PLA_TT_UTYPE_SECONDS:
*pllmsecs = pTimeInfo->dwValue;
break;
case PLA_TT_UTYPE_MINUTES:
*pllmsecs = pTimeInfo->dwValue * PLA_SECONDS_IN_MINUTE;
break;
case PLA_TT_UTYPE_HOURS:
*pllmsecs = pTimeInfo->dwValue * PLA_SECONDS_IN_HOUR;
break;
case PLA_TT_UTYPE_DAYS:
*pllmsecs = pTimeInfo->dwValue * PLA_SECONDS_IN_DAY;
break;
default:
*pllmsecs = 0;
}
*pllmsecs *= 1000;
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
return pdhStatus;
}
/*****************************************************************************\
PdhiPlaFormatBlanks
Replaces blanks with the character specified by:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\SysmonLog\Replace Blanks
Arguments:
Return:
ERROR_SUCCESS
\*****************************************************************************/
PDH_FUNCTION
PdhiPlaFormatBlanksA( LPSTR strComputer, LPSTR strFormat )
{
return PDH_NOT_IMPLEMENTED;
}
PDH_FUNCTION
PdhiPlaFormatBlanksW( LPWSTR strComputer, LPWSTR strFormat )
{
HKEY hkey = NULL;
LPWSTR strScan = strFormat;
PDH_STATUS pdhStatus;
LPWSTR strBlank = NULL;
DWORD dwSize = 0;
if( PlaiIsStringEmpty( strFormat ) ){
return ERROR_SUCCESS;
}
pdhStatus = PlaiConnectToRegistry( strComputer, hkey, FALSE );
CHECK_STATUS( pdhStatus );
pdhStatus = PlaiReadRegistryStringValue(
hkey,
L"Replace Blanks",
READ_REG_MUI,
&strBlank,
&dwSize
);
if( ERROR_SUCCESS != pdhStatus || PlaiIsStringEmpty( strBlank ) ){
pdhStatus = ERROR_SUCCESS;
goto cleanup;
}
__try {
while( *strScan != L'\0' ){
if( *strScan == L' ' ){
*strScan = *strBlank;
}
strScan++;
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
cleanup:
G_FREE( strBlank );
if( hkey != NULL ){
RegCloseKey ( hkey );
}
return pdhStatus;
}
/*****************************************************************************\
PdhPlaGetLogFileName
Arguments:
Return:
PDH_PLA_ERROR_FILEPATH
Not all needed fields we set in the passed info block
ERROR_INVALID_NAME
The final path contains invalid characters
ERROR_SUCCESS
\*****************************************************************************/
PDH_FUNCTION
PlaiScanForInvalidChar( LPWSTR strScan )
{
LPWSTR strCheck = strScan;
if( PlaiIsStringEmpty( strScan ) ){
return PDH_INVALID_ARGUMENT;
}
if( PlaiIsCharWhitespace( *strCheck ) ){
return PDH_PLA_ERROR_FILEPATH;
}
if( PlaiIsCharWhitespace( strCheck[wcslen(strCheck)-1] ) ){
return PDH_PLA_ERROR_FILEPATH;
}
while( *strCheck != L'\0' ){
switch( *strCheck ){
case L'?':
case L'*':
case L'|':
case L'<':
case L'>':
case L'/':
case L'\"':
return PDH_PLA_ERROR_FILEPATH;
case L'\\':
if( strCheck > strScan ){
if( PlaiIsCharWhitespace( *((WCHAR*)strCheck-1)) ){
return PDH_PLA_ERROR_FILEPATH;
}
}
}
strCheck++;
}
return ERROR_SUCCESS;
}
long PlaiJulianDate( SYSTEMTIME st )
{
long day = 0;
BOOL bLeap = FALSE;
static int cDaysInMonth[] =
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
for( int i = 0; i < st.wMonth - 1 && i<12; i++ ){
day += cDaysInMonth[i];
}
day += st.wDay;
if( st.wYear % 400 == 0){
bLeap = TRUE;
}else if( st.wYear % 100 == 0){
bLeap = FALSE;
}else if( st.wYear % 4 ){
bLeap = TRUE;
}
if( st.wMonth > 2 && bLeap ){
day++;
}
return day;
}
PDH_FUNCTION
PlaiGetLogFileName(
DWORD dwFlags,
PPDH_PLA_INFO_W pInfo,
LPDWORD pcchBufferSize,
LPWSTR strFileName
)
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
DWORD cchExpanded = 0;
WCHAR buffer[128];
LPWSTR strExpand;
DWORD cchSize;
DWORD dwSwitch;
SYSTEMTIME st;
GetLocalTime (&st);
LPWSTR strWhack = L"\\";
LPWSTR strUnder = L"_";
DWORD cchTotalSize = 0;
LPWSTR strLocalFileName = NULL;
LPWSTR strBaseFileName = NULL;
LPWSTR strDefaultDir = NULL;
LPWSTR strSQL = L"";
TCHAR strBuffer[MAX_PATH];
if( pInfo->dwMask & PLA_INFO_FLAG_FILENAME ){
strBaseFileName = pInfo->strBaseFileName;
}
if( pInfo->dwMask & PLA_INFO_FLAG_DEFAULTDIR ){
strDefaultDir = pInfo->strDefaultDir;
}
if( (pInfo->dwMask & PLA_INFO_FLAG_FORMAT) &&
pInfo->dwFileFormat == PLA_SQL_LOG ){
if( (pInfo->dwMask & PLA_INFO_FLAG_SQLNAME) &&
! PlaiIsStringEmpty( pInfo->strSqlName ) ){
strDefaultDir = pInfo->strSqlName;
}else{
strDefaultDir = strBaseFileName;
}
strBaseFileName = L"";
if( ! PlaiIsStringEmpty( strDefaultDir ) ){
BOOL bBang = FALSE;
BOOL bLogSet = FALSE;
LPWSTR strLogSet = wcsstr( strDefaultDir, L"!" );
if( ! PlaiIsStringEmpty( strLogSet ) ){
bBang = TRUE;
if( wcslen( strLogSet ) > 1 ){
bLogSet = TRUE;
}
}
if( pInfo->dwAutoNameFormat != PLA_SLF_NAME_NONE ){
if( !bLogSet ){
strUnder = L"";
}
}else if( ! bLogSet ){
pdhStatus = PDH_INVALID_ARGUMENT;
goto cleanup;
}
if( ! bLogSet && ! bBang ){
strWhack = L"!";
}else{
strWhack = L"";
}
if( StrCmpNI( strDefaultDir, L"SQL:", 4 ) != 0 ){
strSQL = L"SQL:";
}
}else{
pdhStatus = PDH_INVALID_ARGUMENT;
goto cleanup;
}
}else{
WCHAR fname[_MAX_FNAME];
WCHAR ext[_MAX_EXT];
if( PlaiIsStringEmpty( strDefaultDir ) ){
strDefaultDir = L"%SystemDrive%\\PerfLogs";
}else if( strDefaultDir[wcslen(strDefaultDir)-1] == L'\\' ){
strWhack = L"";
}
if( PlaiIsStringEmpty( strBaseFileName ) ){
if( (pInfo->dwMask & PLA_INFO_FLAG_AUTOFORMAT) &&
PLA_SLF_NAME_NONE == pInfo->dwAutoNameFormat ){
pdhStatus = PDH_INVALID_ARGUMENT;
goto cleanup;
}else{
strBaseFileName = L"";
strUnder = L"";
}
}
_wsplitpath( strBaseFileName, NULL, NULL, fname, ext );
if( _wcsicmp( ext, L".etl" ) == 0 ||
_wcsicmp( ext, L".blg" ) == 0 ||
_wcsicmp( ext, L".csv" ) == 0 ||
_wcsicmp( ext, L".tsv" ) == 0 ){
if( wcslen( fname ) < _MAX_PATH ){
StringCchCopy( strBuffer, _MAX_PATH, fname );
strBaseFileName = strBuffer;
}
}
}
cchTotalSize = 32; // padding for cnf suffix and sql prefix
cchTotalSize += BYTE_SIZE( strBaseFileName ) / sizeof(WCHAR);
cchTotalSize += BYTE_SIZE( strDefaultDir ) / sizeof(WCHAR);
strLocalFileName = (LPWSTR)G_ALLOC( cchTotalSize * sizeof(WCHAR) );
if( NULL == strLocalFileName ){
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
goto cleanup;
}
if( pInfo->dwMask & PLA_INFO_FLAG_AUTOFORMAT ){
dwSwitch = pInfo->dwAutoNameFormat;
}else{
// default
dwSwitch = PLA_SLF_NAME_NONE;
}
switch( dwSwitch ){
case PLA_SLF_NAME_NONE:
StringCchPrintf( strLocalFileName, cchTotalSize,
L"%s%s%s%s",
strSQL, strDefaultDir, strWhack, strBaseFileName );
break;
case PLA_SLF_NAME_MMDDHH:
StringCchPrintf( strLocalFileName, cchTotalSize,
L"%s%s%s%s%s%02d%02d%02d",
strSQL, strDefaultDir, strWhack, strBaseFileName, strUnder, st.wMonth, st.wDay, st.wHour );
break;
case PLA_SLF_NAME_NNNNNN:
StringCchPrintf( strLocalFileName, cchTotalSize,
L"%s%s%s%s%s%06d",
strSQL, strDefaultDir, strWhack, strBaseFileName, strUnder, pInfo->dwLogFileSerialNumber );
break;
case PLA_SLF_NAME_YYYYDDD:
StringCchPrintf( strLocalFileName, cchTotalSize,
L"%s%s%s%s%s%04d%03d",
strSQL, strDefaultDir, strWhack, strBaseFileName, strUnder, st.wYear, PlaiJulianDate( st ) );
break;
case PLA_SLF_NAME_YYYYMM:
StringCchPrintf( strLocalFileName, cchTotalSize,
L"%s%s%s%s%s%04d%02d",
strSQL, strDefaultDir, strWhack, strBaseFileName, strUnder, st.wYear, st.wMonth );
break;
case PLA_SLF_NAME_YYYYMMDD:
StringCchPrintf( strLocalFileName, cchTotalSize,
L"%s%s%s%s%s%04d%02d%02d",
strSQL, strDefaultDir, strWhack, strBaseFileName, strUnder, st.wYear, st.wMonth, st.wDay );
break;
case PLA_SLF_NAME_YYYYMMDDHH:
StringCchPrintf( strLocalFileName, cchTotalSize,
L"%s%s%s%s%s%04d%02d%02d%02d",
strSQL, strDefaultDir, strWhack, strBaseFileName, strUnder, st.wYear, st.wMonth, st.wDay, st.wHour );
break;
case PLA_SLF_NAME_MMDDHHMM:
StringCchPrintf( strLocalFileName, cchTotalSize,
L"%s%s%s%s%s%02d%02d%02d%02d",
strSQL, strDefaultDir, strWhack, strBaseFileName, strUnder, st.wMonth, st.wDay, st.wHour, st.wMinute );
break;
}
if( (pInfo->dwMask & PLA_INFO_FLAG_CRTNEWFILE) &&
PLA_AUTO_MODE_NONE != pInfo->ptCreateNewFile.dwAutoMode ){
dwFlags |= PLA_FILENAME_USE_SUBEXT;
// default the CNF number.
if ( 0 == pInfo->dwReserved1 ) {
pInfo->dwReserved1 = 1;
}
}
if( dwFlags & PLA_FILENAME_USE_SUBEXT ){
if( dwFlags & PLA_FILENAME_GET_SUBFMT ){
StringCchCat( strLocalFileName, cchTotalSize, L"_%03d" );
}else if( dwFlags & PLA_FILENAME_GET_SUBXXX ){
StringCchCat( strLocalFileName, cchTotalSize, L"_xxx" );
}else{
StringCchPrintf( buffer, 128, L"_%03d", pInfo->dwReserved1 );
StringCchCat( strLocalFileName, cchTotalSize, buffer );
}
}
if( pInfo->dwMask & PLA_INFO_FLAG_FORMAT ){
dwSwitch = (pInfo->dwFileFormat & 0x0000FFFF);
}else{
dwSwitch = PLA_NUM_FILE_TYPES;
}
switch( dwSwitch ){
case PLA_CSV_FILE:
StringCchCat( strLocalFileName, cchTotalSize, L".csv" );
break;
case PLA_TSV_FILE:
StringCchCat( strLocalFileName, cchTotalSize, L".tsv" );
break;
case PLA_BIN_FILE:
case PLA_BIN_CIRC_FILE:
StringCchCat( strLocalFileName, cchTotalSize, L".blg" );
break;
case PLA_CIRC_TRACE_FILE:
case PLA_SEQ_TRACE_FILE:
StringCchCat( strLocalFileName, cchTotalSize, L".etl" );
break;
case PLA_SQL_LOG:
break;
}
if( !(dwFlags & PLA_FILENAME_NOEXPANDEV) ){
if( NULL == strFileName ){
strExpand = buffer;
cchSize = 128;
pdhStatus = PDH_INSUFFICIENT_BUFFER;
}else{
strExpand = strFileName;
cchSize = (*pcchBufferSize);
}
cchExpanded = ExpandEnvironmentStrings( strLocalFileName, strExpand, cchSize );
if( cchExpanded == 0 ){
DWORD dwStatus = GetLastError();
pdhStatus = PlaiErrorToPdhStatus( dwStatus );
}else{
cchTotalSize = cchExpanded;
if( NULL != strFileName && *pcchBufferSize < cchTotalSize ){
pdhStatus = PDH_INSUFFICIENT_BUFFER;
}
}
}else{
cchTotalSize = wcslen( strLocalFileName ) + 1;
if( NULL == strFileName ){
pdhStatus = PDH_INSUFFICIENT_BUFFER;
}else{
if( cchTotalSize <= *pcchBufferSize ){
StringCchCopy( strFileName, *pcchBufferSize, strLocalFileName );
strExpand = strFileName;
}else{
pdhStatus = PDH_INSUFFICIENT_BUFFER;
}
}
}
if( ERROR_SUCCESS == pdhStatus ){
pdhStatus = PlaiScanForInvalidChar( strExpand );
}
cleanup:
G_FREE( strLocalFileName );
*pcchBufferSize = cchTotalSize;
return pdhStatus;
}
PDH_FUNCTION
PdhPlaGetLogFileNameA(
LPSTR strName,
LPSTR strComputer,
PPDH_PLA_INFO_A pInfo,
DWORD dwFlags,
LPDWORD pcchBufferSize,
LPSTR strFileName
)
{
return PDH_NOT_IMPLEMENTED;
}
PDH_FUNCTION
PdhPlaGetLogFileNameW(
LPWSTR strName,
LPWSTR strComputer,
PPDH_PLA_INFO_W pInfo,
DWORD dwFlags,
LPDWORD pcchBufferSize,
LPWSTR strFileName
)
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
PPDH_PLA_INFO_W pLocalInfo = NULL;
LPWSTR strFolder = NULL;
LPWSTR strLocalFileName = NULL;
DWORD cbSize;
__try{
if( pInfo == NULL ){
DWORD dwInfoSize = 0;
pdhStatus = PdhPlaGetInfoW( strName, strComputer, &dwInfoSize, pLocalInfo );
CHECK_STATUS(pdhStatus);
pLocalInfo = (PPDH_PLA_INFO)G_ALLOC(dwInfoSize);
if( NULL != pLocalInfo ){
ZeroMemory( pLocalInfo, dwInfoSize );
pLocalInfo->dwMask = PLA_INFO_CREATE_FILENAME;
pdhStatus = PdhPlaGetInfoW( strName, strComputer, &dwInfoSize, pLocalInfo );
CHECK_STATUS(pdhStatus);
}else{
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
goto cleanup;
}
}else{
pLocalInfo = (PPDH_PLA_INFO)G_ALLOC(sizeof(PDH_PLA_INFO) );
if( NULL != pLocalInfo ){
memcpy( pLocalInfo, pInfo, sizeof(PDH_PLA_INFO) );
}else{
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
goto cleanup;
}
}
if( !(pLocalInfo->dwMask & PLA_INFO_FLAG_TYPE) || PLA_ALERT == pLocalInfo->dwType ){
if( *pcchBufferSize > 1 && strFileName != NULL ){
strFileName[0] = L'\0';
}
*pcchBufferSize = 1;
goto cleanup;
}
if( ((dwFlags & PLA_FILENAME_CURRENTLOG) ||
((pLocalInfo->dwMask & PLA_INFO_FLAG_STATUS) &&
PLA_QUERY_RUNNING == pLocalInfo->dwStatus)) &&
!(dwFlags & PLA_FILENAME_CREATEONLY) ){
if( NULL != strName ){
HKEY hkeyQuery = NULL;
pdhStatus = PlaiConnectAndLockQuery ( strComputer, strName, hkeyQuery, FALSE );
if( ERROR_SUCCESS == pdhStatus ){
cbSize = 0;
pdhStatus = PlaiReadRegistryStringValue( hkeyQuery, szCurrentLogFile, 0, &strLocalFileName, &cbSize );
RELEASE_MUTEX(hPdhPlaMutex);
if( NULL != hkeyQuery ){
RegCloseKey( hkeyQuery );
}
if( pdhStatus == ERROR_SUCCESS ){
if( strFileName != NULL && *pcchBufferSize >= (cbSize/sizeof(WCHAR)) ){
StringCchCopy( strFileName, *pcchBufferSize, strLocalFileName );
}else{
if( NULL != strFileName ){
pdhStatus = PDH_INSUFFICIENT_BUFFER;
}
}
*pcchBufferSize = (cbSize/sizeof(WCHAR));
goto cleanup;
}
}
}
}
if( !(pLocalInfo->dwMask & PLA_INFO_FLAG_DEFAULTDIR) ||
PlaiIsStringEmpty( pLocalInfo->strDefaultDir ) ){
HKEY hkeyLogs = NULL;
pdhStatus = PlaiConnectToRegistry( strComputer, hkeyLogs, FALSE );
CHECK_STATUS( pdhStatus );
cbSize = 0;
pdhStatus = PlaiReadRegistryStringValue(
hkeyLogs,
L"DefaultLogFileFolder",
READ_REG_MUI,
&strFolder,
&cbSize
);
if( hkeyLogs != NULL ){
RegCloseKey ( hkeyLogs );
}
CHECK_STATUS(pdhStatus);
pLocalInfo->strDefaultDir = strFolder;
pLocalInfo->dwMask |= PLA_INFO_FLAG_DEFAULTDIR;
}
if( ! PlaiIsLocalComputer( strComputer ) ){
dwFlags |= PLA_FILENAME_NOEXPANDEV;
}
pdhStatus = PlaiGetLogFileName( dwFlags, pLocalInfo, pcchBufferSize, strFileName );
if(ERROR_SUCCESS == pdhStatus){
pdhStatus = PdhiPlaFormatBlanksW( strComputer, strFileName );
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
cleanup:
G_FREE( pLocalInfo );
G_FREE( strFolder );
G_FREE( strLocalFileName );
return pdhStatus;
}