home *** CD-ROM | disk | FTP | other *** search
- /*++
-
- Copyright (c) 1995-6 Microsoft Corporation
-
- Module Name:
-
- perfgen.c
-
- Abstract:
-
- This file implements an Extensible Performance Object that displays
- generated signals
-
- Created:
-
- Bob Watson 28-Jul-1995
-
- Revision History
-
-
- --*/
-
- //
- // Include Files
- //
-
- #include <windows.h>
- #include <string.h>
- #include <winperf.h>
- #include <math.h>
- #include "genctrs.h" // error message definition
- #include "perfmsg.h"
- #include "perfutil.h"
- #include "datagen.h"
-
- // define constant value counter's value here, any number will do.
-
- #define CONSTANT_VALUE_VALUE 49
- //
- // References to constants which initialize the Object type definitions
- //
-
- extern SIGGEN_DATA_DEFINITION SigGenDataDefinition;
-
- 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 OpenSigGenPerformanceData;
- PM_COLLECT_PROC CollectSigGenPerformanceData;
- PM_CLOSE_PROC CloseSigGenPerformanceData;
-
- typedef struct _WAVE_DATA {
- DWORD dwPeriod;
- DWORD dwAmplitude;
- LPWSTR szInstanceName;
- } WAVE_DATA, *PWAVE_DATA;
-
- static WAVE_DATA wdInstance[] =
- {
- {1000, 100, L" 1 Second"},
- {10000, 100, L" 10 Second"},
- {20000, 100, L" 20 Second"},
- {50000, 100, L" 50 Second"},
- {100000, 100, L"100 Second"}
- };
-
- static const DWORD NUM_INSTANCES =
- (sizeof(wdInstance)/sizeof(wdInstance[0]));
-
- static double dPi = 3.1415926590;
- static double d2Pi = 2.0 * 3.1415926590;
-
-
- static
- DWORD
- GetTimeInMilliSeconds ()
- {
- SYSTEMTIME st;
- DWORD dwReturn;
-
- GetSystemTime (&st);
- dwReturn = (DWORD)st.wMilliseconds;
- dwReturn += (DWORD)st.wSecond * 1000L;
- dwReturn += (DWORD)st.wMinute * 60000L;
- dwReturn += (DWORD)st.wHour * 3600000L;
- dwReturn += (DWORD)st.wDay * 86500000L;
-
- // that's good enough for what it's for
-
- return dwReturn;
- }
-
- DWORD APIENTRY
- OpenSigGenPerformanceData(
- LPWSTR lpDeviceNames
- )
-
- /*++
-
- Routine Description:
-
- This routine will initialize the data structures used to pass
- data back to the registry
-
- Arguments:
-
- Pointer to object ID of each device to be opened (PerfGen)
-
- Return Value:
-
- None.
-
- --*/
-
- {
- LONG status;
- HKEY hKeyDriverPerf;
- DWORD size;
- DWORD type;
- DWORD dwFirstCounter;
- DWORD dwFirstHelp;
-
- //
- // 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 (!dwOpenCount) {
- // open Eventlog interface
-
- hEventLog = MonOpenEventLog();
-
- // get counter and help index base values from registry
- // Open key to registry entry
- // read First Counter and First Help values
- // update static data strucutures by adding base to
- // offset value in structure.
-
- status = RegOpenKeyEx (
- HKEY_LOCAL_MACHINE,
- "SYSTEM\\CurrentControlSet\\Services\\PerfGen\\Performance",
- 0L,
- KEY_READ,
- &hKeyDriverPerf);
-
- if (status != ERROR_SUCCESS) {
- REPORT_ERROR_DATA (GENPERF_UNABLE_OPEN_DRIVER_KEY, 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;
- }
-
- size = sizeof (DWORD);
- status = RegQueryValueEx(
- hKeyDriverPerf,
- "First Counter",
- 0L,
- &type,
- (LPBYTE)&dwFirstCounter,
- &size);
-
- if (status != ERROR_SUCCESS) {
- REPORT_ERROR_DATA (GENPERF_UNABLE_READ_FIRST_COUNTER, 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;
- }
-
- size = sizeof (DWORD);
- status = RegQueryValueEx(
- hKeyDriverPerf,
- "First Help",
- 0L,
- &type,
- (LPBYTE)&dwFirstHelp,
- &size);
-
- if (status != ERROR_SUCCESS) {
- REPORT_ERROR_DATA (GENPERF_UNABLE_READ_FIRST_HELP, 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;
- }
-
- //
- // NOTE: the initialization program could also retrieve
- // LastCounter and LastHelp if they wanted to do
- // bounds checking on the new number. e.g.
- //
- // counter->CounterNameTitleIndex += dwFirstCounter;
- // if (counter->CounterNameTitleIndex > dwLastCounter) {
- // LogErrorToEventLog (INDEX_OUT_OF_BOUNDS);
- // }
-
- SigGenDataDefinition.SigGenObjectType.ObjectNameTitleIndex += dwFirstCounter;
- SigGenDataDefinition.SigGenObjectType.ObjectHelpTitleIndex += dwFirstHelp;
-
- // assign index of default counter (Sine Wave)
- SigGenDataDefinition.SigGenObjectType.DefaultCounter = 0;
-
- SigGenDataDefinition.SineWaveDef.CounterNameTitleIndex += dwFirstCounter;
- SigGenDataDefinition.SineWaveDef.CounterHelpTitleIndex += dwFirstHelp;
-
- SigGenDataDefinition.TriangleWaveDef.CounterNameTitleIndex += dwFirstCounter;
- SigGenDataDefinition.TriangleWaveDef.CounterHelpTitleIndex += dwFirstHelp;
-
- SigGenDataDefinition.SquareWaveDef.CounterNameTitleIndex += dwFirstCounter;
- SigGenDataDefinition.SquareWaveDef.CounterHelpTitleIndex += dwFirstHelp;
-
- SigGenDataDefinition.ConstantValueDef.CounterNameTitleIndex += dwFirstCounter;
- SigGenDataDefinition.ConstantValueDef.CounterHelpTitleIndex += dwFirstHelp;
-
- RegCloseKey (hKeyDriverPerf); // close key to registry
-
- bInitOK = TRUE; // ok to use this function
- }
-
- dwOpenCount++; // increment OPEN counter
-
- status = ERROR_SUCCESS; // for successful exit
-
- OpenExitPoint:
-
- return status;
- }
-
-
- DWORD APIENTRY
- CollectSigGenPerformanceData(
- IN LPWSTR lpValueName,
- IN OUT LPVOID *lppData,
- IN OUT LPDWORD lpcbTotalBytes,
- IN OUT LPDWORD lpNumObjectTypes
- )
- /*++
-
- Routine Description:
-
- This routine will return the data for the Signal Generator counters.
-
- Arguments:
-
- IN 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 writted 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 writted 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.
-
- --*/
- {
- // Variables for reformating the data
-
- PERF_INSTANCE_DEFINITION *pPerfInstanceDefinition;
- DWORD dwThisInstance;
- ULONG SpaceNeeded;
- SIGGEN_DATA_DEFINITION *pSigGenDataDefinition;
- DWORD dwQueryType;
- DWORD dwTime;
- DWORD dwPhase;
- double dPhase, dSin;
- LONG lValue;
- PSIGGEN_COUNTER pSC;
-
- //
- // 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;
- }
-
- if (dwQueryType == QUERY_ITEMS){
- if ( !(IsNumberInUnicodeList (SigGenDataDefinition.SigGenObjectType.ObjectNameTitleIndex, lpValueName))) {
- // request received for data object not provided by this routine
- *lpcbTotalBytes = (DWORD) 0;
- *lpNumObjectTypes = (DWORD) 0;
- return ERROR_SUCCESS;
- }
- }
-
- pSigGenDataDefinition = (SIGGEN_DATA_DEFINITION *) *lppData;
-
- SpaceNeeded = sizeof(SIGGEN_DATA_DEFINITION) +
- (NUM_INSTANCES * (sizeof(PERF_INSTANCE_DEFINITION) +
- (24) + // size of instance names
- sizeof (SIGGEN_COUNTER)));
-
- if ( *lpcbTotalBytes < SpaceNeeded ) {
- *lpcbTotalBytes = (DWORD) 0;
- *lpNumObjectTypes = (DWORD) 0;
- return ERROR_MORE_DATA;
- }
-
- // Get current time for this sample
- //
- dwTime = GetTimeInMilliSeconds();
- //
- // Copy the (constant, initialized) Object Type and counter definitions
- // to the caller's data buffer
- //
- memmove(pSigGenDataDefinition,
- &SigGenDataDefinition,
- sizeof(SIGGEN_DATA_DEFINITION));
- //
- // Create data for return for each instance
- //
- pPerfInstanceDefinition = (PERF_INSTANCE_DEFINITION *)
- &pSigGenDataDefinition[1];
-
- for (dwThisInstance = 0; dwThisInstance < NUM_INSTANCES; dwThisInstance++) {
-
- MonBuildInstanceDefinition(
- pPerfInstanceDefinition,
- (PVOID *)&pSC,
- 0,
- 0,
- (DWORD)-1, // use name
- wdInstance[dwThisInstance].szInstanceName);
-
- pSC->CounterBlock.ByteLength = sizeof (SIGGEN_COUNTER);
-
- //**********************************************************
- //
- // for this particular example, the data is "created" here.
- // normally it would be read from the appropriate device or
- // application program.
- //
- //**********************************************************
-
- // comput phase for this instance period
- dwPhase = dwTime % wdInstance[dwThisInstance].dwPeriod;
- //
- // compute sinewave value here
- //
- dPhase = (double)dwPhase / (double)wdInstance[dwThisInstance].dwPeriod;
- dPhase *= d2Pi;
-
- // the cosine function is used to keep the phase aligned with the
- // other wave forms
- dSin = -cos(dPhase);
- // adjust amplitude and add .5 to round to integer correctly
- dSin *= (double)((wdInstance[dwThisInstance].dwAmplitude) / 2.0) + 0.5 ;
-
- lValue = (LONG)dSin;
- lValue += wdInstance[dwThisInstance].dwAmplitude / 2; // to move negative values above 0
-
- // save sine value
- pSC->dwSineWaveValue = (DWORD)lValue;
-
- // compute triangle wave value here
-
- if (dwPhase < (wdInstance[dwThisInstance].dwPeriod / 2)) {
- lValue = (LONG)((dwPhase * wdInstance[dwThisInstance].dwAmplitude) / (wdInstance[dwThisInstance].dwPeriod / 2));
- } else {
- lValue = (LONG)(((wdInstance[dwThisInstance].dwPeriod - dwPhase) * wdInstance[dwThisInstance].dwAmplitude) /
- (wdInstance[dwThisInstance].dwPeriod / 2));
- }
- // save triangle value
- pSC->dwTriangleWaveValue = (DWORD) lValue;
-
- //
- // compute square wave value
- //
- if (dwPhase <= (wdInstance[dwThisInstance].dwPeriod / 2)) {
- lValue = 0;
- } else {
- lValue = (LONG)wdInstance[dwThisInstance].dwAmplitude;
- }
- // save square value
- pSC->dwSquareWaveValue = (DWORD) lValue;
-
- // finally the constant value (same fore every instance)
- pSC->dwConstantValue = (DWORD)CONSTANT_VALUE_VALUE;
-
- // update instance pointer for next instance
- pPerfInstanceDefinition = (PERF_INSTANCE_DEFINITION *)&pSC[1];
- }
- // update arguments for return
-
- *lppData = (PVOID)pPerfInstanceDefinition;
-
- *lpNumObjectTypes = 1;
-
- pSigGenDataDefinition->SigGenObjectType.TotalByteLength =
- *lpcbTotalBytes = (PBYTE)pPerfInstanceDefinition -
- (PBYTE) pSigGenDataDefinition;
-
- // update instance count
- pSigGenDataDefinition->SigGenObjectType.NumInstances = NUM_INSTANCES;
-
- return ERROR_SUCCESS;
- }
-
-
- DWORD APIENTRY
- CloseSigGenPerformanceData(
- )
-
- /*++
-
- Routine Description:
-
- This routine closes the open handles to the Signal Gen counters.
-
- Arguments:
-
- None.
-
-
- Return Value:
-
- ERROR_SUCCESS
-
- --*/
-
- {
- if (!(--dwOpenCount)) { // when this is the last thread...
-
- MonCloseEventLog();
- }
-
- return ERROR_SUCCESS;
-
- }