/*++ Copyright (c) 1996 Microsoft Corporation All rights reserved. Module Name: perfutil.cxx Abstract: Utility routines copied from sockets\internet\svcs\lib\perfutil.c (which were in-turn copied from perfmon interface common code). Code reuse from copy & paste instead of fixing the interface. Author: Albert Ting (AlbertT) 17-Dec-1996 Revision History: --*/ #include "precomp.hxx" #pragma hdrstop #include "perf.hxx" #include "perfp.hxx" #include "messages.h" /******************************************************************** Globals ********************************************************************/ // // Translation table from kEventLogLevel to EVENTLOG_*_TYPE // UINT gauEventLogTable[] = { EVENTLOG_INFORMATION_TYPE, // kSuccess EVENTLOG_INFORMATION_TYPE, // kInformation, EVENTLOG_WARNING_TYPE, // kWarning, EVENTLOG_ERROR_TYPE // kError }; // // Test for delimiter, end of line and non-digit characters // used by IsNumberInUnicodeList routine. // enum CHAR_TYPE { kDigit = 1, kDelimiter = 2, kInvalid = 3 }; inline CHAR_TYPE EvalThisChar( WCHAR c, WCHAR d ) { if( c == d || c == 0 ) { return kDelimiter; } if( c < L'0' || c > L'9' ) { return kInvalid; } return kDigit; } BOOL Pfp_bNumberInUnicodeList ( IN DWORD dwNumber, IN LPCWSTR lpwszUnicodeList ) /*++ Arguments: IN dwNumber DWORD number to find in list IN lpwszUnicodeList Null terminated, Space delimited list of decimal numbers Return Value: TRUE: dwNumber was found in the list of unicode number strings FALSE: dwNumber was not found in the list. --*/ { DWORD dwThisNumber; LPCWSTR pwcThisChar; BOOL bValidNumber; BOOL bNewItem; WCHAR wckDelimiter; // could be an argument to be more flexible if( !lpwszUnicodeList ) { // // NULL pointer, # not found. // return FALSE; } pwcThisChar = lpwszUnicodeList; dwThisNumber = 0; wckDelimiter = (WCHAR)' '; bValidNumber = FALSE; bNewItem = TRUE; while (TRUE) { switch (EvalThisChar (*pwcThisChar, wckDelimiter)) { case kDigit: // if this is the first kDigit after a kDelimiter, then // set flags to start computing the new number if (bNewItem) { bNewItem = FALSE; bValidNumber = TRUE; } if (bValidNumber) { dwThisNumber *= 10; dwThisNumber += (*pwcThisChar - L'0'); } break; case kDelimiter: // a delimter is either the kDelimiter character or the // end of the string ('\0') if when the kDelimiter has been // reached a valid number was found, then compare it to the // number from the argument list. if this is the end of the // string and no match was found, then return. // if (bValidNumber) { if (dwThisNumber == dwNumber) return TRUE; bValidNumber = FALSE; } if (*pwcThisChar == 0) { return FALSE; } else { bNewItem = TRUE; dwThisNumber = 0; } break; case kInvalid: // if an kInvalid character was encountered, ignore all // characters up to the next kDelimiter and then start fresh. // the kInvalid number is not compared. bValidNumber = FALSE; break; default: break; } pwcThisChar++; } } // IsNumberInUnicodeList VOID Pfp_vOpenEventLog ( VOID ) /*++ Routine Description: Reads the level of event logging from the registry and opens the channel to the event logger for subsequent event log entries. Arguments: Return Value: Revision History: --*/ { if (gpd.hEventLog == NULL) { gpd.hEventLog = RegisterEventSource( NULL, gszAppName ); if (gpd.hEventLog != NULL) { Pf_vReportEvent( kInformation | kDebug, MSG_PERF_LOG_OPEN, 0, NULL, NULL ); } } } VOID Pfp_vCloseEventLog( VOID ) /*++ Routine Description: Closes the global event log connection. Arguments: Return Value: --*/ { if( gpd.hEventLog ) { Pf_vReportEvent( kInformation | kDebug, MSG_PERF_LOG_CLOSE, 0, NULL, NULL ); DeregisterEventSource( gpd.hEventLog ); gpd.hEventLog = NULL; } } VOID Pf_vReportEvent( IN UINT uLevel, IN DWORD dwMessage, IN DWORD cbData, OPTIONAL IN PVOID pvData, OPTIONAL IN LPCWSTR pszFirst, OPTIONAL ... ) /*++ Routine Description: Log an event. Arguments: uLevel - Combination of level (e.g., kSuccess, kError) and type (e.g., kUser, kVerbose). dwMessage - Message number. cbData - Size of optional data. pvData - Optional data. pszFirst - String inserts begin here, optional. Return Value: --*/ { LPCWSTR apszMergeStrings[kMaxMergeStrings]; UINT cMergeStrings = 0; va_list vargs; // // Skip the message if the log level is not high enough. // if(( uLevel >> kLevelShift ) > gpd.uLogLevel ) { return; } if( !gpd.hEventLog ) { Pfp_vOpenEventLog(); } if( !gpd.hEventLog ) { return; } if( pszFirst ) { apszMergeStrings[cMergeStrings++] = pszFirst; va_start( vargs, pszFirst ); while(( cMergeStrings < kMaxMergeStrings ) && ( apszMergeStrings[cMergeStrings] = va_arg( vargs, LPCWSTR ))) { cMergeStrings++; } va_end( vargs ); } ReportEvent( gpd.hEventLog, (WORD)gauEventLogTable[uLevel & kTypeMask], 0, dwMessage, NULL, (WORD)cMergeStrings, cbData, apszMergeStrings, pvData ); }