windows-nt/Source/XPSP1/NT/inetsrv/iis/svcs/w3/perfmon/perfw3.cxx
2020-09-26 16:20:57 +08:00

288 lines
7.6 KiB
C++

/**********************************************************************/
/** Microsoft Windows NT **/
/** Copyright(c) Microsoft Corp., 1993 **/
/**********************************************************************/
/*
perfw3.c
This file implements the Extensible Performance Objects for
the W3 Server service.
FILE HISTORY:
KeithMo 07-Jun-1993 Created, based on RussBl's sample code.
MuraliK 16-Nov-1995 Modified dependencies and removed NetApi
SophiaC 06-Nov-1996 Supported mutlitiple instances
MingLu 21-Nov-1999 Optimized W3 performance counter routine
*/
#include <windows.h>
#include <winperf.h>
#include <lm.h>
#include <iis64.h>
#include "iisinfo.h"
#include "w3svc.h"
#include "w3ctrs.h"
#include "w3msg.h"
#include "perfutil.h"
#define APP_NAME (TEXT("W3Ctrs"))
//
// Private globals.
//
DWORD cOpens = 0; // Active "opens" reference count.
BOOL fInitOK = FALSE; // TRUE if DLL initialized OK.
DWORD cbTotalRequired = 0; // Total space for retrieving perf data
HANDLE hEventLog = NULL; // Event log handle
//
// Public prototypes.
//
PM_OPEN_PROC OpenW3PerformanceData;
PM_COLLECT_PROC CollectW3PerformanceData;
PM_CLOSE_PROC CloseW3PerformanceData;
//
// Public functions.
//
/*******************************************************************
NAME: OpenW3PerformanceData
SYNOPSIS: Initializes the data structures used to communicate
performance counters with the registry.
ENTRY: lpDeviceNames - Poitner to object ID of each device
to be opened.
RETURNS: DWORD - Win32 status code.
HISTORY:
KeithMo 07-Jun-1993 Created.
********************************************************************/
DWORD OpenW3PerformanceData( LPWSTR lpDeviceNames )
{
NET_API_STATUS neterr;
//
// Since WINLOGON is multi-threaded and will call this routine in
// order to service remote performance queries, this library
// must keep track of how many times it has been opened (i.e.
// how many threads have accessed it). The registry routines will
// limit access to the initialization routine to only one thread
// at a time so synchronization (i.e. reentrancy) should not be
// a problem.
//
if( !fInitOK )
{
//
// This is the *first* open.
//
// open event log interface
if (hEventLog == NULL){
hEventLog = RegisterEventSource (
(LPTSTR)NULL, // Use Local Machine
APP_NAME // event log app name to find in registry
);
if (hEventLog == NULL)
{
return GetLastError();
}
}
// call rpc to init remote data structure for w3 counters
neterr = InitW3CounterStructure(NULL,
&cbTotalRequired
);
// log rpc err info to event log
if( neterr != NERR_Success )
{
// if the server is down, we don't log an error.
if ( !( neterr == RPC_S_SERVER_UNAVAILABLE ||
neterr == RPC_S_UNKNOWN_IF ||
neterr == ERROR_SERVICE_NOT_ACTIVE ||
neterr == RPC_S_CALL_FAILED_DNE ))
{
ReportEvent (hEventLog, EVENTLOG_ERROR_TYPE,
0, W3_UNABLE_QUERY_W3SVC_DATA,
(PSID)NULL, 0,
sizeof(neterr), NULL,
(PVOID)(&neterr));
}
return ERROR_SUCCESS;
}
if( cbTotalRequired == 0 )
{
return ERROR_SUCCESS;
}
fInitOK = true;
}
//
// Bump open counter.
//
InterlockedIncrement((LPLONG)&cOpens);
return ERROR_SUCCESS;
} // OpenW3PerformanceData
/*******************************************************************
NAME: CollectW3PerformanceData
SYNOPSIS: Initializes the data structures used to communicate
ENTRY: lpValueName - The name of the value to retrieve.
lppData - On entry contains a pointer to the buffer to
receive the completed PerfDataBlock & subordinate
structures. On exit, points to the first bytes
*after* the data structures added by this routine.
lpcbTotalBytes - On entry contains a pointer to the
size (in BYTEs) of the buffer referenced by lppData.
On exit, contains the number of BYTEs added by this
routine.
lpNumObjectTypes - Receives the number of objects added
by this routine.
RETURNS: DWORD - Win32 status code. MUST be either NO_ERROR
or ERROR_MORE_DATA.
HISTORY:
KeithMo 07-Jun-1993 Created.
********************************************************************/
DWORD CollectW3PerformanceData( LPWSTR lpValueName,
LPVOID * lppData,
LPDWORD lpcbTotalBytes,
LPDWORD lpNumObjectTypes )
{
NET_API_STATUS neterr;
LPBYTE * lppPerfData = (LPBYTE*)lppData;
//
// No need to even try if we failed to open...
//
if( !fInitOK )
{
*lpcbTotalBytes = 0;
*lpNumObjectTypes = 0;
//
// According to the Performance Counter design, this
// is a successful exit. Go figure.
//
return ERROR_SUCCESS;
}
if( *lpcbTotalBytes < cbTotalRequired ){
//*lpcbTotalBytes = cbTotalRequired;
return ERROR_MORE_DATA;
}
//One rpc call to get all the counters infomation
neterr = CollectW3PerfData(
NULL,
lpValueName,
*lppPerfData,
lpcbTotalBytes,
lpNumObjectTypes
);
// log rpc err info to event log
if( neterr != NERR_Success )
{
// if the server is down, we don't log an error.
if ( !( neterr == RPC_S_SERVER_UNAVAILABLE ||
neterr == RPC_S_UNKNOWN_IF ||
neterr == ERROR_SERVICE_NOT_ACTIVE ||
neterr == RPC_S_CALL_FAILED_DNE ))
{
ReportEvent (hEventLog, EVENTLOG_ERROR_TYPE,
0, W3_UNABLE_QUERY_W3SVC_DATA,
(PSID)NULL, 0,
sizeof(neterr), NULL,
(PVOID)(&neterr));
}
*lpcbTotalBytes = 0;
*lpNumObjectTypes = 0;
return ERROR_SUCCESS;
}
// align the total bytes to a QWORD_MULTIPLE
*lpcbTotalBytes = QWORD_MULTIPLE(*lpcbTotalBytes);
if( *lpcbTotalBytes && *lpNumObjectTypes )
{
*lppData = *lppPerfData + *lpcbTotalBytes;
}
return ERROR_SUCCESS;
} // CollectW3PerformanceData
/*******************************************************************
NAME: CloseW3PerformanceData
SYNOPSIS: Terminates the performance counters.
RETURNS: DWORD - Win32 status code.
HISTORY:
KeithMo 07-Jun-1993 Created.
********************************************************************/
DWORD CloseW3PerformanceData( VOID )
{
//
// No real cleanup to do here.
//
DWORD dwCount = InterlockedDecrement((LPLONG)&cOpens);
if (dwCount == 0)
{
if (hEventLog != NULL)
{
DeregisterEventSource (hEventLog);
hEventLog = NULL;
}
}
return ERROR_SUCCESS;
} // CloseW3PerformanceData