|
|
/*
* HrStorageEntry.c v0.10 * Generated in conjunction with Management Factory scripts: * script version: SNMPv1, 0.16, Apr 25, 1996 * project: D:\TEMP\EXAMPLE\HOSTMIB **************************************************************************** * * * (C) Copyright 1995 DIGITAL EQUIPMENT CORPORATION * * * * This software is an unpublished work protected under the * * the copyright laws of the United States of America, all * * rights reserved. * * * * In the event this software is licensed for use by the United * * States Government, all use, duplication or disclosure by the * * United States Government is subject to restrictions as set * * forth in either subparagraph (c)(1)(ii) of the Rights in * * Technical Data And Computer Software Clause at DFARS * * 252.227-7013, or the Commercial Computer Software Restricted * * Rights Clause at FAR 52.221-19, whichever is applicable. * * * **************************************************************************** * * Facility: * * Windows NT SNMP Extension Agent * * Abstract: * * This module contains the code for dealing with the get, set, and * instance name routines for the HrStorageEntry. * Actual instrumentation code is supplied by the developer. * * Functions: * * A get and set routine for each attribute in the class. * * The routines for instances within the class, plus the cache * initialization function "Gen_Hrstorage_Cache()". * * Author: * * D. D. Burns @ Webenable Inc * * Revision History: * * V1.00 - 04/17/97 D. D. Burns Genned: Thu Nov 07 16:40:22 1996 * V1.01 - 05/15/97 D. D. Burns Move Disk Label/Size acquisitions * to cache from real-time * V1.02 - 06/18/97 D. D. Burns Add spt to scan event log for * allocation failures * */
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <malloc.h>
#include <snmp.h>
#include "mib.h"
#include "smint.h"
#include "hostmsmi.h"
#include "user.h" /* Developer supplied include file */
#include "HMCACHE.H" /* Cache-related definitions */
#include "string.h" /* For string manipulation in "Gen_Hrstorage_Cache"*/
#include "stdio.h" /* For sprintf */
#include <limits.h>
/*
|============================================================================== | Function prototypes for this module. | */ /* ScanLog_Failures - Scan Event Log for Storage Allocation Failures */ static UINT ScanLog_Failures( CHAR *device );
#if defined(CACHE_DUMP)
/* debug_print_hrstorage - Prints a Row from Hrstorage sub-table */ static void debug_print_hrstorage( CACHEROW *row /* Row in hrstorage table */ ); #endif
/*
|============================================================================== | Cache Refresh Time | | The cache for the hrStorage and hrFSTable tables are refreshed automatically | when a request arrives at the hrStorage --AND-- the cache is older than | CACHE_MAX_AGE in seconds. | */ static LARGE_INTEGER cache_time; // 100ns Timestamp of cache (when last refreshed)
#define CACHE_MAX_AGE 120 // Maximum age in seconds
/*
|============================================================================== | Create the list-head for the HrStorage table cache. | | This list-head is globally accessible so the logic that loads hrFSTable | can scan this cache for matches (among other reasons). | | (This macro is defined in "HMCACHE.H"). */ CACHEHEAD_INSTANCE(hrStorage_cache, debug_print_hrstorage);
/*
|============================================================================== | Local string for this kind of "storage". */ #define VM "Virtual Memory"
#define PHYMEM "Physical Memory"
/*
* ============================================================================ * GetHrStorageIndex * A unique value for each logical storage are contained by the host. * * Gets the value for HrStorageIndex. * * Arguments: * * outvalue address to return variable value * accesss Reserved for future security use * instance address of instance name as ordered native * data type(s) * * Return Codes: * * Standard PDU error codes. * * SNMP_ERRORSTATUS_NOERROR Successful get * SNMP_ERRORSTATUS_GENERR Catch-all failure code * mibtget.c v0.10 * | =============== From WebEnable Design Spec Rev 3 04/11/97================== | hrStorageIndex | | ACCESS SYNTAX | read-only INTEGER (1..2147483647) | | "A unique value for each logical storage area contained by the host." | | DISCUSSION: | | The value of this attribute is always the number of drives reported by | "GetLogicalDrives" (excepting network drives) plus one (for reporting on | "Virtual Memory"). | |============================================================================ | 1.3.6.1.2.1.25.2.3.1.1.<instance> | | | | | | | | | *hrStorageIndex | | | *hrStorageEntry | | *-hrStorageTable | *-hrStorage */
UINT GetHrStorageIndex( OUT Integer *outvalue , IN Access_Credential *access , IN InstanceName *instance )
{ ULONG index; /* As fetched from instance structure */ CACHEROW *row; /* Row entry fetched from cache */
/*
| Grab the instance information */ index = GET_INSTANCE(0);
/*
| Use it to find the right entry in the cache */ if ((row = FindTableRow(index, &hrStorage_cache)) == NULL) { return SNMP_ERRORSTATUS_GENERR; }
/*
| Return the "hrStorageIndex" value from this entry */ *outvalue = row->attrib_list[HRST_INDEX].u.unumber_value;
return SNMP_ERRORSTATUS_NOERROR ;
} /* end of GetHrStorageIndex() */
/*
* ============================================================================ * GetHrStorageType * The type of strage represented by this entry. * * Gets the value for HrStorageType. * * Arguments: * * outvalue address to return variable value * accesss Reserved for future security use * instance address of instance name as ordered native * data type(s) * * Return Codes: * * Standard PDU error codes. * * SNMP_ERRORSTATUS_NOERROR Successful get * SNMP_ERRORSTATUS_GENERR Catch-all failure code * mibtget.c v0.10 * | =============== From WebEnable Design Spec Rev 3 04/11/97================== | hrStorageType | | ACCESS SYNTAX | read-only OBJECT IDENTIFIER | | "The type of storage represented by this entry." | | -- Registration for some storage types, for use with hrStorageType | | hrStorageOther OBJECT IDENTIFIER ::= { hrStorageTypes 1 } | hrStorageRam OBJECT IDENTIFIER ::= { hrStorageTypes 2 } | -- hrStorageVirtualMemory is temporary storage of swapped | -- or paged memory | hrStorageVirtualMemory OBJECT IDENTIFIER ::= { hrStorageTypes 3 } | hrStorageFixedDisk OBJECT IDENTIFIER ::= { hrStorageTypes 4 } | hrStorageRemovableDisk OBJECT IDENTIFIER ::= { hrStorageTypes 5 } | hrStorageFloppyDisk OBJECT IDENTIFIER ::= { hrStorageTypes 6 } | hrStorageCompactDisc OBJECT IDENTIFIER ::= { hrStorageTypes 7 } | hrStorageRamDisk OBJECT IDENTIFIER ::= { hrStorageTypes 8 } | | DISCUSSION: | | The value returned for this attribute is determined by indications from | "GetDriveType" for disks. For the "Virtual Memory" entry, the OID for | "hrStorageVirtualMemory" is returned. | |============================================================================ | 1.3.6.1.2.1.25.2.3.1.2.<instance> | | | | | | | | | *hrStorageType | | | *hrStorageEntry | | *-hrStorageTable | *-hrStorage */
UINT GetHrStorageType( OUT ObjectIdentifier *outvalue , IN Access_Credential *access , IN InstanceName *instance )
{ ULONG index; /* As fetched from instance structure */ CACHEROW *row; /* Row entry fetched from cache */
/*
| Grab the instance information */ index = GET_INSTANCE(0);
/*
| Use it to find the right entry in the cache */ if ((row = FindTableRow(index, &hrStorage_cache)) == NULL) { return SNMP_ERRORSTATUS_GENERR; }
/*
| By convention with the cache-building function "Gen_Hrstorage_Cache()", | the cached value is the right-most arc we must return as the value. | | Hence whatever cache entry we retrieve, we tack the number retrieved | from the cache for this attribute onto { hrStorageTypes ... }. */ if ( (outvalue->ids = SNMP_malloc(10 * sizeof( UINT ))) == NULL) { return SNMP_ERRORSTATUS_GENERR; } outvalue->idLength = 10;
/*
| Load in the full hrStorageType OID: | | 1.3.6.1.2.1.25.2.1.n | | | | | | | *-Type indicator | | *-hrStorageTypes (OIDs specifying storage types) | *-hrStorage | */ outvalue->ids[0] = 1; outvalue->ids[1] = 3; outvalue->ids[2] = 6; outvalue->ids[3] = 1; outvalue->ids[4] = 2; outvalue->ids[5] = 1; outvalue->ids[6] = 25; outvalue->ids[7] = 2; outvalue->ids[8] = 1;
/* Cached Type indicator */ outvalue->ids[9] = row->attrib_list[HRST_TYPE].u.unumber_value;
return SNMP_ERRORSTATUS_NOERROR ;
} /* end of GetHrStorageType() */
/*
* GetHrStorageDesc * A description of the type and instance of the storage described by this * entry. * * Gets the value for HrStorageDesc. * * Arguments: * * outvalue address to return variable value * accesss Reserved for future security use * instance address of instance name as ordered native * data type(s) * * Return Codes: * * Standard PDU error codes. * * SNMP_ERRORSTATUS_NOERROR Successful get * SNMP_ERRORSTATUS_GENERR Catch-all failure code * mibtget.c v0.10 * | =============== From WebEnable Design Spec Rev 3 04/11/97================== | hrStorageDescr | | ACCESS SYNTAX | read-only DisplayString | | "A description of the type and instance of the storage described by this | entry." | | DISCUSSION: | | For the Virtual Memory entry, the string "Virtual Memory" is returned. | | For disks, a string composed of: | + the logical drive letter followed by | + the Volume Identification (for drives containing a volume) | in double quotes | + the Volume Serial Number | | For instance, the value of this variable for drive C might be | C: Label="Main Disk" Serial #=0030-34FE | | For speed, the label acquisition is done at cache-build time, and | as a consequence the removable drives are sampled only once. | =========================================================================== | 1.3.6.1.2.1.25.2.3.1.3.<instance> | | | | | | | | | *hrStorageDescr | | | *hrStorageEntry | | *-hrStorageTable | *-hrStorage */
UINT GetHrStorageDesc( OUT Simple_DisplayString *outvalue , IN Access_Credential *access , IN InstanceName *instance )
{ ULONG index; /* As fetched from instance structure */ CACHEROW *row; /* Row entry fetched from cache */
/*
| Grab the instance information */ index = GET_INSTANCE(0);
/*
| Use it to find the right entry in the cache */ if ((row = FindTableRow(index, &hrStorage_cache)) == NULL) { return SNMP_ERRORSTATUS_GENERR; }
/* Return the description that was computed at cache-build time */ outvalue->length = strlen(row->attrib_list[HRST_DESCR].u.string_value); outvalue->string = row->attrib_list[HRST_DESCR].u.string_value;
return SNMP_ERRORSTATUS_NOERROR ;
} /* end of GetHrStorageDesc() */
/*
* GetHrStorageAllocationUnits * The size, in bytes, of the data objects allocated from this pool. If * this entry is monitoring sectors, blocks, buffers, or pack * * Gets the value for HrStorageAllocationUnits. * * Arguments: * * outvalue address to return variable value * accesss Reserved for future security use * instance address of instance name as ordered native * data type(s) * * Return Codes: * * Standard PDU error codes. * * SNMP_ERRORSTATUS_NOERROR Successful get * SNMP_ERRORSTATUS_GENERR Catch-all failure code * mibtget.c v0.10 * | =============== From WebEnable Design Spec Rev 3 04/11/97================== | hrStorageAllocationUnits | | ACCESS SYNTAX | read-only INTEGER (1..2147483647) | | "The size, in bytes, of the data objects allocated from this pool. If this | entry is monitoring sectors, blocks, buffers, or packets, for example, this | number will commonly be greater than one. Otherwise this number will | typically be one." | | DISCUSSION: | | For Virtual Memory, the value returned is that provided as | "AllocationGranularity" after a call to "GetSystemInfo". | | For disks, the size of the "hrStorageAllocationUnits" value is computed as | the quantity "BytesPerSector * SectorsPerCluster" as returned by Win32 API | function "GetDiskFreeSpace". | | ============================================================================= | 1.3.6.1.2.1.25.2.3.1.4.<instance> | | | | | | | | | *hrStorageAllocationUnits | | | *hrStorageEntry | | *-hrStorageTable | *-hrStorage */
UINT GetHrStorageAllocationUnits( OUT Integer *outvalue , IN Access_Credential *access , IN InstanceName *instance )
{ ULONG index; /* As fetched from instance structure */ CACHEROW *row; /* Row entry fetched from cache */
/*
| Grab the instance information */ index = GET_INSTANCE(0);
/*
| Use it to find the right entry in the cache */ if ((row = FindTableRow(index, &hrStorage_cache)) == NULL) { return SNMP_ERRORSTATUS_GENERR; }
*outvalue = row->attrib_list[HRST_ALLOC].u.number_value; return ( SNMP_ERRORSTATUS_NOERROR );
} /* end of GetHrStorageAllocationUnits() */
/*
* GetHrStorageSize * The size of the storage represented by this entry, in units of * hrStorageAllocationUnits. * * Gets the value for HrStorageSize. * * Arguments: * * outvalue address to return variable value * accesss Reserved for future security use * instance address of instance name as ordered native * data type(s) * * Return Codes: * * Standard PDU error codes. * * SNMP_ERRORSTATUS_NOERROR Successful get * SNMP_ERRORSTATUS_GENERR Catch-all failure code * mibtget.c v0.10 * | =============== From WebEnable Design Spec Rev 3 04/11/97================== | hrStorageSize | | ACCESS SYNTAX | read-write INTEGER (0..2147483647) | | "The size of the storage represented by this entry, in units of | hrStorageAllocationUnits." | | DISCUSSION: | | For Virtual Memory, the value returned is computed as "TotalPageFile" (as | returned by "GlobalMemoryStatusEx") divided by "AllocationGranularity" from | "GetSystemInfo". | | For disks, the "hrStorageSize" value is the value of "TotalNumberOfClusters" | as returned by Win32 API function "GetDiskFreeSpace". | | <POA-4> This variable is marked as ACCESS="read-write". It is unclear to me | what effect can be expected from a SET operation on this variable. I propose | making a SET operation have no effect. | | RESOLVED >>>>>>> | <POA-4> Leaving this read-only is fine. | RESOLVED >>>>>>> | | ============================================================================= | 1.3.6.1.2.1.25.2.3.1.5.<instance> | | | | | | | | | *hrStorageSize | | | *hrStorageEntry | | *-hrStorageTable | *-hrStorage */
UINT GetHrStorageSize( OUT Integer *outvalue , IN Access_Credential *access , IN InstanceName *instance )
{ ULONG index; /* As fetched from instance structure */ CACHEROW *row; /* Row entry fetched from cache */
/*
| Grab the instance information */ index = GET_INSTANCE(0);
/*
| Use it to find the right entry in the cache */ if ((row = FindTableRow(index, &hrStorage_cache)) == NULL) { return SNMP_ERRORSTATUS_GENERR; }
*outvalue = row->attrib_list[HRST_SIZE].u.number_value; return ( SNMP_ERRORSTATUS_NOERROR ) ;
} /* end of GetHrStorageSize() */
/*
* SetHrStorageSize * The size of the storage represented by this entry, in units of * hrStorageAllocationUnits. * * Sets the HrStorageSize value. * * Arguments: * * invalue address of value to set the variable * outvalue address to return the set variable value * access Reserved for future security use * instance address of instance name as ordered native * data type(s) * * Return Codes: * * Standard PDU error codes. * * SNMP_ERRORSTATUS_NOERROR Successful get * SNMP_ERRORSTATUS_BADVALUE Set value not in range * SNMP_ERRORSTATUS_GENERR Catch-all failure code * mibtset.ntc v0.10 * | ============================================================================= | 1.3.6.1.2.1.25.2.3.1.5.<instance> | | | | | | | | | *hrStorageSize | | | *hrStorageEntry | | *-hrStorageTable | *-hrStorage */
UINT SetHrStorageSize( IN Integer *invalue , OUT Integer *outvalue , IN Access_Credential *access , IN InstanceName *instance )
{
#if 0
//debug debug debug debug debug
static int x=0; if (x==0) { /*
| If it is invoked here, the invocation | of it in mib.c must be removed. */ Gen_HrDevice_Cache(); x =1; } //debug debug debug debug debug
#endif
return SNMP_ERRORSTATUS_NOSUCHNAME ;
} /* end of SetHrStorageSize() */
/*
* GetHrStorageUsed * The amount of the storage represented by this entry that is allocated, * in units of hrStorageAllocationUnits. * * Gets the value for HrStorageUsed. * * Arguments: * * outvalue address to return variable value * accesss Reserved for future security use * instance address of instance name as ordered native * data type(s) * * Return Codes: * * Standard PDU error codes. * * SNMP_ERRORSTATUS_NOERROR Successful get * SNMP_ERRORSTATUS_GENERR Catch-all failure code * mibtget.c v0.10 * | =============== From WebEnable Design Spec Rev 3 04/11/97================== | hrStorageUsed | | ACCESS SYNTAX | read-only INTEGER (0..2147483647) | | "The amount of the storage represented by this entry that is allocated, in | units of hrStorageAllocationUnits." | | DISCUSSION: | | For Virtual Memory, the value returned is computed as the quantity | "TotalPageFile" less "AvailPageFile" (as returned by "GlobalMemoryStatusEx") | divided by "AllocationGranularity" (as returned by "GetSystemInfo". | | For disks, the "hrStorageUsed" value is computed as the quantity | "TotalNumberOfClusters - NumberOfFreeClusters" as returned by Win32 API | function "GetDiskFreeSpace". | | =========================================================================== | 1.3.6.1.2.1.25.2.3.1.6.<instance> | | | | | | | | | *hrStorageUsed | | | *hrStorageEntry | | *-hrStorageTable | *-hrStorage */
UINT GetHrStorageUsed( OUT Integer *outvalue , IN Access_Credential *access , IN InstanceName *instance )
{
ULONG index; /* As fetched from instance structure */ CACHEROW *row; /* Row entry fetched from cache */
/*
| Grab the instance information */ index = GET_INSTANCE(0);
/*
| Use it to find the right entry in the cache */ if ((row = FindTableRow(index, &hrStorage_cache)) == NULL) { return SNMP_ERRORSTATUS_GENERR; }
*outvalue = row->attrib_list[HRST_USED].u.number_value; return ( SNMP_ERRORSTATUS_NOERROR ) ;
} /* end of GetHrStorageUsed() */
/*
* GetHrStorageAllocationFailures * The number of requests for storage represented by this entry that could * not be honored due to not enough storage. It should be * * Gets the value for HrStorageAllocationFailures. * * Arguments: * * outvalue address to return variable value * accesss Reserved for future security use * instance address of instance name as ordered native * data type(s) * * Return Codes: * * Standard PDU error codes. * * SNMP_ERRORSTATUS_NOERROR Successful get * SNMP_ERRORSTATUS_GENERR Catch-all failure code * mibtget.c v0.10 * |============================================================================= |hrStorageAllocationFailures | | ACCESS SYNTAX | read-only Counter | |"The number of requests for storage represented by this entry that could not |be honored due to not enough storage. It should be noted that as this object |has a SYNTAX of Counter, that it does not have a defined initial value. |However, it is recommended that this object be initialized to zero." | |DISCUSSION: | |<POA-5> This value as very problematical for both Virtual Memory and Disk |storage. There appear to be no Win32 APIs that report allocation failures for |either virtual memory or disk storage. I presume there may be performance |monitoring counters stored in the registry, however I'm not able to find the |documentation that describes where such information might be stored. For |disks, we need to be able to map whatever counters are stored into logical |drives (as that is how this table is organized). | |RESOLVED >>>>>>> |<POA-5> You would have to scan to event log looking for the out of virtual |memory and out of disk space events and count them. |RESOLVED >>>>>>> |============================================================================= | 1.3.6.1.2.1.25.2.3.1.7.<instance> | | | | | | | | | *hrStorageAllocationFailures | | | *hrStorageEntry | | *-hrStorageTable | *-hrStorage */
UINT GetHrStorageAllocationFailures( OUT Counter *outvalue , IN Access_Credential *access , IN InstanceName *instance )
{ CHAR device[3]; /* Device Name build-buffer */ ULONG index; /* As fetched from instance structure */ CACHEROW *row; /* Row entry fetched from cache */
/*
| Grab the instance information */ index = GET_INSTANCE(0);
/*
| Use it to find the right entry in the cache */ if ((row = FindTableRow(index, &hrStorage_cache)) == NULL) { return SNMP_ERRORSTATUS_GENERR; }
/*
| Load the "device[]" array with two characters, either something like "C:" | (indicating we're interested in allocation failures for "C:") or "VM" | if we want VM storage allocation failures.... from the HRST_DESCR string. */ if (strcmp(row->attrib_list[HRST_DESCR].u.string_value, VM) == 0) { /* Storage is really "Virtual Memory" */ device[0] = 'V'; device[1] = 'M'; } else { device[0] = row->attrib_list[HRST_DESCR].u.string_value[0]; device[1] = row->attrib_list[HRST_DESCR].u.string_value[1]; } device[2] = 0; /* Null-terminate */
/* Riffle thru the Event Log looking for this device's failures */ *outvalue = ScanLog_Failures( device );
return SNMP_ERRORSTATUS_NOERROR ;
} /* end of GetHrStorageAllocationFailures() */
/*
* HrStorageEntryFindInstance * * This routine is used to verify that the specified instance is * valid. * * Arguments: * * FullOid Address for the full oid - group, variable, * and instance information * instance Address for instance specification as an oid * * Return Codes: * * SNMP_ERRORSTATUS_NOERROR Instance found and valid * SNMP_ERRORSTATUS_NOSUCHNAME Invalid instance * */
UINT HrStorageEntryFindInstance( IN ObjectIdentifier *FullOid , IN OUT ObjectIdentifier *instance ) { UINT tmp_instance ;
//
// Developer instrumentation code to find appropriate instance goes here.
// For non-tables, it is not necessary to modify this routine. However, if
// there is any context that needs to be set, it can be done here.
//
if ( FullOid->idLength <= HRSTORAGEENTRY_VAR_INDEX ) // No instance was specified
return SNMP_ERRORSTATUS_NOSUCHNAME ; else if ( FullOid->idLength != HRSTORAGEENTRY_VAR_INDEX + 1 ) // Instance length is more than 1
return SNMP_ERRORSTATUS_NOSUCHNAME ; else // The only valid instance for a non-table are instance 0. If this
// is a non-table, the following code validates the instances. If this
// is a table, developer modification is necessary below.
tmp_instance = FullOid->ids[ HRSTORAGEENTRY_VAR_INDEX ] ;
/*
| Check for age-out and possibly refresh the entire cache for the | hrStorage table and hrFSTable before we check to see if the | instance is there. */ if (hrStorageCache_hrFSTableCache_Refresh() == FALSE) { return SNMP_ERRORSTATUS_GENERR; }
/*
| For hrStorage, the instance arc(s) is a single arc, and it must | correctly select an entry in the hrStorageTable cache. | Check that here. */ if ( FindTableRow(tmp_instance, &hrStorage_cache) == NULL ) { return SNMP_ERRORSTATUS_NOSUCHNAME ; } else { // the instance is valid. Create the instance portion of the OID
// to be returned from this call.
instance->ids[ 0 ] = tmp_instance ; instance->idLength = 1 ; }
return SNMP_ERRORSTATUS_NOERROR ;
} /* end of HrStorageEntryFindInstance() */
/*
* HrStorageEntryFindNextInstance * * This routine is called to get the next instance. If no instance * was passed than return the first instance (1). * * Arguments: * * FullOid Address for the full oid - group, variable, * and instance information * instance Address for instance specification as an oid * * Return Codes: * * SNMP_ERRORSTATUS_NOERROR Instance found and valid * SNMP_ERRORSTATUS_NOSUCHNAME Invalid instance * */
UINT HrStorageEntryFindNextInstance( IN ObjectIdentifier *FullOid , IN OUT ObjectIdentifier *instance ) { // Developer supplied code to find the next instance of class goes here.
//
// The purpose of this function is to indicate to the rest of the system
// what the exact OID of the "next instance" is GIVEN THAT:
//
// a) The "FullOid" passed in will have enough arcs to specify
// both the TABLE and the ATTRIBUTE in the table
//
// b) The "instance" OID array is always big enough to have
// as many arcs as needed loaded into it by this function
// to specify (exactly) the "next instance"
//
//
// If this is a class with cardinality 1, no modification of this routine
// is necessary unless additional context needs to be set.
//
// If the FullOid is so short that it does not specify an instance,
// then the only instance of the class should be returned. If this is a
// table, the first row of the table is returned. To do these things,
// set the "instance" OID to just the right arcs such that when
// concatenated onto the FullOid, the concatenation exactly specifies
// the first instance of this attribute in the table.
//
// If an instance is specified and this is a non-table class, then
// NOSUCHNAME is returned so that correct MIB rollover processing occurs.
//
// If this is a table, then the next instance is the one following the
// current instance.
//
// If there are no more instances in the table, return NOSUCHNAME.
//
CACHEROW *row; ULONG tmp_instance;
if ( FullOid->idLength <= HRSTORAGEENTRY_VAR_INDEX ) { /*
| Too short: must return the instance arc that selects the first | entry in the table if there is one. */ tmp_instance = 0; } else { /*
| There is at least one instance arc. Even if it is the only arc | we use it as the "index" in a request for the "NEXT" one. */ tmp_instance = FullOid->ids[ HRSTORAGEENTRY_VAR_INDEX ] ; }
/*
| Check for age-out and possibly refresh the entire cache for the | hrStorage table and hrFSTable before we check to see if the | instance is there. */ if (hrStorageCache_hrFSTableCache_Refresh() == FALSE) { return SNMP_ERRORSTATUS_GENERR; }
/* Now go off and try to find the next instance in the table */ if ((row = FindNextTableRow(tmp_instance, &hrStorage_cache)) == NULL) { return SNMP_ERRORSTATUS_NOSUCHNAME ; }
instance->ids[ 0 ] = row->index ; instance->idLength = 1 ;
return SNMP_ERRORSTATUS_NOERROR ;
} /* end of HrStorageEntryFindNextInstance() */
/*
* HrStorageEntryConvertInstance * * This routine is used to convert the object id specification of an * instance into an ordered native representation. The object id format * is that object identifier that is returned from the Find Instance * or Find Next Instance routines. It is NOT the full object identifier * that contains the group and variable object ids as well. The native * representation is an argc/argv-like structure that contains the * ordered variables that define the instance. This is specified by * the MIB's INDEX clause. See RFC 1212 for information about the INDEX * clause. * * * Arguments: * * oid_spec Address of the object id instance specification * native_spec Address to return the ordered native instance * specification * * Return Codes: * * SUCCESS Conversion complete successfully * FAILURE Unable to convert object id into native format * */
UINT HrStorageEntryConvertInstance( IN ObjectIdentifier *oid_spec , IN OUT InstanceName *native_spec ) { static char *array; /* The address of this (char *) is passed back */ /* as though it were an array of length 1 of these */ /* types. */
static ULONG inst; /* The address of this ULONG is passed back */ /* (Obviously, no "free()" action is needed) */
/* We only expect the one arc in "oid_spec" */ inst = oid_spec->ids[0]; array = (char *) &inst;
native_spec->count = 1; native_spec->array = &array; return SUCCESS ;
} /* end of HrStorageEntryConvertInstance() */
/*
* HrStorageEntryFreeInstance * * This routine is used to free an ordered native representation of an * instance name. * * Arguments: * * instance Address to return the ordered native instance * specification * * Return Codes: * * */
void HrStorageEntryFreeInstance( IN OUT InstanceName *instance ) {
/* No action needed for hrStorageTable */ } /* end of HrStorageEntryFreeInstance() */
/*
| End of Generated Code */
/* hrStorageCache_hrFSTableCache_Refresh Cache Refresh-Check Routine */ /* hrStorageCache_hrFSTableCache_Refresh Cache Refresh-Check Routine */ /* hrStorageCache_hrFSTableCache_Refresh Cache Refresh-Check Routine */
BOOL hrStorageCache_hrFSTableCache_Refresh( void )
/*
| EXPLICIT INPUTS: | | None. | | IMPLICIT INPUTS: | | The "hrStorage_cache" CACHEHEAD structure and the time when | it was last refreshed in module-local cell "cache_time". | The "hrFSTable_cache" CACHEHEAD structure which depends on | the hrStorage_cache CACHEHEAD structure. | | OUTPUTS: | | On Success/Failure: | The function returns TRUE. Only if the cache-time has aged-out | is the cache actually rebuilt. | | On any Failure: | If during a rebuild there is an error, this function returns FALSE. | The state of the cache is indeterminate. | | THE BIG PICTURE: | | This function is invoked before any reference is made to any SNMP | variable in the hrStorage table. It checks to see | if the cache needs to be rebuilt based on the last time it was built. | Since the hrFSTable_cache depends on the hrStorage table, | hrFSTable_cache will be rebuilt whenever hrStorage table is rebuilt. | | The calls to this function are strategically located in the | "FindInstance" and "FindNextInstance" functions in "HRSTOENT.C" | (this module). | | OTHER THINGS TO KNOW: | */ { LARGE_INTEGER now_time; /* Current System time in 100 ns ticks */
/* Get the current time in 100 ns ticks*/ if (NtQuerySystemTime (&now_time) != STATUS_SUCCESS) return FALSE;
/* If the cache is older than the maximum allowed time (in ticks) . . . */ if ( (now_time.QuadPart - cache_time.QuadPart) > (CACHE_MAX_AGE * 10000000) ) { if (Gen_Hrstorage_Cache()) { // hrFSStorageIndex attribute of hrFSTable depends on the
// the index of the hrStorageEntry
return (Gen_HrFSTable_Cache()); } else return FALSE; }
return ( TRUE ); /* No Error (because no refresh) */ }
/* Gen_Hrstorage_Cache - Generate a initial cache for HrStorage Table */ /* Gen_Hrstorage_Cache - Generate a initial cache for HrStorage Table */ /* Gen_Hrstorage_Cache - Generate a initial cache for HrStorage Table */
BOOL Gen_Hrstorage_Cache( void )
/*
| EXPLICIT INPUTS: | | None. | | IMPLICIT INPUTS: | | The module-local head of the cache for the HrStorage table, | "hrStorage_cache". | | OUTPUTS: | | On Success: | Function returns TRUE indicating that the cache has been fully | populated with all "static" cache-able values. | | On any Failure: | Function returns FALSE (indicating "not enough storage"). | | THE BIG PICTURE: | | At subagent startup time, the cache for each table in the MIB is | populated with rows for each row in the table. This function is | invoked by the start-up code in "UserMibInit()" ("MIB.C") to | populate the cache for the HrStorage table. | | OTHER THINGS TO KNOW: | | There is one of these function for every table that has a cache. | Each is found in the respective source file. | |=============== From WebEnable Design Spec Rev 3 04/11/97================== | DISCUSSION: | | Since this table is meant for diagnosing "out-of-storage" situations and | given that the information is meant to be regarded from the point of view | of an application, we simply report every instance of what would appear | on the "Drive Bar" of the File Manager (excepting network drives) plus | one more table entry to reflect information on "Virtual Memory". | | To this end, a combination of Win32 API functions "GetLogicalDrives", | "GetVolumeInformation", "GetDriveType" and "GetDiskFreeSpace" are used to | acquire the information for the SNMP attributes in this table. | | For reporting on "Virtual Memory", functions "GlobalMemoryStatusEx" and | "GetSystemInfo" are invoked. |============================================================================ | 1.3.6.1.2.1.25.2.1.... | | | | | *-hrStorageTypes (OIDs specifying storage types) | *-hrStorage | | 1.3.6.1.2.1.25.2.2.... | | | | | *-hrMemorySize (standalone attribute) | *-hrStorage | | 1.3.6.1.2.1.25.2.3.... | | | | | *-hrStorageTable (the table) | *-hrStorage */
#define VOL_NAME_SIZE 256
#define DESCR_SIZE 384
{ CHAR temp[8]; /* Temporary buffer for first call */ LPSTR pDrvStrings; /* --> allocated storage for drive strings */ LPSTR pOriginal_DrvStrings; /* (Needed for final deallocation */ DWORD DS_request_len; /* Storage actually needed */ DWORD DS_current_len; /* Storage used on 2nd call */ ULONG table_index=0; /* hrStorageTable index counter */ CACHEROW *row; /* --> Cache structure for row-being built */
SYSTEM_INFO sys_info; /* Filled in by GetSystemInfo for VM */
LPSTR str_descr; /* String for disk label/serial description*/ CHAR volname[VOL_NAME_SIZE+1]; /* Volume Name returned here */ DWORD volnamesize=VOL_NAME_SIZE; /* Size of volname buffer */ DWORD serial_number; /* Volume Serial Number */ DWORD max_comp_len; /* File system file-name component length */ DWORD filesys_flags; /* File System flags (GetVolInformation) */ CHAR descr[DESCR_SIZE+1]; /* Full description possibly built here */
DWORD SectorsPerCluster; /* GetDiskFreeSpace() cells */ DWORD BytesPerSector; DWORD NumberOfFreeClusters; DWORD TotalNumberOfClusters;
MEMORYSTATUSEX mem_status; /* Filled in by GlobalMemoryStatusEx */ NTSTATUS ntstatus; /* Generic return status */ UINT nPrevErrorMode; /* previous state of error-mode bit flags */ DWORDLONG ullTempStorage; // ensures null terminated strings
descr[DESCR_SIZE] = 0; volname[VOL_NAME_SIZE] = 0;
/*
| Blow away any old copy of the cache */ DestroyTable(&hrStorage_cache);
/*
| We're going to call GetLogicalDriveStrings() twice, once to get the proper | buffer size, and the second time to actually get the drive strings. | | Bogus: */ if ((DS_request_len = GetLogicalDriveStrings(2, temp)) == 0) {
/* Request failed altogether, can't initialize */ return ( FALSE ); }
/*
| Grab enough storage for the drive strings plus one null byte at the end */
if ( (pOriginal_DrvStrings = pDrvStrings = malloc( (DS_request_len + 2) ) ) == NULL) {
/* Storage Request failed altogether, can't initialize */ return ( FALSE ); }
/* Go for all of the strings */ if ((DS_current_len = GetLogicalDriveStrings(DS_request_len, pDrvStrings)) == 0) {
/* Request failed altogether, can't initialize */ free( pOriginal_DrvStrings ); return ( FALSE ); }
/*
| Freshen the time on the cache | | Get the current system-time in 100ns intervals . . . */ ntstatus = NtQuerySystemTime (&cache_time); if (ntstatus != STATUS_SUCCESS) { free( pOriginal_DrvStrings ); return ( FALSE ); }
/*
|============================================================================== | As long as we've got an unprocessed drive-string. . . */ while ( strlen(pDrvStrings) > 0 ) {
UINT drivetype; /* Type of the drive from "GetDriveType()" */
/*
| Get the drive-type so we can decide whether it should participate in | this table. */ drivetype = GetDriveType(pDrvStrings);
if ( drivetype == DRIVE_UNKNOWN || drivetype == DRIVE_NO_ROOT_DIR || drivetype == DRIVE_REMOTE /* No Remotes in HrStorage */ ) {
/* Step to next string, if any */ pDrvStrings += strlen(pDrvStrings) + 1;
continue; }
/*
| OK, we want this one in the table, get a row-entry created. */ if ((row = CreateTableRow( HRST_ATTRIB_COUNT ) ) == NULL) { return ( FALSE ); // Out of memory
}
/* =========== hrStorageIndex ==========*/ row->attrib_list[HRST_INDEX].attrib_type = CA_NUMBER; row->attrib_list[HRST_INDEX].u.unumber_value = ++table_index;
/* =========== hrStorageType ==========*/ row->attrib_list[HRST_TYPE].attrib_type = CA_NUMBER;
/*
| Based on the drive-type returned, we store a single number as | the cached value of the hrStorageType attribute. When this attribute | is fetched, the cached number forms the last arc in the OBJECT IDENTIFIER | that actually specifies the type: { hrStorageTypes x }, where "x" is | what gets stored. */ switch (drivetype) {
case DRIVE_REMOVABLE: row->attrib_list[HRST_TYPE].u.unumber_value = 5; break;
case DRIVE_FIXED: row->attrib_list[HRST_TYPE].u.unumber_value = 4; break;
case DRIVE_CDROM: row->attrib_list[HRST_TYPE].u.unumber_value = 7; break;
case DRIVE_RAMDISK: row->attrib_list[HRST_TYPE].u.unumber_value = 8; break;
default: row->attrib_list[HRST_TYPE].u.unumber_value = 1; // "Other"
break; }
/* =========== hrStorageDescr ==========
| | We try and fetch the volume label here, to get a string | that may look like: | C: Label="Main Disk" Serial #=0030-34FE | | Handle all kinds of disk storage here: | | Try to get volume label and serial number. If we fail, we just give | 'em the root-path name. | | Presume that we'll fail, and just return the root-path string. */ str_descr = pDrvStrings;
/*
| Suppress any attempt by the system to make the user put a volume in a | removable drive. */ nPrevErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
if (GetVolumeInformation(pDrvStrings, /* drive name */ volname, /* Volume Name Buffer */ volnamesize, /* Size of buffer */ &serial_number, /* Vol. # Returned here */ &max_comp_len, /* Max filename length */ &filesys_flags, /* File System flags */ NULL, /* Name of Filesystem */ 0 /* Length of name */ )) { /*
| We got something back. | | If we have room given string lengths, build a description: | | <root path> Label:<volume name> Serial Number: <#> */ #define SPRINTF_FORMAT "%s Label:%s Serial Number %x"
if ((strlen(SPRINTF_FORMAT) + strlen(volname) + strlen(str_descr)) < DESCR_SIZE) { _snprintf(descr, DESCR_SIZE, SPRINTF_FORMAT, str_descr, // root-path
volname, // volume name
serial_number); // volume serial #
str_descr = descr; } }
row->attrib_list[HRST_DESCR].attrib_type = CA_STRING;
/*
| Note: | The convention is established that the first characters of | this description string is always the device-string (e.g. "C:") | or the value of local symbol "VM" ("Virtual Memory"). | | Code in "GetHrStorageAllocationFailures()" attempts to extract | the drive letter (or "Virtual Memory") from the beginning of this | string in order to determine allocation failures from the | Event Log(!). */ if ( (row->attrib_list[HRST_DESCR].u.string_value = ( LPSTR ) malloc(strlen(str_descr) + 1)) == NULL) {
DestroyTableRow(row); free( pOriginal_DrvStrings ); SetErrorMode(nPrevErrorMode); /* Turn error suppression mode off */ return ( FALSE ); /* out of memory */ } /* Copy the Value into the space */ strcpy(row->attrib_list[HRST_DESCR].u.string_value, str_descr);
row->attrib_list[HRST_ALLOC].attrib_type = CA_NUMBER; row->attrib_list[HRST_SIZE].attrib_type = CA_NUMBER; row->attrib_list[HRST_USED].attrib_type = CA_NUMBER;
/*
| Handle all kinds of disk storage info here: | | Try to get volume statistics via GetDiskFreeSpace(). */ if (GetDiskFreeSpace(pDrvStrings, // drive
&SectorsPerCluster, &BytesPerSector, &NumberOfFreeClusters, &TotalNumberOfClusters )) { /* Success */
/* =========== hrStorageAllocationUnits ==========*/ row->attrib_list[HRST_ALLOC].u.unumber_value = BytesPerSector * SectorsPerCluster;
/* =========== hrStorageSize ==========*/ row->attrib_list[HRST_SIZE].u.unumber_value = TotalNumberOfClusters;
/* =========== hrStorageUsed ==========*/ row->attrib_list[HRST_USED].u.unumber_value = TotalNumberOfClusters - NumberOfFreeClusters; } else { /* Failure */
/* =========== hrStorageAllocationUnits ==========*/ row->attrib_list[HRST_ALLOC].u.unumber_value = 0;
/* =========== hrStorageSize ==========*/ row->attrib_list[HRST_SIZE].u.unumber_value = 0;
/* =========== hrStorageUsed ==========*/ row->attrib_list[HRST_USED].u.unumber_value = 0; }
/* =========== hrStorageAllocationFailures ==========*/ row->attrib_list[HRST_FAILS].attrib_type = CA_COMPUTED;
SetErrorMode(nPrevErrorMode); /* Turn error suppression mode off */
/*
| Now insert the filled-in CACHEROW structure into the | cache-list for the hrStorageTable. */ if (AddTableRow(row->attrib_list[HRST_INDEX].u.unumber_value, /* Index */ row, /* Row */ &hrStorage_cache /* Cache */ ) == FALSE) { DestroyTableRow(row); free( pOriginal_DrvStrings ); return ( FALSE ); /* Internal Logic Error! */ }
/* Step to next string, if any */ pDrvStrings += strlen(pDrvStrings) + 1; }
free( pOriginal_DrvStrings );
/*
|============================================================================== | Now handle Virtual Memory as a special case. |============================================================================== */ if ((row = CreateTableRow( HRST_ATTRIB_COUNT ) ) == NULL) { return ( FALSE ); // Out of memory
}
/* =========== hrStorageIndex ==========*/ row->attrib_list[HRST_INDEX].attrib_type = CA_NUMBER; row->attrib_list[HRST_INDEX].u.unumber_value = ++table_index;
/* =========== hrStorageType ==========*/ row->attrib_list[HRST_TYPE].attrib_type = CA_NUMBER; row->attrib_list[HRST_TYPE].u.unumber_value = 3; /* Virtual Memory */
/* =========== hrStorageDescr ==========*/ row->attrib_list[HRST_DESCR].attrib_type = CA_STRING; if ( (row->attrib_list[HRST_DESCR].u.string_value = ( LPSTR ) malloc(strlen(VM) + 1)) == NULL) { DestroyTableRow(row); return ( FALSE ); /* out of memory */ } strcpy(row->attrib_list[HRST_DESCR].u.string_value, VM);
/* =========== hrStorageAllocationUnits ==========*/ GetSystemInfo(&sys_info); row->attrib_list[HRST_ALLOC].attrib_type = CA_NUMBER; row->attrib_list[HRST_ALLOC].u.unumber_value = sys_info.dwAllocationGranularity;
/* =========== hrStorageSize ==========*/ /* Acquire current memory statistics */ mem_status.dwLength = sizeof(MEMORYSTATUSEX); if (!GlobalMemoryStatusEx(&mem_status)) { RtlZeroMemory(&mem_status, sizeof(MEMORYSTATUSEX)); } ASSERT(sys_info.dwAllocationGranularity != 0); ullTempStorage = mem_status.ullTotalPageFile / sys_info.dwAllocationGranularity; if (ullTempStorage > (DWORDLONG)INT_MAX) { ullTempStorage = (DWORDLONG)INT_MAX; } row->attrib_list[HRST_SIZE].attrib_type = CA_NUMBER; row->attrib_list[HRST_SIZE].u.unumber_value = (INT)ullTempStorage;
/* =========== hrStorageUsed ==========*/ ullTempStorage = (mem_status.ullTotalPageFile - mem_status.ullAvailPageFile) / sys_info.dwAllocationGranularity; if (ullTempStorage > (DWORDLONG)INT_MAX) { ullTempStorage = (DWORDLONG)INT_MAX; } row->attrib_list[HRST_USED].attrib_type = CA_NUMBER; row->attrib_list[HRST_USED].u.unumber_value = (INT)ullTempStorage;
/* =========== hrStorageAllocationFailures ==========*/ row->attrib_list[HRST_FAILS].attrib_type = CA_COMPUTED;
/*
| Now insert the filled-in CACHEROW structure into the | cache-list for the hrStorageTable. */ if (AddTableRow(row->attrib_list[HRST_INDEX].u.unumber_value, /* Index */ row, /* Row */ &hrStorage_cache /* Cache */ ) == FALSE) { DestroyTableRow(row); return ( FALSE ); /* Internal Logic Error! */ } /*
|============================================================================== | End of Virtual Memory |============================================================================== */
/*
|============================================================================== | Now handle Physical Memory as a special case. |============================================================================== */ if ((row = CreateTableRow( HRST_ATTRIB_COUNT ) ) == NULL) { return ( FALSE ); // Out of memory
}
/* =========== hrStorageIndex ==========*/ row->attrib_list[HRST_INDEX].attrib_type = CA_NUMBER; row->attrib_list[HRST_INDEX].u.unumber_value = ++table_index;
/* =========== hrStorageType ==========*/ row->attrib_list[HRST_TYPE].attrib_type = CA_NUMBER; row->attrib_list[HRST_TYPE].u.unumber_value = 2; /* hrStorageRAM */
/* =========== hrStorageDescr ==========*/ row->attrib_list[HRST_DESCR].attrib_type = CA_STRING; if ( (row->attrib_list[HRST_DESCR].u.string_value = ( LPSTR ) malloc(strlen(PHYMEM) + 1)) == NULL) { DestroyTableRow(row); return ( FALSE ); /* out of memory */ } strcpy(row->attrib_list[HRST_DESCR].u.string_value, PHYMEM);
/* =========== hrStorageAllocationUnits ==========*/ // same as granularity with which virtual memory is allocated
row->attrib_list[HRST_ALLOC].attrib_type = CA_NUMBER; row->attrib_list[HRST_ALLOC].u.unumber_value = sys_info.dwAllocationGranularity;
/* =========== hrStorageSize ==========*/ ullTempStorage = mem_status.ullTotalPhys / sys_info.dwAllocationGranularity; if (ullTempStorage > (DWORDLONG)INT_MAX) { ullTempStorage = (DWORDLONG)INT_MAX; } row->attrib_list[HRST_SIZE].attrib_type = CA_NUMBER; row->attrib_list[HRST_SIZE].u.unumber_value = (INT)ullTempStorage;
/* =========== hrStorageUsed ==========*/ ullTempStorage = (mem_status.ullTotalPhys - mem_status.ullAvailPhys) / sys_info.dwAllocationGranularity; if (ullTempStorage > (DWORDLONG)INT_MAX) { ullTempStorage = (DWORDLONG)INT_MAX; } row->attrib_list[HRST_USED].attrib_type = CA_NUMBER; row->attrib_list[HRST_USED].u.unumber_value = (INT)ullTempStorage;
/* =========== hrStorageAllocationFailures ==========*/ row->attrib_list[HRST_FAILS].attrib_type = CA_COMPUTED;
/*
| Now insert the filled-in CACHEROW structure into the | cache-list for the hrStorageTable. */ if (AddTableRow(row->attrib_list[HRST_INDEX].u.unumber_value, /* Index */ row, /* Row */ &hrStorage_cache /* Cache */ ) == FALSE) { DestroyTableRow(row); return ( FALSE ); /* Internal Logic Error! */ } /*
|============================================================================== | End of Physical Memory |============================================================================== */
#if defined(CACHE_DUMP)
PrintCache(&hrStorage_cache); #endif
/*
| Initialization of this table's cache succeeded */ return (TRUE); }
/* ScanLog_Failures - Scan Event Log for Storage Allocation Failures */ /* ScanLog_Failures - Scan Event Log for Storage Allocation Failures */ /* ScanLog_Failures - Scan Event Log for Storage Allocation Failures */
static UINT ScanLog_Failures( CHAR *device )
/*
| EXPLICIT INPUTS: | | "device" is either the string "VM" (for "Virtual Memory") or | the logical device for which we're looking for failures (e.g. "C:"). | | IMPLICIT INPUTS: | | The System Event log file. | | OUTPUTS: | | On Success/Failure: | Function returns the number of storage allocation failures | found for the specified device. | | THE BIG PICTURE: | | This is a "helper" function for routine "GetHrStorageAllocationFailures" | within this module. | | OTHER THINGS TO KNOW: | | We scan backwards (in time) thru the Event Log until we hit the | "Event Logging Started" event record (because, presumably, we don't | care about failures that happened before the system last came up). */
/*
| These symbols select the "Event Log Started" informational message. */ #define EVENTLOG_START_ID 0x80001775
#define EVENTLOG_START_TYPE 4
#define EVENTLOG_START_SRC "EventLog"
{ #define EVL_BUFFER_SIZE 2048
EVENTLOGRECORD *pevlr; BYTE bBuffer[EVL_BUFFER_SIZE]; DWORD dwRead, dwNeeded, cRecords; HANDLE h; BOOL keep_scanning = TRUE; UINT alloc_failures = 0;
/*
| Open the System event log */ h = OpenEventLog(NULL, /* local computer */ "System" /* source name */ );
if (h == NULL) { return ( alloc_failures ); }
pevlr = (EVENTLOGRECORD *) &bBuffer;
/*
| Read records sequentially "Backward in Time" until there | are no more, or we hit the "Event Logging Started" event. | | Read a "Slug 'o Records": */ while (ReadEventLog(h, // event log handle
EVENTLOG_BACKWARDS_READ | // reads backward
EVENTLOG_SEQUENTIAL_READ, // sequential read
0, // ignored for sequential reads
pevlr, // address of buffer
EVL_BUFFER_SIZE, // size of buffer
&dwRead, // count of bytes read
&dwNeeded) // bytes in next record
&& keep_scanning == TRUE) {
/* Wind down thru this "slug" . . . */ while (dwRead > 0) {
/*
| Check for "Event Logging Started" | | (The source name is just past the end of the formal structure). */ if ( pevlr->EventID == EVENTLOG_START_ID && pevlr->EventType == EVENTLOG_START_TYPE && strcmp( ((LPSTR) ((LPBYTE) pevlr + sizeof(EVENTLOGRECORD))), EVENTLOG_START_SRC) == 0 ) { keep_scanning = FALSE; break; }
//============================================================================
// INSERT RECORD CHECKING LOGIC OF THIS SORT HERE:
//
// IF ( <eventrecordID> == pevlr->EventID
// && <eventrecordtype> == pevlr->EventType
// && <eventrecordsourcestring> == (is the same as..)
// ( (LPSTR) ((LPBYTE) pevlr + sizeof(EVENTLOGRECORD)) )
// ) {
// // It's an allocation-failure record, if it is for device
// // "device", then count it.
// IF (strcmp(device, <eventrecordinstance-data>) {
// alloc_failures += 1;
// }
// }
//============================================================================
dwRead -= pevlr->Length; pevlr = (EVENTLOGRECORD *) ((LPBYTE) pevlr + pevlr->Length); }
pevlr = (EVENTLOGRECORD *) &bBuffer; }
CloseEventLog(h);
/* Give 'em the count */ return (alloc_failures); }
#if defined(CACHE_DUMP)
/* debug_print_hrstorage - Prints a Row from Hrstorage sub-table */ /* debug_print_hrstorage - Prints a Row from Hrstorage sub-table */ /* debug_print_hrstorage - Prints a Row from Hrstorage sub-table */
static void debug_print_hrstorage( CACHEROW *row /* Row in hrstorage table */ ) /*
| EXPLICIT INPUTS: | | "row" - points to the row to be dumped, if NULL, the function | merely prints a suitable title. | | IMPLICIT INPUTS: | | - Symbols used to reference the attributes in the row entry. | - File handle defined by OFILE, presumed to be open. | | OUTPUTS: | | On Success: | Function prints a dump of the row in ASCII for debugging purposes | on file handle OFILE. | | THE BIG PICTURE: | | Debugging only. | | OTHER THINGS TO KNOW: */ {
if (row == NULL) { fprintf(OFILE, "=====================\n"); fprintf(OFILE, "hrStorage Table Cache\n"); fprintf(OFILE, "=====================\n"); return; }
fprintf(OFILE, "hrStorageIndex . . . . . %d\n", row->attrib_list[HRST_INDEX].u.unumber_value);
fprintf(OFILE, "hrStorageType. . . . . . %d ", row->attrib_list[HRST_TYPE].u.unumber_value);
switch (row->attrib_list[HRST_TYPE].u.unumber_value) { case 1: fprintf(OFILE, "(Other)\n"); break; case 2: fprintf(OFILE, "(RAM)\n"); break; case 3: fprintf(OFILE, "(Virtual Memory)\n"); break; case 4: fprintf(OFILE, "(Fixed Disk)\n"); break; case 5: fprintf(OFILE, "(Removable Disk)\n"); break; case 6: fprintf(OFILE, "(Floppy Disk)\n"); break; case 7: fprintf(OFILE, "(Compact Disk)\n"); break; case 8: fprintf(OFILE, "(RAM Disk)\n"); break; default: fprintf(OFILE, "(Unknown)\n"); }
fprintf(OFILE, "hrStorageDescr . . . . . \"%s\"\n", row->attrib_list[HRST_DESCR].u.string_value);
fprintf(OFILE, "hrStorageAllocationUnits %d\n", row->attrib_list[HRST_ALLOC].u.number_value);
fprintf(OFILE, "hrStorageSize. . . . . . %d\n", row->attrib_list[HRST_SIZE].u.number_value);
fprintf(OFILE, "hrStorageUsed. . . . . . %d\n", row->attrib_list[HRST_USED].u.number_value);
fprintf(OFILE, "hrStorageAllocationFails (Computed)\n"); } #endif
|