windows-nt/Source/XPSP1/NT/net/rras/ras/ui/perf/perfras.c
2020-09-26 16:20:57 +08:00

575 lines
14 KiB
C

/*++ BUILD Version: 0001 // Increment this if a change has global effects
Copyright (c) 1992 Microsoft Corporation
Module Name:
perfras.c
Abstract:
This file implements the Extensible Objects for the Ras object type
Created:
Russ Blake 24 Feb 93
Thomas J. Dimitri 28 May 93
Revision History
Ram Cherala 15 Feb 96
Don't hard code the length of the instance name in
CollectRasPerformanceData.
PerfMon checks the actual instance name length to determine
if the name is properly formatted, so compute it for each
instance name.
Patrick Y. Ng 12 Aug 93
--*/
//
// Include Files
//
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <ntddser.h>
#include <windows.h>
#include <string.h>
#include <wcstr.h>
#include <winperf.h>
#include <malloc.h>
#include <ntprfctr.h>
#include "globals.h"
#include "rasctrs.h" // error message definition
#include "perfmsg.h"
#include "perfutil.h"
#include "dataras.h"
#include "port.h"
#include <rasman.h>
#include <serial.h>
#include <isdn.h>
#include <raserror.h>
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
//
// References to constants which initialize the Object type definitions
//
DWORD dwOpenCount = 0; // count of "Open" threads
BOOL bInitOK = FALSE; // true = DLL initialized OK
//
// Function Prototypes
//
// these are used to insure that the data collection functions
// accessed by Perflib will have the correct calling format.
//
PM_OPEN_PROC OpenRasPerformanceData;
PM_COLLECT_PROC CollectRasPerformanceData;
PM_CLOSE_PROC CloseRasPerformanceData;
//***
//
// Routine Description:
//
// This routine will open and map the memory used by the RAS driver to
// pass performance data in. This routine also initializes the data
// structures used to pass data back to the registry
//
// Arguments:
//
// Pointer to object ID of each device to be opened (RAS)
//
//
// Return Value:
//
// None.
//
//***
DWORD OpenRasPerformanceData( LPWSTR lpDeviceNames )
{
LONG status;
HKEY hKeyDriverPerf;
DWORD size;
DWORD type;
//
// Since SCREG 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 (!dwOpenCount)
{
//
// open Eventlog interface
//
hEventLog = MonOpenEventLog();
//
// Load rasman.dll and get all the required functions.
//
status = InitRasFunctions();
if( status != ERROR_SUCCESS )
{
REPORT_ERROR (RASPERF_UNABLE_DO_IOCTL, LOG_USER);
// this is fatal, if we can't get data then there's no
// point in continuing.
goto OpenExitPoint;
}
InitObjectCounterIndex( RAS_FIRST_COUNTER_INDEX,
RAS_FIRST_HELP_INDEX );
//
// Initialize all the port information.
//
status = InitPortInfo();
if (status != ERROR_SUCCESS)
{
REPORT_ERROR_DATA (RASPERF_UNABLE_CREATE_PORT_TABLE, LOG_USER,
&status, sizeof(status));
// this is fatal, if we can't get the base values of the
// counter or help names, then the names won't be available
// to the requesting application so there's not much
// point in continuing.
goto OpenExitPoint;
}
bInitOK = TRUE; // ok to use this function
}
dwOpenCount++; // increment OPEN counter
status = ERROR_SUCCESS; // for successful exit
OpenExitPoint:
return status;
}
//***
//
// Routine Description:
//
// This routine will return the data for the RAS counters.
//
// Arguments:
//
// IN OUT LPWSTR lpValueName
// pointer to a wide character string passed by registry.
//
// IN OUT LPVOID *lppData
// IN: pointer to the address of the buffer to receive the completed
// PerfDataBlock and subordinate structures. This routine will
// append its data to the buffer starting at the point referenced
// by *lppData.
// OUT: points to the first byte after the data structure added by this
// routine. This routine updated the value at lppdata after appending
// its data.
//
// IN OUT LPDWORD lpcbTotalBytes
// IN: the address of the DWORD that tells the size in bytes of the
// buffer referenced by the lppData argument
// OUT: the number of bytes added by this routine is written to the
// DWORD pointed to by this argument
//
// IN OUT LPDWORD NumObjectTypes
// IN: the address of the DWORD to receive the number of objects added
// by this routine
// OUT: the number of objects added by this routine is written to the
// DWORD pointed to by this argument
//
// Return Value:
//
// ERROR_MORE_DATA if buffer passed is too small to hold data
// any error conditions encountered are reported to the event log if
// event logging is enabled.
//
// ERROR_SUCCESS if success or any other error. Errors, however are
// also reported to the event log.
//
//***
DWORD CollectRasPerformanceData(
IN LPWSTR lpValueName,
IN OUT LPVOID *lppData,
IN OUT LPDWORD lpcbTotalBytes,
IN OUT LPDWORD lpNumObjectTypes )
{
// Variables for reformating the data
NTSTATUS Status;
ULONG SpaceNeeded;
PBYTE pbIn = (PBYTE) *lppData;
// variables used for error logging
DWORD dwQueryType;
// Variables used to record which objects are required
static BOOL IsRasPortObject;
static BOOL IsRasTotalObject;
//
// Reset some output variables.
//
*lpNumObjectTypes = 0;
//
// before doing anything else, see if Open went OK
//
if (!bInitOK)
{
// unable to continue because open failed.
*lpcbTotalBytes = (DWORD) 0;
*lpNumObjectTypes = (DWORD) 0;
return ERROR_SUCCESS; // yes, this is a successful exit
}
//
// see if this is a foreign (i.e. non-NT) computer data request
//
dwQueryType = GetQueryType (lpValueName);
if (dwQueryType == QUERY_FOREIGN)
{
// this routine does not service requests for data from
// Non-NT computers
*lpcbTotalBytes = (DWORD) 0;
*lpNumObjectTypes = (DWORD) 0;
return ERROR_SUCCESS;
}
else if (dwQueryType == QUERY_ITEMS)
{
IsRasPortObject = IsNumberInUnicodeList (gRasPortDataDefinition.RasObjectType.ObjectNameTitleIndex,
lpValueName);
IsRasTotalObject = IsNumberInUnicodeList (gRasTotalDataDefinition.RasObjectType.ObjectNameTitleIndex,
lpValueName);
if ( !IsRasPortObject && !IsRasTotalObject )
{
//
// request received for data object not provided by this routine
//
*lpcbTotalBytes = (DWORD) 0;
*lpNumObjectTypes = (DWORD) 0;
return ERROR_SUCCESS;
}
}
else if( dwQueryType == QUERY_GLOBAL )
{
IsRasPortObject = IsRasTotalObject = TRUE;
}
//
// Now check to see if we have enough space to hold all the data
//
SpaceNeeded = GetSpaceNeeded(IsRasPortObject, IsRasTotalObject);
// DbgPrint("RASCTRS: IN TotalBytes=0x%x, SpaceNeeded=0x%x\n",
// *lpcbTotalBytes, SpaceNeeded);
if ( *lpcbTotalBytes < SpaceNeeded )
{
*lpcbTotalBytes = (DWORD) 0;
*lpNumObjectTypes = (DWORD) 0;
return ERROR_MORE_DATA;
}
//
// Collect all the RAS statistics now.
//
Status = CollectRasStatistics();
if( Status != ERROR_SUCCESS )
{
REPORT_ERROR_DATA (RASPERF_CANNOT_GET_RAS_STATISTICS, LOG_USER,
&Status, sizeof(Status));
*lpcbTotalBytes = (DWORD) 0;
*lpNumObjectTypes = (DWORD) 0;
return ERROR_SUCCESS;
}
//DbgPrint("RASCTRS: pbIn = 0x%x\n", pbIn);
//
// We first fill in the data for object Ras Port, if needed.
//
if( IsRasPortObject )
{
PRAS_PORT_DATA_DEFINITION pRasPortDataDefinition;
RAS_PORT_INSTANCE_DEFINITION RasPortInstanceDefinition;
PRAS_PORT_INSTANCE_DEFINITION pRasPortInstanceDefinition;
DWORD cPorts;
DWORD i;
PVOID pData;
cPorts = GetNumOfPorts();
pRasPortDataDefinition = (PRAS_PORT_DATA_DEFINITION) *lppData;
//DbgPrint("RASCTRS: pRasPortDataDefinition = 0x%x\n", pRasPortDataDefinition);
//
// Copy the (constant, initialized) Object Type and counter definitions
// to the caller's data buffer
//
memcpy( pRasPortDataDefinition,
&gRasPortDataDefinition,
sizeof(RAS_PORT_DATA_DEFINITION));
//
// Now copy the instance definition and counter block.
//
//
// First construct the default perf instance definition.
//
RasPortInstanceDefinition.RasInstanceType.ByteLength =
ALIGN8(sizeof(RAS_PORT_INSTANCE_DEFINITION));
RasPortInstanceDefinition.RasInstanceType.ParentObjectTitleIndex = 0;
RasPortInstanceDefinition.RasInstanceType.ParentObjectInstance = 0;
RasPortInstanceDefinition.RasInstanceType.NameOffset =
sizeof(PERF_INSTANCE_DEFINITION);
//DbgPrint("RASCTRS: RasPortinstanceDefinition.ByteLength = 0x%x\n",
// RasPortInstanceDefinition.RasInstanceType.ByteLength);
/* Don't hard code the length of the instance name.
** PerfMon checks the actual instance name length to determine
** if the name is properly formatted, so compute it for
** each instance name. ramc 2/15/96.
** RasPortInstanceDefinition.RasInstanceType.NameLength =
** sizeof( WCHAR ) * MAX_PORT_NAME;
*/
//
// Get to the end of the data definition.
//
// pData = (PVOID) &(pRasPortDataDefinition[1]);
pData = ((PBYTE) pRasPortDataDefinition + ALIGN8(sizeof(RAS_PORT_DATA_DEFINITION)));
for( i=0; i < cPorts; i++ )
{
//DbgPrint("RASCTRS: port %d, pData = 0x%x\n", i, pData);
//
// First copy the instance definition data.
//
RasPortInstanceDefinition.RasInstanceType.UniqueID = PERF_NO_UNIQUE_ID;
lstrcpyW( (LPWSTR)&RasPortInstanceDefinition.InstanceName,
GetInstanceName(i) );
// Compute the instance name length
RasPortInstanceDefinition.RasInstanceType.NameLength =
(lstrlenW(RasPortInstanceDefinition.InstanceName) + 1) *
sizeof( WCHAR );
memcpy( pData, &RasPortInstanceDefinition,
sizeof( RasPortInstanceDefinition ) );
//
// Move pPerfInstanceDefinition to the beginning of data block.
//
pData = (PVOID)((PBYTE) pData + ALIGN8(sizeof(RAS_PORT_INSTANCE_DEFINITION)));
//
// Get the data block. Note that pPerfInstanceDefinition will be
// set to the next available byte.
//
GetInstanceData( i, &pData );
}
//
// Set *lppData to the next available byte.
//
*lppData = pData;
(*lpNumObjectTypes)++;
}
//
// Then we fill in the data for object Ras Total, if needed.
//
if( IsRasTotalObject )
{
PRAS_TOTAL_DATA_DEFINITION pRasTotalDataDefinition;
PVOID pData;
pRasTotalDataDefinition = (PRAS_TOTAL_DATA_DEFINITION) *lppData;
//DbgPrint("RASCTRS: RasTotalDataDefinition = 0x%x\n",
// pRasTotalDataDefinition);
//
// Copy the (constant, initialized) Object Type and counter definitions
// to the caller's data buffer
//
memcpy( pRasTotalDataDefinition,
&gRasTotalDataDefinition,
sizeof(RAS_TOTAL_DATA_DEFINITION));
//
// Now copy the counter block.
//
//
// Set pRasTotalDataDefinition to the beginning of counter block.
//
// pData = (PVOID) &(pRasTotalDataDefinition[1]);
pData = (PBYTE) pRasTotalDataDefinition + ALIGN8(sizeof(RAS_TOTAL_DATA_DEFINITION));
//DbgPrint("RASCTRS: pData for total = 0x%x\n", pData);
GetTotalData( &pData );
//
// Set *lppData to the next available byte.
//
*lppData = pData;
(*lpNumObjectTypes)++;
}
//DbgPrint("RASCTRS: pbOut = 0x%x\n", *lppData);
*lpcbTotalBytes = SpaceNeeded;
/*
DbgPrint("pbIn+SpaceNeeded=0x%x, *lppData=0x%x\n",
pbIn+SpaceNeeded,
*lppData);
*/
ASSERT((pbIn + SpaceNeeded) == (PBYTE) *lppData);
//DbgPrint("RASCTRS: OUT TotalBytes=0x%x\n", *lpcbTotalBytes);
return ERROR_SUCCESS;
}
//***
//
// Routine Description:
//
// This routine closes the open handles to RAS device performance
// counters.
//
// Arguments:
//
// None.
//
// Return Value:
//
// ERROR_SUCCESS
//
//***
DWORD CloseRasPerformanceData()
{
if (!(--dwOpenCount))
{
// when this is the last thread...
MonCloseEventLog();
ClosePortInfo();
}
return ERROR_SUCCESS;
}