You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1888 lines
60 KiB
1888 lines
60 KiB
/*
|
|
* 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
|