/*
 *  HrDeviceEntry.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 HrDeviceEntry.  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.
 *
 *  Author:
 *
 *	D. D. Burns @ Webenable Inc
 *
 *  Revision History:
 *
 *    V1.00 - 04/27/97  D. D. Burns     Genned: Thu Nov 07 16:41:55 1996
 *
 *
 */


#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 "HRDEVENT.H"     /* HrDevice Table  related definitions */
#include <stdio.h>        /* for sprintf                         */


/*
|==============================================================================
| Function prototypes for this module.
|
*/
/* Gen_SingleDevices - Generate Single Device row entries in HrDevice */
BOOL
Gen_SingleDevices( void );


#if defined(CACHE_DUMP)

/* debug_print_hrdevice - Prints a Row from HrDevice */
static void
debug_print_hrdevice(
                     CACHEROW     *row  /* Row in hrDiskStorage table */
                     );
#endif


/*
|==============================================================================
| Create the list-head for the HrDevice table cache.
|
| This list-head is globally accessible so the logic that loads the "sub" 
| tables can scan this cache for matches (among other reasons).
|
| (This macro is defined in "HMCACHE.H").
*/
CACHEHEAD_INSTANCE(hrDevice_cache, debug_print_hrdevice);


/*
|==============================================================================
| Initial Load Device
|
| This number is the index into hrDevice table for the entry that corresponds
| to the disk from which the system was initially loaded.
|
| This static location serves as "cache" for the value of 
| "HrSystemInitialLoadDevice" (serviced by code in "HRSYSTEM.C").
|
| It is initialized by function "Gen_Fixed_disks()" in module "HRDISKST.C"
| which is called by way of "Gen_HrDiskStorage_Cache()" invoked from this
| module.  It is during the scan of the fixed disks that we discover from which
| one the system booted.
*/
ULONG   InitLoadDev_index=0;


/*
 *  GetHrDeviceIndex
 *    A unique value for each device contained by the host.  The value for 
 *    each device must remain constant at least from one re-initi
 *    
 *    Gets the value for HrDeviceIndex.
 *
 *  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==================
 | hrDeviceIndex
 | 
 |  ACCESS         SYNTAX
 |  read-only      INTEGER (1..2147483647)
 | 
 | "A unique value for each device contained by the host.  The value for each
 | device must remain constant at least from one re-initialization of the agent
 | to the next re-initialization."
 | 
 | DISCUSSION:
 | 
 | As mentioned in the discussion for this table, all entries for this table
 | are derived from a local cache built at start-up time.  As a consequence the
 | maximum value of this attribute is fixed at SNMP service start-time.
 | 
 |============================================================================
 | 1.3.6.1.2.1.25.3.2.1.1.<instance>
 |                | | | |
 |                | | | *hrDeviceIndex
 |                | | *hrDeviceEntry
 |                | *hrDeviceTable
 |                *-hrDevice
 */

UINT
GetHrDeviceIndex( 
        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, &hrDevice_cache)) == NULL) {
    return SNMP_ERRORSTATUS_GENERR;
    }

/*
| Return the "hrDeviceIndex" value from this entry
*/
*outvalue = row->attrib_list[HRDV_INDEX].u.unumber_value;


return SNMP_ERRORSTATUS_NOERROR ;

} /* end of GetHrDeviceIndex() */


/*
 *  GetHrDeviceType
 *    An indication of the type of device.
 *    
 *    Gets the value for HrDeviceType.
 *
 *  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==================
 | hrDeviceType
 | 
 |  ACCESS         SYNTAX
 |  read-only      OBJECT IDENTIFIER
 | 
 |   "An indication of the type of device.
 | 
 |   If this value is `hrDeviceProcessor { hrDeviceTypes3 }'
 |   then an entry exists in the hrProcessorTable
 |   which corresponds to this device.
 | 
 |   If this value is `hrDeviceNetwork { hrDeviceTypes 4}',
 |   then an entry exists in the hrNetworkTable
 |   which corresponds to this device.
 | 
 |   If this value is `hrDevicePrinter { hrDeviceTypes 5}',
 |   then an entry exists in the hrPrinterTable
 |   which corresponds to this device.
 | 
 |   If this value is `hrDeviceDiskStorage {hrDeviceTypes 6 }',
 |   then an entry exists in the
 |   hrDiskStorageTable which corresponds to this
 |   device."
 | 
 | DISCUSSION:
 | 
 | The list of registered device types (i.e. values that can be used in the
 | hrDeviceType attribute) are:
 | 
 |    hrDeviceOther             OBJECT IDENTIFIER ::= { hrDeviceTypes 1 }
 |    hrDeviceUnknown           OBJECT IDENTIFIER ::= { hrDeviceTypes 2 }
 |    hrDeviceProcessor         OBJECT IDENTIFIER ::= { hrDeviceTypes 3 }
 |    hrDeviceNetwork           OBJECT IDENTIFIER ::= { hrDeviceTypes 4 }
 |    hrDevicePrinter           OBJECT IDENTIFIER ::= { hrDeviceTypes 5 }
 |    hrDeviceDiskStorage       OBJECT IDENTIFIER ::= { hrDeviceTypes 6 }
 |    hrDeviceVideo             OBJECT IDENTIFIER ::= { hrDeviceTypes 10 }
 |    hrDeviceAudio             OBJECT IDENTIFIER ::= { hrDeviceTypes 11 }
 |    hrDeviceCoprocessor       OBJECT IDENTIFIER ::= { hrDeviceTypes 12 }
 |    hrDeviceKeyboard          OBJECT IDENTIFIER ::= { hrDeviceTypes 13 }
 |    hrDeviceModem             OBJECT IDENTIFIER ::= { hrDeviceTypes 14 }
 |    hrDeviceParallelPort      OBJECT IDENTIFIER ::= { hrDeviceTypes 15 }
 |    hrDevicePointing          OBJECT IDENTIFIER ::= { hrDeviceTypes 16 }
 |    hrDeviceSerialPort        OBJECT IDENTIFIER ::= { hrDeviceTypes 17 }
 |    hrDeviceTape              OBJECT IDENTIFIER ::= { hrDeviceTypes 18 }
 |    hrDeviceClock             OBJECT IDENTIFIER ::= { hrDeviceTypes 19 }
 |    hrDeviceVolatileMemory    OBJECT IDENTIFIER ::= { hrDeviceTypes 20 }
 |    hrDeviceNonVolatileMemory OBJECT IDENTIFIER ::= { hrDeviceTypes 21 }
 | 
 | (See discussion above for hrDeviceTable).
 |============================================================================
 | 1.3.6.1.2.1.25.3.1.n
 |                | | |
 |                | | * Identifying arc for type
 |                | *-hrDeviceTypes (OIDs specifying device types)
 |                *-hrDevice
 |
 | 1.3.6.1.2.1.25.3.2.1.2.<instance>
 |                | | | |
 |                | | | *-hrDeviceType
 |                | | *-hrDeviceEntry
 |                | *-hrDeviceTable
 |                *-hrDevice
 */

UINT
GetHrDeviceType( 
        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, &hrDevice_cache)) == NULL) {
    return SNMP_ERRORSTATUS_GENERR;
    }

/*
| By convention with the cache-building function "Gen_HrDevice_Cache()",
| and it's minions 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 { hrDeviceType ... }.
*/
if ( (outvalue->ids = SNMP_malloc(10 * sizeof( UINT ))) == NULL) {
    return SNMP_ERRORSTATUS_GENERR;
    }
outvalue->idLength = 10;


/*
| Load in the full hrDeviceType OID:
|
| 1.3.6.1.2.1.25.3.1.n
|                | | |
|                | | * Identifying arc for type
|                | *-hrDeviceTypes (OIDs specifying device types)
|                *-hrDevice
*/
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] = 3;
outvalue->ids[8] = 1;

/* Cached Device Type indicator */
outvalue->ids[9] = row->attrib_list[HRDV_TYPE].u.unumber_value;

return SNMP_ERRORSTATUS_NOERROR ;

} /* end of GetHrDeviceType() */


/*
 *  GetHrDeviceDesc
 *    A textual description of this device, including the device's 
 *    manufacturer and revision, and optionally, its serial number.
 *    
 *    Gets the value for HrDeviceDesc.
 *
 *  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==================
 | hrDeviceDescr
 | 
 |  ACCESS         SYNTAX
 |  read-only      DisplayString (SIZE (0..64))
 | 
 | "A textual description of this device, including the device's manufacturer and
 | revision, and optionally, its serial number."
 | 
 | DISCUSSION:
 | 
 | (See discussion above for hrDeviceTable, the information source for this
 |  attribute depends on the device type).
 | 
 |============================================================================
 | 1.3.6.1.2.1.25.3.2.1.3.<instance>
 |                | | | |
 |                | | | *-hrDeviceDescr
 |                | | *-hrDeviceEntry
 |                | *-hrDeviceTable
 |                *-hrDevice
 */

UINT
GetHrDeviceDesc( 
        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, &hrDevice_cache)) == NULL) {
    return SNMP_ERRORSTATUS_GENERR;
    }

outvalue->string = row->attrib_list[HRDV_DESCR].u.string_value;

/* "Truncate" here to meet RFC as needed*/
if ((outvalue->length = strlen(outvalue->string)) > 64) {
    outvalue->length = 64;
    }


return SNMP_ERRORSTATUS_NOERROR ;

} /* end of GetHrDeviceDesc() */


/*
 *  GetHrDeviceID
 *    The product ID for this device.
 *    
 *    Gets the value for HrDeviceID.
 *
 *  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==================
 | hrDeviceID
 | 
 |  ACCESS         SYNTAX
 |  read-only      ProductID
 | 
 | "The product ID for this device."
 | 
 |    ProductID ::= OBJECT IDENTIFIER
 | 
 |    "unknownProduct will be used for any unknown ProductID:
 |     unknownProduct OBJECT IDENTIFIER ::= { 0 0 }
 | 
 | DISCUSSION:
 | 
 | <POA-10> I anticipate always using "unknownProduct" as the value for this
 | attribute, as I can envision no systematic means of acquiring a registered
 | OID for all devices to be used as the value for this attribute.
 | 
 | RESOLVED >>>>>>>>
 | <POA-10> Returning an unknown Product ID is acceptable.
 | RESOLVED >>>>>>>>
 |============================================================================
 | 1.3.6.1.2.1.25.3.2.1.4.<instance>
 |                | | | |
 |                | | | *-hrDeviceID
 |                | | *-hrDeviceEntry
 |                | *-hrDeviceTable
 |                *-hrDevice
 */

UINT
GetHrDeviceID( 
        OUT ProductID *outvalue ,
        IN Access_Credential *access ,
        IN InstanceName *instance )

{

/*
| The deal on this attribute is that we'll never have a valid OID value
| for this attribute.  Consequently, we always return the standard
| "unknown" OID value ("0.0") regardless of the instance value (which
| by now in the calling sequence of things has been validated anyway).
*/

if ( (outvalue->ids = SNMP_malloc(2 * sizeof( UINT ))) == NULL) {
    return SNMP_ERRORSTATUS_GENERR;
    }
outvalue->idLength = 2;

/*
| Load in the OID value for "unknown" for ProductID: "0.0" 
*/
outvalue->ids[0] = 0;
outvalue->ids[1] = 0;

return SNMP_ERRORSTATUS_NOERROR ;

} /* end of GetHrDeviceID() */


/*
 *  GetHrDeviceStatus
 *    The current operational state of the device described by this row of the 
 *    table.  A value unknown (1) indicates that the current 
 *    
 *    Gets the value for HrDeviceStatus.
 *
 *  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==================
 | hrDeviceStatus
 | 
 |  ACCESS         SYNTAX
 |  read-only      INTEGER {unknown(1),running(2),warning(3),testing(4),
 |                          down(5)}
 | 
 | "The current operational state of the device described by this row of the
 | table.  A value unknown(1) indicates that the current state of the device is
 | unknown.  running(2) indicates that the device is up and running and that no
 | unusual error conditions are known.  The warning(3) state indicates that agent
 | has been informed of an unusual error condition by the operational software
 | (e.g., a disk device driver) but that the device is still 'operational'.  An
 | example would be high number of soft errors on a disk.  A value of testing(4),
 | indicates that the device is not available for use because it is in the
 | testing state.  The state of down(5) is used only when the agent has been
 | informed that the device is not available for any use."
 | 
 | DISCUSSION:
 | 
 | For those devices for which a driver can be queried for the device status,
 | this is done.  For all other circumstances, "unknown(1)" is returned.
 | 
 | (See discussion above for hrDeviceTable, the information source for this
 |  attribute depends on the device type).
 | 
 |============================================================================
 | 1.3.6.1.2.1.25.3.2.1.5.<instance>
 |                | | | |
 |                | | | *-hrDeviceStatus
 |                | | *-hrDeviceEntry
 |                | *-hrDeviceTable
 |                *-hrDevice
 */

UINT
GetHrDeviceStatus( 
        OUT INThrDeviceStatus *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, &hrDevice_cache)) == NULL) {
    return SNMP_ERRORSTATUS_GENERR;
    }

/*
| By convention with the cache-building function "Gen_HrDevice_Cache()",
| and its minions the cached value in the row just fetched above for
| the "hrDeviceType" attribute (indexed by our symbol "HRDV_TYPE") is the
| last arc in the OID that specifies the type of device for which we need
| to return status/errors.
|
| The scheme for returning status depends on the value of the type to
| dispatch to the correct code to handle that kind of device.
|
| Also, code that initializes the hrDevice cache for any given device
| has the option of storing in the "hidden context" attribute (accessed via 
| our symbol "HIDDEN_CTX") information needed to access that device.
| 
| For instance, the code that enters Printer devices into hrDevice (in
| function "Gen_HrPrinter_Cache()" in "HRPRINTE.C") stores a string in
| "HIDDEN_CTX" that is the printer name thereby allowing logic below to 
| re-open that printer to obtain status/errors.
|
*/
switch ( row->attrib_list[HRDV_TYPE].u.unumber_value ) {

    case HRDV_TYPE_LASTARC_PRINTER:
        /*  (In "HRPRINTE.C") */
        if (!COMPUTE_hrPrinter_status(row, (UINT *) outvalue)) {
            return SNMP_ERRORSTATUS_GENERR;
            }
        break;


    case HRDV_TYPE_LASTARC_PROCESSOR:
        /* Any processor in the table is running */
        *outvalue = 2;
        break;


    case HRDV_TYPE_LASTARC_DISKSTORAGE:
        /* Stored by Gen_hrDiskStorage_cache() */
        *outvalue =  row->attrib_list[HRDV_STATUS].u.unumber_value;
        break;


    case HRDV_TYPE_LASTARC_KEYBOARD:
    case HRDV_TYPE_LASTARC_POINTING:
        /* Any Keyboard or Mouse in the table is reasably presumed "running" */
        *outvalue = 2;  // "running"
        break;


    case HRDV_TYPE_LASTARC_PARALLELPORT:
    case HRDV_TYPE_LASTARC_SERIALPORT:
        *outvalue = 1;  // "Unknown"
        break;


    case HRDV_TYPE_LASTARC_OTHER:
    case HRDV_TYPE_LASTARC_UNKNOWN:
    case HRDV_TYPE_LASTARC_NETWORK:
    case HRDV_TYPE_LASTARC_VIDEO:
    case HRDV_TYPE_LASTARC_AUDIO:
    case HRDV_TYPE_LASTARC_COPROCESSOR:
    case HRDV_TYPE_LASTARC_MODEM:
    case HRDV_TYPE_LASTARC_TAPE:
    case HRDV_TYPE_LASTARC_CLOCK:
    case HRDV_TYPE_LASTARC_VOLMEMORY:
    case HRDV_TYPE_LASTARC_NONVOLMEMORY:

        *outvalue = 1;  // "Unknown"
        break;


    default:
        return SNMP_ERRORSTATUS_GENERR;

    }

return SNMP_ERRORSTATUS_NOERROR ;

} /* end of GetHrDeviceStatus() */


/*
 *  GetHrDeviceErrors
 *    The number of errors detected on this device.  It should be noted that as 
 *    this object has a SYNTAX of Counter, that it does not 
 *    
 *    Gets the value for HrDeviceErrors.
 *
 *  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==================
 | hrDeviceErrors
 |  ACCESS         SYNTAX
 |  read-only      Counter
 | 
 | "The number of errors detected on this device.  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:
 | 
 | For those devices for which a driver can be queried for the device errors,
 | this is done.  For all other circumstances, "0" is returned.
 | 
 | (See discussion above for hrDeviceTable, the information source for this
 |  attribute depends on the device type).
 | 
 |============================================================================
 | 1.3.6.1.2.1.25.3.2.1.6.<instance>
 |                | | | |
 |                | | | *-hrDeviceErrors
 |                | | *-hrDeviceEntry
 |                | *-hrDeviceTable
 |                *-hrDevice
 */

UINT
GetHrDeviceErrors( 
        OUT Counter *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, &hrDevice_cache)) == NULL) {
    return SNMP_ERRORSTATUS_GENERR;
    }

/*
| By convention with the cache-building function "Gen_HrDevice_Cache()",
| and its minions the cached value in the row just fetched above for
| the "hrDeviceType" attribute (indexed by our symbol "HRDV_TYPE") is the
| last arc in the OID that specifies the type of device for which we need
| to return status/errors.
|
| The scheme for returning status depends on the value of the type to
| dispatch to the correct code to handle that kind of device.
|
| Also, code that initializes the hrDevice cache for any given device
| has the option of storing in the "hidden context" attribute (accessed via 
| our symbol "HIDDEN_CTX") information needed to access that device.
| 
| For instance, the code that enters Printer devices into hrDevice (in
| function "Gen_HrPrinter_Cache()" in "HRPRINTE.C") stores a string in
| "HIDDEN_CTX" that is the printer name thereby allowing logic below to 
| re-open that printer to obtain status/errors.
|
*/
switch ( row->attrib_list[HRDV_TYPE].u.unumber_value ) {

    case HRDV_TYPE_LASTARC_PRINTER:

        /*  (In "HRPRINTE.C") */
        if (!COMPUTE_hrPrinter_errors(row, outvalue)) {
            return SNMP_ERRORSTATUS_GENERR;
            }
        break;


    case HRDV_TYPE_LASTARC_PROCESSOR:

        /* If 'errors' ain't 0, odds are low you're gonna find out via SNMP */
        *outvalue = 0;
        break;


    case HRDV_TYPE_LASTARC_POINTING:
    case HRDV_TYPE_LASTARC_KEYBOARD:
    case HRDV_TYPE_LASTARC_PARALLELPORT:
    case HRDV_TYPE_LASTARC_SERIALPORT:
        /* 'errors' presumed 0 */
        *outvalue = 0;
        break;


    case HRDV_TYPE_LASTARC_OTHER:
    case HRDV_TYPE_LASTARC_UNKNOWN:
    case HRDV_TYPE_LASTARC_NETWORK:
    case HRDV_TYPE_LASTARC_DISKSTORAGE:
    case HRDV_TYPE_LASTARC_VIDEO:
    case HRDV_TYPE_LASTARC_AUDIO:
    case HRDV_TYPE_LASTARC_COPROCESSOR:
    case HRDV_TYPE_LASTARC_MODEM:
    case HRDV_TYPE_LASTARC_TAPE:
    case HRDV_TYPE_LASTARC_CLOCK:
    case HRDV_TYPE_LASTARC_VOLMEMORY:
    case HRDV_TYPE_LASTARC_NONVOLMEMORY:
        *outvalue = 0;
        break;

    default:
        return SNMP_ERRORSTATUS_GENERR;

    }

return SNMP_ERRORSTATUS_NOERROR ;
} /* end of GetHrDeviceErrors() */


/*
 *  HrDeviceEntryFindInstance
 *
 *     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
HrDeviceEntryFindInstance( 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 <= HRDEVICEENTRY_VAR_INDEX )
	// No instance was specified
	return SNMP_ERRORSTATUS_NOSUCHNAME ;
    else  if ( FullOid->idLength != HRDEVICEENTRY_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[ HRDEVICEENTRY_VAR_INDEX ] ;

        /*
        | For hrDeviceTable, the instance arc(s) is a single arc, and it must
        | correctly select an entry in the hrDeviceTable cache.
        | Check that here.
        */
	if ( FindTableRow(tmp_instance, &hrDevice_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 HrDeviceEntryFindInstance() */



/*
 *  HrDeviceEntryFindNextInstance
 *
 *     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
HrDeviceEntryFindNextInstance( IN ObjectIdentifier *FullOid ,
                           IN OUT ObjectIdentifier *instance )
{
    //
    //  Developer supplied code to find the next instance of class goes here.
    //  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 does not specify an instance, then the only instance
    //  of the class is returned.  If this is a table, the first row of the
    //  table is returned.
    //
    //  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 <= HRDEVICEENTRY_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[ HRDEVICEENTRY_VAR_INDEX ] ;
        }

    /* Now go off and try to find the next instance in the table */
    if ((row = FindNextTableRow(tmp_instance, &hrDevice_cache)) == NULL) {
        return SNMP_ERRORSTATUS_NOSUCHNAME ;
        }

    instance->ids[ 0 ] = row->index ;
    instance->idLength = 1 ;

    return SNMP_ERRORSTATUS_NOERROR ;

} /* end of HrDeviceEntryFindNextInstance() */



/*
 *  HrDeviceEntryConvertInstance
 *
 *     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
HrDeviceEntryConvertInstance( 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 HrDeviceEntryConvertInstance() */




/*
 *  HrDeviceEntryFreeInstance
 *
 *     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
HrDeviceEntryFreeInstance( IN OUT InstanceName *instance )
{

  /* No action needed for hrDevice Table */
} /* end of HrDeviceEntryFreeInstance() */


/*
| End of Generated Code
*/

/* Gen_HrDevice_Cache - Generate a initial cache for HrDevice Table */
/* Gen_HrDevice_Cache - Generate a initial cache for HrDevice Table */
/* Gen_HrDevice_Cache - Generate a initial cache for HrDevice Table */

BOOL
Gen_HrDevice_Cache(
                    void
                    )

/*
|  EXPLICIT INPUTS:
|
|       None.
|
|  IMPLICIT INPUTS:
|
|       The module-local head of the cache for the HrDevice table,
|       "HrDevice_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" or other
|       internal logic error).
|
|  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 HrDevice 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==================
| A Row in the hrDeviceTable
| 
| "A (conceptual) entry for one device contained by the host.  As an example, an
| instance of the hrDeviceType object might be named hrDeviceType.3"
| 
|    HrDeviceEntry ::= SEQUENCE {
|            hrDeviceIndex           INTEGER,
|            hrDeviceType            OBJECT IDENTIFIER,
|            hrDeviceDescr           DisplayString,
|            hrDeviceID              ProductID,
|            hrDeviceStatus          INTEGER,
|            hrDeviceErrors          Counter
|        }
| 
| DISCUSSION:
| 
| This is the largest and most complicated table to populate.  The strategy for
| populating entries in this table is to execute a slug of code for each device
| type (in the list below) in an attempt to find all instances of that device
| type.  For some devices, the code uses standard Win32 API functions, for
| others it is clear that special-purpose code is needed to extract the relevant
| information from the "behind the scenes" (direct NT kernel inquiries).
| 
| This table is fully populated with respect to the other tables in the hrDevice
| group. The other tables are sparse tables augmenting only selected entries in
| hrDeviceTable.
| 
| The list of registered device types (i.e. values that can be used in the
| hrDeviceType attribute) are:
| 
|    hrDeviceOther             OBJECT IDENTIFIER ::= { hrDeviceTypes 1 }
|    hrDeviceUnknown           OBJECT IDENTIFIER ::= { hrDeviceTypes 2 }
|    hrDeviceProcessor         OBJECT IDENTIFIER ::= { hrDeviceTypes 3 }
|    hrDeviceNetwork           OBJECT IDENTIFIER ::= { hrDeviceTypes 4 }
|    hrDevicePrinter           OBJECT IDENTIFIER ::= { hrDeviceTypes 5 }
|    hrDeviceDiskStorage       OBJECT IDENTIFIER ::= { hrDeviceTypes 6 }
|    hrDeviceVideo             OBJECT IDENTIFIER ::= { hrDeviceTypes 10 }
|    hrDeviceAudio             OBJECT IDENTIFIER ::= { hrDeviceTypes 11 }
|    hrDeviceCoprocessor       OBJECT IDENTIFIER ::= { hrDeviceTypes 12 }
|    hrDeviceKeyboard          OBJECT IDENTIFIER ::= { hrDeviceTypes 13 }
|    hrDeviceModem             OBJECT IDENTIFIER ::= { hrDeviceTypes 14 }
|    hrDeviceParallelPort      OBJECT IDENTIFIER ::= { hrDeviceTypes 15 }
|    hrDevicePointing          OBJECT IDENTIFIER ::= { hrDeviceTypes 16 }
|    hrDeviceSerialPort        OBJECT IDENTIFIER ::= { hrDeviceTypes 17 }
|    hrDeviceTape              OBJECT IDENTIFIER ::= { hrDeviceTypes 18 }
|    hrDeviceClock             OBJECT IDENTIFIER ::= { hrDeviceTypes 19 }
|    hrDeviceVolatileMemory    OBJECT IDENTIFIER ::= { hrDeviceTypes 20 }
|    hrDeviceNonVolatileMemory OBJECT IDENTIFIER ::= { hrDeviceTypes 21 }
| 
| All of the foregoing types can be divided into two groups based on the
| approach needed to acquire information about them.  Information for the first
| group can be queried using Win32 API functions while the second group 
| requires special inquiry-code.
| 
| (1) Win32 Device-Types  Win32 Function Used
| ----------------------  -------------------
|    hrDeviceOther
|         Partitions      DeviceIoControl (IOCTL_GET_PARTITION_INFO)
| 
|    hrDeviceProcessor    GetSystemInfo
|    hrDevicePrinter      EnumPrinterDrivers
|    hrDeviceDiskStorage  QueryDosDevice/CreateFile (using physical drive access)
|    hrDeviceKeyboard     GetKeyboardType
|    hrDevicePointing     (Win32 function provides pointer-device button-count)
|
| 
| (2) Special-Inquiry Device-Types
| ---------------------------------
|    hrDeviceNetwork      Access is provided via special "mib2util" DLL
| 
|    hrDeviceParallelPort NtQuerySystemInformation(SYSTEM_DEVICE_INFORMATION)
|    hrDeviceSerialPort
| 
|    hrDeviceVideo        ??? NtQuerySystemInformation(SYSTEM_GDI_DRIVER_INFORMATION)
|    hrDeviceAudio        ???
|    hrDeviceTape         ???
| 
| 
| The following "devices" do not readily fall into either of the above groups
| and no attempt is made to recognize them:
| 
|    hrDeviceModem             OBJECT IDENTIFIER ::= { hrDeviceTypes 14 }
|    hrDeviceVolatileMemory    OBJECT IDENTIFIER ::= { hrDeviceTypes 20 }
|    hrDeviceNonVolatileMemory OBJECT IDENTIFIER ::= { hrDeviceTypes 21 }
|    hrDeviceCoprocessor       OBJECT IDENTIFIER ::= { hrDeviceTypes 12 }
|    hrDeviceClock             OBJECT IDENTIFIER ::= { hrDeviceTypes 19 }
| 
| 
| Other Implementation Details
| ----------------------------
| The bulk of the information for this table (and the associated sparse tables
| hrProcessorTable, hrNetworkTable, hrPrinterTable, hrDiskStorageTable,
| hrPartitionTable and hrFSTable) is acquired and stored in a local cache at the
| time the SNMP agent enrolls the DLL for the Host Resources MIB.  This strategy
| is designed to reduce the hit on system resources when requests are processed.
| The only information that is acquired dynamically (on a per SNMP request) is
| information for variables likely to be dynamic: Status and Error status.
| 
| One consequence of this strategy is that user-implemented changes to the
| system configuration (including changing printer drivers, or disk partition
| layout) will not be reported until the SNMP service is restarted.
| 
| 
|============================================================================
| 1.3.6.1.2.1.25.3.1.n
|                | | |
|                | | * Identifying arc for type
|                | *-hrDeviceTypes (OIDs specifying device types)
|                *-hrDevice
|
| 1.3.6.1.2.1.25.3.2.1....
|                | | |
|                | | *hrDeviceEntry
|                | *hrDeviceTable
|                *-hrDevice
|
*/
{


/*
|============================================================================
|
| Call the "Gen_*_cache()" functions for each of the "sub-tables" within
| the hrDevice table.
|
| Each of these functions is responsible for:
|
|       + populating the hrDevice cache with however many rows are called for
|         given the device(s) available
|
|       + creating and populating their own cache for the sub-table if
|         the sub-table needs a cache.  (If all the sub-table attributes
|         are "computed" on request, then there is no need for a separate 
|         sub-table cache).
*/

if (Gen_HrPrinter_Cache(HRDV_TYPE_LASTARC_PRINTER) == FALSE) {
    return ( FALSE );
    }

if (Gen_HrProcessor_Cache(HRDV_TYPE_LASTARC_PROCESSOR) == FALSE) {
    return ( FALSE );
    }

if (Gen_HrNetwork_Cache(HRDV_TYPE_LASTARC_NETWORK) == FALSE) {
    return ( FALSE );
    }

if (Gen_HrDiskStorage_Cache(HRDV_TYPE_LASTARC_DISKSTORAGE) == FALSE) {
    return ( FALSE );
    }


/*
|============================================================================
|
| Now handle the odd "one-off" devices for which potentially just a single 
| entry is made into the existing hrDevice table cache.
*/
if (Gen_SingleDevices() == FALSE) {
    return ( FALSE );
    }

#if defined(CACHE_DUMP)
PrintCache(&hrDevice_cache);
PrintCache(&hrDiskStorage_cache);
#endif


/*
| HrDevice cache generation complete.
*/
return ( TRUE );
}


/* Gen_SingleDevices - Generate Single Device row entries in HrDevice */
/* Gen_SingleDevices - Generate Single Device row entries in HrDevice */
/* Gen_SingleDevices - Generate Single Device row entries in HrDevice */

BOOL
Gen_SingleDevices( void )

/*
|  EXPLICIT INPUTS:
|
|       None.
|
|  IMPLICIT INPUTS:
|
|       None.
|
|  OUTPUTS:
|
|     On Success:
|       Function creates a new row entry populated with all "static" cache-able
|       values for HrDevice table for each "one-off" device and returns TRUE.
|
|     On any Failure:
|       Function returns FALSE (indicating "not enough storage" or other
|       internal logic error).
|
|
|  THE BIG PICTURE:
|
|       At subagent startup time, the cache for each table in the MIB is
|       being populated.  This function handles populating hrDevice with
|       a row for each "single-type" device (such as keyboard).
|
|  OTHER THINGS TO KNOW:
|
|       Devices being added by this function are not associated with
|       sub-tables.
|
|       We handle:
|         + Keyboard "device"
|         + Pointing "device"
|         + Parallel and Serial Port "devices"
|
*/
{
UINT    key_status;             /* Value returned from GetKeyboardType()    */
UINT    button_count;           /* Mouse button count from GetSystemMetrics */
CHAR    msg[256];               /* (Big enough for constant strings below)  */
UINT    dev_number;

#define PHYS_SIZE 64
CHAR    phys_name[PHYS_SIZE];   /* Buffer where a string like "\\.C:" (for */
                                /*  example) is built for drive access.    */
HANDLE                  hdrv;   /* Handle to device                        */


/*
|==============================================================================
| Keyboard Device
|
| If we can get keyboard type... */
if ((key_status = GetKeyboardType(0)) != 0 ) {

    PCHAR       key_type;              /* Description string             */

    /* Select initial part of description string */
    switch (key_status) {
        case 1: key_type = "IBM PC/XT or compatible (83-key) keyboard"; break;
        case 2: key_type = "Olivetti \"ICO\" (102-key) keyboard"; break;
        case 3: key_type = "IBM PC/AT (84-key) or similar keyboard"; break;
        case 4: key_type = "IBM enhanced (101- or 102-key) keyboard"; break;
        case 5: key_type = "Nokia 1050 and similar keyboards"; break;
        case 6: key_type = "Nokia 9140 and similar keyboards"; break;
        case 7: key_type = "Japanese keyboard"; break;
        default: key_type = "Unknown keyboard"; break;
        }

    /* Build the full description string */
    sprintf(msg, "%s, Subtype=(%d)", key_type, GetKeyboardType(1));

    if (AddHrDeviceRow(HRDV_TYPE_LASTARC_KEYBOARD,      // Last Type OID arc
                       msg,                             // Description string
                       NULL,                            // No hidden context
                       CA_UNKNOWN) == NULL) {

        return ( FALSE );       /* Something blew */
        }
    }

/*
|==============================================================================
| Pointing Device
|
| If we can get Mouse Button count... */
if ((button_count = GetSystemMetrics(SM_CMOUSEBUTTONS)) != 0 ) {

    sprintf(msg, "%d-Buttons %s",
            button_count,
            (GetSystemMetrics(SM_MOUSEWHEELPRESENT)) ? " (with wheel)" : "");

 
    if (AddHrDeviceRow(HRDV_TYPE_LASTARC_POINTING,      // Last Type OID arc
                       msg,                             // Description string
                       NULL,                            // No hidden context
                       CA_UNKNOWN) == NULL) {

        return ( FALSE );       /* Something blew */
        }
    }


/*
|==============================================================================
| LPT Devices
|
| For every LPTx device we can open successfully. . .
*/
for (dev_number = 1; dev_number < 4; dev_number += 1) {

    /* Build it for device n: */
    sprintf(phys_name, "LPT%d:", dev_number);

    /*
    | Suppress any attempt by the system to talk to the user
    */
    SetErrorMode(SEM_FAILCRITICALERRORS);

    /* Attempt to get a handle using this physical name string */
    if ((hdrv = CreateFile(phys_name,           // Device
                               GENERIC_READ,    // Access mode
                               FILE_SHARE_READ, // Share Mode
                               NULL,            // Security
                               OPEN_EXISTING,   // CreationDistribution
                               FILE_ATTRIBUTE_NORMAL,  // FlagsandAttributes
                               NULL             // Template file
                           )) != INVALID_HANDLE_VALUE) {

        /*
        | Ok, we managed to get ahold of it, we'll put it in the table.
        */
        if (AddHrDeviceRow(HRDV_TYPE_LASTARC_PARALLELPORT, // Last Type OID arc
                           phys_name,                      // Descr string
                           NULL,                           // No hidden context
                           CA_UNKNOWN) == NULL) {
            CloseHandle(hdrv); // Prefix bug 445177
            return ( FALSE );       /* Something blew */
            }

        CloseHandle(hdrv);
        }   /* if (we managed to "CreateFile" the device) */
    else {
        /*
        | Keep trucking if we couldn't open the device, but quit when we
        | hit this error.
        */
        if (GetLastError() == ERROR_FILE_NOT_FOUND) {
            break;
            }
        }

    SetErrorMode(0);        /* Turn error suppression mode off */
    }   /* For each device */

/*
|==============================================================================
| COM Devices
|
| For every COMx device we can open successfully. . .
*/
for (dev_number = 1; dev_number <= 4; dev_number += 1) {

    /* Build it for device n: */
    sprintf(phys_name, "COM%d:", dev_number);

    /*
    | Suppress any attempt by the system to talk to the user
    */
    SetErrorMode(SEM_FAILCRITICALERRORS);

    /* Attempt to get a handle using this physical name string */
    if ((hdrv = CreateFile(phys_name,           // Device
                               GENERIC_READ,    // Access mode
                               FILE_SHARE_READ, // Share Mode
                               NULL,            // Security
                               OPEN_EXISTING,   // CreationDistribution
                               FILE_ATTRIBUTE_NORMAL,  // FlagsandAttributes
                               NULL             // Template file
                           )) != INVALID_HANDLE_VALUE) {

        /*
        | Ok, we managed to get ahold of it, we'll put it in the table.
        */
        if (AddHrDeviceRow(HRDV_TYPE_LASTARC_SERIALPORT,   // Last Type OID arc
                           phys_name,                      // Descr string
                           NULL,                           // No hidden context
                           CA_UNKNOWN) == NULL) {

            return ( FALSE );       /* Something blew */
            }

        CloseHandle(hdrv);
        }   /* if (we managed to "CreateFile" the device) */
    else {
        /*
        | Keep trucking if we couldn't open the device, but quit when we
        | hit this error (skip share failures).
        */
        if (GetLastError() == ERROR_FILE_NOT_FOUND) {
            break;
            }
        }

    SetErrorMode(0);        /* Turn error suppression mode off */
    }   /* For each device */
    return ( TRUE );    //--ft:09/28-- sundown cleanup
}

/* AddHrDeviceRow - Generate another Row Entry in HrDevice Table */
/* AddHrDeviceRow - Generate another Row Entry in HrDevice Table */
/* AddHrDeviceRow - Generate another Row Entry in HrDevice Table */

CACHEROW *
AddHrDeviceRow(
               ULONG   type_arc,       /* Last Arc value for OID for Type   */
               LPSTR   descr,          /* Description string                */
               void   *hidden_ctx,     /* If non-NULL: Hidden-context value */
               ATTRIB_TYPE  hc_type    /* Type of "hidden_ctx"              */
               )

/*
|  EXPLICIT INPUTS:
|
|       "type_arc" is the number that is inserted as the right-most arc in
|       Object Identifier that is the cache entry for the hrDevicetype of the
|       device.
|
|       "descr" is a string pointer that is to be the cached value of
|       the hrDeviceDesc attribute.
|
|       "hidden_ctx" - If non-null, this is a pointer to the value to be
|       stored as the "Hidden Context" attribute in the new row.
|
|       "hc_type" is the type of "hidden_ctx" if hidden_ctx is non-null.
|
|
|  IMPLICIT INPUTS:
|
|       The module-local head of the cache for the HrDevice table,
|       "HrDevice_cache".
|
|  OUTPUTS:
|
|     On Success:
|       Function creates a new row entry populated with all "static" cache-able
|       values for HrDevice table and returns a pointer to the new row entry.
|
|     On any Failure:
|       Function returns NULL (indicating "not enough storage" or other
|       internal logic error).
|
|
|  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 each of the "sub-hrDevicetable"
|       files to populate the cache for the HrDevice table for the rows
|       pertaining to a particular sub-table (hrProcessorTable, hrPrinterTable
|       etc).
|
|  OTHER THINGS TO KNOW:
|
|  The "hidden_ctx" argument provides an easy way for the caller to stash
|  a value useful for later run-time reference.  For instance, "GET" functions
|  for Printer devices may need a string that identifies the printer (for
|  a given row-entry) in order to lookup the current value of an SNMP 
|  attribute (like the current status).  So the "Hidden Context" attribute
|  may be set to a string that can be submitted to a Win32 function to obtain
|  the current status for the printer.
*/
{
static                          /* NOTE: "static" is a 'must'              */
ULONG     table_index=0;        /* HrDeviceTable index counter             */

CACHEROW *row;                  /* --> Cache structure for row-being built */


/*
| OK, the caller wants another row in the table, get a row-entry created.
*/
if ((row = CreateTableRow( HRDV_ATTRIB_COUNT ) ) == NULL) {
    return ( NULL );       // Out of memory
    }

/*
| Set up the standard-hrDevice attributes in the new row
*/

/* =========== hrDeviceIndex ==========*/
row->attrib_list[HRDV_INDEX].attrib_type = CA_NUMBER;
row->attrib_list[HRDV_INDEX].u.unumber_value = (table_index += 1) ;


/* =========== hrDeviceType ==========
|
| Some GET functions for "computed" attributes expect to be able to use
| the value of the "hrDeviceType" cache value stored below to dispatch
| to appropriate code based on the device type (using the last type-OID arc
| as the "switch" value).
*/
row->attrib_list[HRDV_TYPE].attrib_type = CA_NUMBER;
row->attrib_list[HRDV_TYPE].u.unumber_value = type_arc ;


/* =========== hrDeviceDescr ==========*/
row->attrib_list[HRDV_DESCR].attrib_type = CA_STRING;
if ( (row->attrib_list[HRDV_DESCR].u.string_value
      = ( LPSTR ) malloc(strlen(descr) + 1)) == NULL) {
    return ( NULL );       /* out of memory */
    }
strcpy(row->attrib_list[HRDV_DESCR].u.string_value, descr);


/*
| The rest of the standard hrDevice attributes are "computed" at run time
*/

/* =========== hrDeviceStatus ==========*/
row->attrib_list[HRDV_STATUS].attrib_type = CA_COMPUTED;


/* =========== hrDeviceErrors ==========*/
row->attrib_list[HRDV_ERRORS].attrib_type = CA_COMPUTED;

/*
|================================================================
| If they gave us a hidden-context attribute string, store it now.
*/
if (hidden_ctx != NULL) {

    switch (hc_type) {

        case CA_STRING:
            row->attrib_list[HIDDEN_CTX].attrib_type = CA_STRING;
            if ( (row->attrib_list[HIDDEN_CTX].u.string_value
                  = ( LPSTR ) malloc(strlen((LPSTR)hidden_ctx) + 1)) == NULL) {
                return ( NULL );       /* out of memory */
                }
            strcpy(row->attrib_list[HIDDEN_CTX].u.string_value, hidden_ctx);
            break;

        case CA_NUMBER:
            row->attrib_list[HIDDEN_CTX].attrib_type = CA_NUMBER;
            row->attrib_list[HIDDEN_CTX].u.unumber_value =
                                                      *((ULONG *) hidden_ctx);
            break;

        case CA_CACHE:
            row->attrib_list[HIDDEN_CTX].attrib_type = CA_CACHE;
            row->attrib_list[HIDDEN_CTX].u.cache = (CACHEHEAD *) hidden_ctx;
            break;

        case CA_UNKNOWN:
            row->attrib_list[HIDDEN_CTX].attrib_type = CA_UNKNOWN;
            break;

        default:
            return ( NULL );    /* Something wrong */
        }
    }
else {
    /* Show no "Hidden-Context" attribute for this row */
    row->attrib_list[HIDDEN_CTX].attrib_type = CA_UNKNOWN;
    row->attrib_list[HIDDEN_CTX].u.string_value = NULL;
    }

/*
| Now insert the filled-in CACHEROW structure into the
| cache-list for the hrDeviceTable.
*/
if (AddTableRow(row->attrib_list[HRDV_INDEX].u.unumber_value,  /* Index */
                row,                                           /* Row   */
                &hrDevice_cache                                /* Cache */
                ) == FALSE) {
    return ( NULL );       /* Internal Logic Error! */
    }

/*
| Meet caller's expectation of receiving a pointer to the new row.
*/
return ( row );
}

#if defined(CACHE_DUMP)

/* debug_print_hrdevice - Prints a Row from HrDevice */
/* debug_print_hrdevice - Prints a Row from HrDevice */
/* debug_print_hrdevice - Prints a Row from HrDevice */

static void
debug_print_hrdevice(
                     CACHEROW     *row  /* Row in hrDiskStorage 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:
*/
{
char    *type;          /* String representation of device type */

if (row == NULL) {
    fprintf(OFILE, "====================\n");
    fprintf(OFILE, "hrDevice Table Cache\n");
    fprintf(OFILE, "====================\n");
    return;
    }

fprintf(OFILE, "hrDeviceIndex. . . . . . . %d\n",
        row->attrib_list[HRDV_INDEX].u.unumber_value);

switch (row->attrib_list[HRDV_TYPE].u.unumber_value) {

    case 1: type = "Other"; break;
    case 2: type = "Unknown"; break;
    case 3: type = "Processor"; break;
    case 4: type = "Network"; break;
    case 5: type = "Printer"; break;
    case 6: type = "DiskStorage"; break;
    case 10: type = "Video"; break;
    case 11: type = "Audio"; break;
    case 12: type = "Coprocessor"; break;
    case 13: type = "Keyboard"; break;
    case 14: type = "Modem"; break;
    case 15: type = "ParallelPort"; break;
    case 16: type = "Pointing"; break;
    case 17: type = "SerialPort"; break;
    case 18: type = "Tape"; break;
    case 19: type = "Clock"; break;
    case 20: type = "VolatileMemory"; break;
    case 21: type = "NonVolatileMemory"; break;
    default: type = "<Unknown!>"; break;
    }

fprintf(OFILE, "hrDeviceType . . . . . . . %d (%s)\n",
        row->attrib_list[HRDV_TYPE].u.unumber_value, type);

fprintf(OFILE, "hrDeviceDescr. . . . . . . %s\n",
        row->attrib_list[HRDV_DESCR].u.string_value);

fprintf(OFILE, "hrDeviceStatus . . . . . . ");
switch (row->attrib_list[HRDV_STATUS].attrib_type) {

    case CA_STRING:
        fprintf(OFILE, "CA_STRING: \"%s\"\n",
                row->attrib_list[HRDV_STATUS].u.string_value);
        break;

    case CA_NUMBER:
        fprintf(OFILE, "CA_NUMBER: %d\n",
                row->attrib_list[HRDV_STATUS].u.unumber_value);
        break;

    case CA_UNKNOWN:
        fprintf(OFILE, "CA_UNKNOWN\n");
        break;

    case CA_COMPUTED:
        fprintf(OFILE, "CA_COMPUTED\n");
        break;

    default:
        fprintf(OFILE, "(INCORRECT)\n");
        break;
    }

fprintf(OFILE, "hrDeviceErrors . . . . . . ");
switch (row->attrib_list[HRDV_ERRORS].attrib_type) {

    case CA_STRING:
        fprintf(OFILE, "CA_STRING: \"%s\"\n",
                row->attrib_list[HRDV_ERRORS].u.string_value);
        break;

    case CA_NUMBER:
        fprintf(OFILE, "CA_NUMBER: %d\n",
                row->attrib_list[HRDV_ERRORS].u.unumber_value);
        break;

    case CA_UNKNOWN:
        fprintf(OFILE, "CA_UNKNOWN\n");
        break;

    case CA_COMPUTED:
        fprintf(OFILE, "CA_COMPUTED\n");
        break;

    default:
        fprintf(OFILE, "(INCORRECT)\n");
        break;
    }


/* Hidden Context */
fprintf(OFILE, "(HIDDEN CONTEXT) . . . . . ");

switch (row->attrib_list[HRDV_TYPE].u.unumber_value) {

    /*
    | What is stored in HIDDEN_CTX is hardwired for these types
    | of cache entries:
    */
    case 3: // "Processor"
        fprintf(OFILE, "CA_NUMBER: %d (Processor Number)\n",
                row->attrib_list[HIDDEN_CTX].u.unumber_value);
        break;


    case 4: // "Network"
        fprintf(OFILE, "CA_NUMBER: %d ( \"hrNetworkIfIndex\" value)\n",
                row->attrib_list[HIDDEN_CTX].u.unumber_value);
        break;


    case 5: // "Printer"
        fprintf(OFILE, "CA_STRING: \"%s\" ( \"OpenPrinter\" string)\n",
                row->attrib_list[HIDDEN_CTX].u.string_value);
        break;


    /* For this type, it varies */
    case 6: // "DiskStorage"

        switch (row->attrib_list[HIDDEN_CTX].attrib_type) {

            case CA_STRING:
                fprintf(OFILE, "CA_STRING: \"%s\"\n",
                        row->attrib_list[HIDDEN_CTX].u.string_value);
                break;

            case CA_NUMBER:
                fprintf(OFILE, "CA_NUMBER: %d\n",
                        row->attrib_list[HIDDEN_CTX].u.unumber_value);
                break;

            case CA_UNKNOWN:
                fprintf(OFILE, "CA_UNKNOWN\n");
                break;

            case CA_COMPUTED:
                fprintf(OFILE, "CA_COMPUTED\n");
                break;

            case CA_CACHE:
                fprintf(OFILE, "CA_CACHE @ 0x%x\n",
                        row->attrib_list[HIDDEN_CTX].u.cache);
                if (row->attrib_list[HIDDEN_CTX].u.cache != NULL) {
                    PrintCache(row->attrib_list[HIDDEN_CTX].u.cache);
                    }
                break;
            }

        break;


    case 10: // "Video"
    case 11: // "Audio"
    case 12: // "Coprocessor"
    case 13: // "Keyboard"
    case 14: // "Modem"
    case 15: // "ParallelPort"
    case 16: // "Pointing"
    case 17: // "SerialPort"
    case 18: // "Tape"
    case 19: // "Clock"
    case 20: // "VolatileMemory"
    case 21: // "NonVolatileMemory"
    case 2: // "Unknown"
    case 1: // "Other"
    default:
        fprintf(OFILE, "<None>\n");
        break;

    }
}
#endif