331 lines
6.4 KiB
C++
331 lines
6.4 KiB
C++
/*++
|
|
|
|
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 );
|
|
}
|
|
|
|
|
|
|
|
|