|
|
/**********************************************************************/ /** 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
|