288 lines
7.6 KiB
C++
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
|
|
|
|
|