1163 lines
38 KiB
C
1163 lines
38 KiB
C
|
/*
|
|||
|
* HrSWInstalledEntry.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 HrSWInstalledEntry. 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:49:12 1996
|
|||
|
*
|
|||
|
*/
|
|||
|
|
|||
|
|
|||
|
#include <windows.h>
|
|||
|
#include <malloc.h>
|
|||
|
|
|||
|
#include <snmp.h>
|
|||
|
#include <winsock.h> /* For htons() */
|
|||
|
|
|||
|
#include "mib.h"
|
|||
|
#include "smint.h"
|
|||
|
#include "hostmsmi.h"
|
|||
|
#include "user.h" /* Developer supplied include file */
|
|||
|
#include "HMCACHE.H" /* Cache-related definitions */
|
|||
|
#include <regstr.h> /* For Registry-lookup on software */
|
|||
|
#include <winreg.h> /* For Registry-lookup on software */
|
|||
|
#include <objbase.h> /* For CoFileTimeToDosDateTime() */
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
|==============================================================================
|
|||
|
| Function prototypes for this module.
|
|||
|
|
|
|||
|
*/
|
|||
|
/* Gen_SingleDevices - Generate Single Device row entries in HrDevice */
|
|||
|
BOOL Gen_SingleDevices( void );
|
|||
|
|
|||
|
|
|||
|
/* AddSWInstalled - Add a row to HrSWInstalled Table */
|
|||
|
BOOL AddSWInstalled( HKEY sw_key, FILETIME *ft);
|
|||
|
|
|||
|
|
|||
|
#if defined(CACHE_DUMP)
|
|||
|
|
|||
|
/* debug_print_hrswinstalled - Prints a Row from HrSWInstalled table */
|
|||
|
static void
|
|||
|
debug_print_hrswinstalled(
|
|||
|
CACHEROW *row /* Row in hrSWInstalled table */
|
|||
|
);
|
|||
|
#endif
|
|||
|
|
|||
|
/*
|
|||
|
|==============================================================================
|
|||
|
| Create the list-head for the HrSWInstalled table cache.
|
|||
|
|
|
|||
|
| (This macro is defined in "HMCACHE.H").
|
|||
|
*/
|
|||
|
static CACHEHEAD_INSTANCE(hrSWInstalled_cache, debug_print_hrswinstalled);
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
|==============================================================================
|
|||
|
| hrSWInstalledTable Attribute Defines
|
|||
|
|
|
|||
|
| Each attribute defined for this table is associated with one of the
|
|||
|
| #defines below. These symbols are used as C indices into the array of
|
|||
|
| attributes within a cached-row.
|
|||
|
|
|
|||
|
*/
|
|||
|
#define HRIN_INDEX 0 // hrSWInstalledIndex
|
|||
|
#define HRIN_NAME 1 // hrSWInstalledName
|
|||
|
#define HRIN_DATE 2 // hrSWInstalledDate
|
|||
|
//-->Add more here, change count below!
|
|||
|
#define HRIN_ATTRIB_COUNT 3
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
* GetHrSWInstalledIndex
|
|||
|
* A unique value for each piece of software installed on the host. This
|
|||
|
* value shall be in the range from 1 to the number of piece
|
|||
|
*
|
|||
|
* Gets the value for HrSWInstalledIndex.
|
|||
|
*
|
|||
|
* 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==================
|
|||
|
| hrSWInstalledIndex
|
|||
|
|
|
|||
|
| ACCESS SYNTAX
|
|||
|
| read-only INTEGER (1..2147483647)
|
|||
|
|
|
|||
|
| "A unique value for each piece of software installed on the host. This value
|
|||
|
| shall be in the range from 1 to the number of pieces of software installed on
|
|||
|
| the host."
|
|||
|
|
|
|||
|
|============================================================================
|
|||
|
| 1.3.6.1.2.1.25.6.3.1.1.<instance>
|
|||
|
| | | | |
|
|||
|
| | | | *-hrSwInstalledIndex
|
|||
|
| | | *-hrSWInstalledEntry
|
|||
|
| | *-hrSWInstalledTable
|
|||
|
| *-hrSWInstalled
|
|||
|
*/
|
|||
|
|
|||
|
UINT
|
|||
|
GetHrSWInstalledIndex(
|
|||
|
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, &hrSWInstalled_cache)) == NULL) {
|
|||
|
return SNMP_ERRORSTATUS_GENERR;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
| Return the "hrSWInstalledIndex" value from this entry
|
|||
|
*/
|
|||
|
*outvalue = row->attrib_list[HRIN_INDEX].u.unumber_value;
|
|||
|
|
|||
|
return SNMP_ERRORSTATUS_NOERROR ;
|
|||
|
|
|||
|
} /* end of GetHrSWInstalledIndex() */
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
* GetHrSWInstalledName
|
|||
|
* A textual description of this installed piece of software, including the
|
|||
|
* manufacturer, revision, the name by which it is commonl
|
|||
|
*
|
|||
|
* Gets the value for HrSWInstalledName.
|
|||
|
*
|
|||
|
* 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==================
|
|||
|
| hrSWInstalledName
|
|||
|
|
|
|||
|
| ACCESS SYNTAX
|
|||
|
| read-only InternationalDisplayString (SIZE (0..64))
|
|||
|
|
|
|||
|
| "A textual description of this installed piece of software, including the
|
|||
|
| manufacturer, revision, the name by which it is commonly known, and
|
|||
|
| optionally, its serial number."
|
|||
|
|
|
|||
|
|============================================================================
|
|||
|
| DISCUSSION:
|
|||
|
| For logo 95 programs, we use the Registry sub-key name.
|
|||
|
|
|
|||
|
| 1.3.6.1.2.1.25.6.3.1.2.<instance>
|
|||
|
| | | | |
|
|||
|
| | | | *-hrSwInstalledName
|
|||
|
| | | *-hrSWInstalledEntry
|
|||
|
| | *-hrSWInstalledTable
|
|||
|
| *-hrSWInstalled
|
|||
|
*/
|
|||
|
|
|||
|
UINT
|
|||
|
GetHrSWInstalledName(
|
|||
|
OUT InternationalDisplayString *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, &hrSWInstalled_cache)) == NULL) {
|
|||
|
return SNMP_ERRORSTATUS_GENERR;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
| Return the "hrSWInstalledName" value from this entry
|
|||
|
*/
|
|||
|
outvalue->string = row->attrib_list[HRIN_NAME].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 GetHrSWInstalledName() */
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
* GetHrSWInstalledID
|
|||
|
* The product ID of this installed piece of software.
|
|||
|
*
|
|||
|
* Gets the value for HrSWInstalledID.
|
|||
|
*
|
|||
|
* 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==================
|
|||
|
| hrSWInstalledID
|
|||
|
|
|
|||
|
| ACCESS SYNTAX
|
|||
|
| read-only ProductID
|
|||
|
|
|
|||
|
| "The product ID of this installed piece of software."
|
|||
|
|
|
|||
|
|============================================================================
|
|||
|
| DISCUSSION:
|
|||
|
| For logo 95 programs we don't know the ProductID as an OID, so we
|
|||
|
| return the ProductID for "unknown": { 0.0 }
|
|||
|
|
|
|||
|
| 1.3.6.1.2.1.25.6.3.1.3.<instance>
|
|||
|
| | | | |
|
|||
|
| | | | *-hrSwInstalledID
|
|||
|
| | | *-hrSWInstalledEntry
|
|||
|
| | *-hrSWInstalledTable
|
|||
|
| *-hrSWInstalled
|
|||
|
*/
|
|||
|
|
|||
|
UINT
|
|||
|
GetHrSWInstalledID(
|
|||
|
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 GetHrSWInstalledID() */
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
* GetHrSWInstalledType
|
|||
|
* The type of this software.
|
|||
|
*
|
|||
|
* Gets the value for HrSWInstalledType.
|
|||
|
*
|
|||
|
* 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==================
|
|||
|
| hrSWInstalledType
|
|||
|
|
|
|||
|
| ACCESS SYNTAX
|
|||
|
| read-only INTEGER {unknown(1),operatingSystem(2),deviceDriver(3),
|
|||
|
| application(4)}
|
|||
|
|
|
|||
|
| "The type of this software."
|
|||
|
|============================================================================
|
|||
|
| DISCUSSION:
|
|||
|
| For logo 95 programs we presume that all uninstallable software is
|
|||
|
| an application. That is the only type we return.
|
|||
|
|
|
|||
|
| 1.3.6.1.2.1.25.6.3.1.4.<instance>
|
|||
|
| | | | |
|
|||
|
| | | | *-hrSwInstalledType
|
|||
|
| | | *-hrSWInstalledEntry
|
|||
|
| | *-hrSWInstalledTable
|
|||
|
| *-hrSWInstalled
|
|||
|
*/
|
|||
|
|
|||
|
UINT
|
|||
|
GetHrSWInstalledType(
|
|||
|
OUT INTSWType *outvalue ,
|
|||
|
IN Access_Credential *access ,
|
|||
|
IN InstanceName *instance )
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
*outvalue = 4; // 4 = "application"
|
|||
|
|
|||
|
return SNMP_ERRORSTATUS_NOERROR ;
|
|||
|
|
|||
|
} /* end of GetHrSWInstalledType() */
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
* GetHrSWInstalledDate
|
|||
|
* The last-modification date of this application as it would appear in a
|
|||
|
* directory listing.
|
|||
|
*
|
|||
|
* Gets the value for HrSWInstalledDate.
|
|||
|
*
|
|||
|
* 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==================
|
|||
|
| hrSWInstalledDate
|
|||
|
|
|
|||
|
| ACCESS SYNTAX
|
|||
|
| read-only DateAndTime
|
|||
|
|
|
|||
|
| "The last-modification date of this application as it would appear in a
|
|||
|
| directory listing."
|
|||
|
|============================================================================
|
|||
|
| DISCUSSION:
|
|||
|
| For logo 95 programs we use the date of the last write into the
|
|||
|
| Registry key associated with the application.
|
|||
|
|
|
|||
|
| 1.3.6.1.2.1.25.6.3.1.5.<instance>
|
|||
|
| | | | |
|
|||
|
| | | | *-hrSwInstalledDate
|
|||
|
| | | *-hrSWInstalledEntry
|
|||
|
| | *-hrSWInstalledTable
|
|||
|
| *-hrSWInstalled
|
|||
|
*/
|
|||
|
|
|||
|
UINT
|
|||
|
GetHrSWInstalledDate(
|
|||
|
OUT DateAndTime *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, &hrSWInstalled_cache)) == NULL) {
|
|||
|
return SNMP_ERRORSTATUS_GENERR;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
| Return the "hrSWInstalledDate" value from this entry
|
|||
|
*/
|
|||
|
outvalue->string = row->attrib_list[HRIN_DATE].u.string_value;
|
|||
|
outvalue->length = 8;
|
|||
|
|
|||
|
return SNMP_ERRORSTATUS_NOERROR ;
|
|||
|
|
|||
|
} /* end of GetHrSWInstalledDate() */
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
* HrSWInstalledEntryFindInstance
|
|||
|
*
|
|||
|
* 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
|
|||
|
HrSWInstalledEntryFindInstance( 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 <= HRSWINSTALLEDENTRY_VAR_INDEX )
|
|||
|
// No instance was specified
|
|||
|
return SNMP_ERRORSTATUS_NOSUCHNAME ;
|
|||
|
else if ( FullOid->idLength != HRSWINSTALLEDENTRY_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[ HRSWINSTALLEDENTRY_VAR_INDEX ] ;
|
|||
|
|
|||
|
/*
|
|||
|
| For hrSWInstalledTable, the instance arc(s) is a single arc, and
|
|||
|
| it must correctly select an entry in the hrSWInstalled Table cache.
|
|||
|
| Check that here.
|
|||
|
*/
|
|||
|
if ( FindTableRow(tmp_instance, &hrSWInstalled_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 HrSWInstalledEntryFindInstance() */
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
* HrSWInstalledEntryFindNextInstance
|
|||
|
*
|
|||
|
* 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
|
|||
|
HrSWInstalledEntryFindNextInstance( 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 <= HRSWINSTALLEDENTRY_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[ HRSWINSTALLEDENTRY_VAR_INDEX ] ;
|
|||
|
}
|
|||
|
|
|||
|
/* Now go off and try to find the next instance in the table */
|
|||
|
if ((row = FindNextTableRow(tmp_instance, &hrSWInstalled_cache)) == NULL) {
|
|||
|
return SNMP_ERRORSTATUS_NOSUCHNAME ;
|
|||
|
}
|
|||
|
|
|||
|
instance->ids[ 0 ] = row->index ;
|
|||
|
instance->idLength = 1 ;
|
|||
|
|
|||
|
return SNMP_ERRORSTATUS_NOERROR ;
|
|||
|
|
|||
|
} /* end of HrSWInstalledEntryFindNextInstance() */
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
* HrSWInstalledEntryConvertInstance
|
|||
|
*
|
|||
|
* 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
|
|||
|
HrSWInstalledEntryConvertInstance( 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 HrSWInstalledEntryConvertInstance() */
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
* HrSWInstalledEntryFreeInstance
|
|||
|
*
|
|||
|
* 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
|
|||
|
HrSWInstalledEntryFreeInstance( IN OUT InstanceName *instance )
|
|||
|
{
|
|||
|
|
|||
|
/* No action needed for hrSWInstalledTable */
|
|||
|
} /* end of HrSWInstalledEntryFreeInstance() */
|
|||
|
|
|||
|
/*
|
|||
|
| End of Generated Code
|
|||
|
*/
|
|||
|
|
|||
|
|
|||
|
/* Gen_HrSWInstalled_Cache - Generate a cache for HrSWInstalled Table */
|
|||
|
/* Gen_HrSWInstalled_Cache - Generate a cache for HrSWInstalled Table */
|
|||
|
/* Gen_HrSWInstalled_Cache - Generate a cache for HrSWInstalled Table */
|
|||
|
|
|||
|
BOOL
|
|||
|
Gen_HrSWInstalled_Cache(
|
|||
|
void
|
|||
|
)
|
|||
|
|
|||
|
/*
|
|||
|
| EXPLICIT INPUTS:
|
|||
|
|
|
|||
|
| None.
|
|||
|
|
|
|||
|
| IMPLICIT INPUTS:
|
|||
|
|
|
|||
|
| The module-local head of the cache for the HrSWInstalled table,
|
|||
|
| "hrSWInstalled_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 HrSWInstalled 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:
|
|||
|
|
|
|||
|
| This implementation of this entire group is rather problematical without the
|
|||
|
| creation of a standard. It certainly appears that many software manufacturers
|
|||
|
| dutifully register SOMETHING in the Registry when software is installed,
|
|||
|
| however there appears to be no rhyme nor reason to the information put into
|
|||
|
| the Registry in leaves below the manufacturers name. Consequently, for
|
|||
|
| installed application software, there is no easy, reliable way of mapping
|
|||
|
| the Registry information into entries in this table.
|
|||
|
|
|
|||
|
| It is clear that some consistent scheme seems to be currently implemented for
|
|||
|
| Microsoft software, however the details of extracting it from the Registry
|
|||
|
| (and whether or not all information needed for full population of entries in
|
|||
|
| this table is available) is not documented.
|
|||
|
|
|
|||
|
| Proper implementation of "hrSWInstalled" requires the creation and
|
|||
|
| promulgation of a standard for registering ISD software (presumably in the
|
|||
|
| Registry). Information in "hrSWInstalled" includes attributes with
|
|||
|
| values of Object Identifiers. Webenable Inc. is prepared to work with
|
|||
|
| Microsoft in establishing a standard for registering software in a fashion
|
|||
|
| that allows proper implementation of the "hrSWInstalled" table.
|
|||
|
|
|
|||
|
| Resolution:
|
|||
|
| Report only logo 95 compliant software initially.
|
|||
|
|
|
|||
|
|============================================================================
|
|||
|
|
|
|||
|
| 1.3.6.1.2.1.25.6.1.0....
|
|||
|
| | |
|
|||
|
| | *hrSWInstalledLastChange
|
|||
|
| *-hrSWInstalled
|
|||
|
|
|
|||
|
| 1.3.6.1.2.1.25.6.2.0....
|
|||
|
| | |
|
|||
|
| | *hrSWInstalledLastUpdateTime
|
|||
|
| *-hrSWInstalled
|
|||
|
|
|
|||
|
| 1.3.6.1.2.1.25.6.3.1....
|
|||
|
| | | |
|
|||
|
| | | *-hrSWInstalledEntry
|
|||
|
| | *-hrSWInstalledTable
|
|||
|
| *-hrSWInstalled
|
|||
|
|
|
|||
|
*/
|
|||
|
|
|||
|
#define SUBKEY_LEN 64 // Long enough for short key-name of software
|
|||
|
{
|
|||
|
HKEY subkey; /* Handle of subkey for uninstall software */
|
|||
|
DWORD index; /* Index counter for enumerating subkeys */
|
|||
|
LONG enum_status=ERROR_SUCCESS; /* Status from subkey enumeration */
|
|||
|
CHAR subkey_name[SUBKEY_LEN]; /* Subkey name returned here */
|
|||
|
DWORD subkey_len=SUBKEY_LEN; /* Subkey name buffer size */
|
|||
|
FILETIME keytime; /* Time subkey was last written to */
|
|||
|
BOOL add_status; /* Status from add-row operation */
|
|||
|
HKEY sw_key; /* Handle of software key for value enum */
|
|||
|
|
|||
|
|
|||
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, // hkey - currently open
|
|||
|
REGSTR_PATH_UNINSTALL, // subkey to open
|
|||
|
0, // options
|
|||
|
KEY_READ, // Security access mask
|
|||
|
&subkey
|
|||
|
) == ERROR_SUCCESS) {
|
|||
|
|
|||
|
/* Enumerate the keys using the Uninstall subkey */
|
|||
|
for (index = 0; enum_status != ERROR_NO_MORE_ITEMS; index += 1) {
|
|||
|
|
|||
|
subkey_len=SUBKEY_LEN;
|
|||
|
|
|||
|
enum_status = RegEnumKeyEx(subkey, // Enumerating this key
|
|||
|
index, // next subkey index
|
|||
|
subkey_name, // Buffer to rcv subkey name
|
|||
|
&subkey_len, // Buffer size
|
|||
|
NULL, // Reserved
|
|||
|
NULL, // Class name buffer
|
|||
|
NULL, // Class buffer size
|
|||
|
&keytime // Time of last write to subkey
|
|||
|
);
|
|||
|
|
|||
|
/* Skip if we didn't open OK */
|
|||
|
if (enum_status != ERROR_SUCCESS) {
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/* Now try for the software itself */
|
|||
|
if (RegOpenKeyEx(subkey, // hkey - currently open
|
|||
|
subkey_name, // subkey to open
|
|||
|
0, // options
|
|||
|
KEY_READ, // Security access mask
|
|||
|
&sw_key
|
|||
|
) == ERROR_SUCCESS) {
|
|||
|
|
|||
|
/* Now Enumerate the Values of this key */
|
|||
|
add_status =
|
|||
|
AddSWInstalled(sw_key, // Key to obtain DisplayName
|
|||
|
&keytime // Date and Time installed
|
|||
|
);
|
|||
|
RegCloseKey(sw_key);
|
|||
|
|
|||
|
/* If something blew down below, bail out */
|
|||
|
if (add_status == FALSE) {
|
|||
|
|
|||
|
RegCloseKey(subkey);
|
|||
|
return ( FALSE );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
RegCloseKey(subkey);
|
|||
|
}
|
|||
|
|
|||
|
#if defined(CACHE_DUMP)
|
|||
|
PrintCache(&hrSWInstalled_cache);
|
|||
|
#endif
|
|||
|
|
|||
|
/* hrSWInstalled cache initialized */
|
|||
|
return ( TRUE );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/* UTCDosDateTimeToLocalSysTime - converts UTC msdos date and time to local SYSTEMTIME structure */
|
|||
|
/* UTCDosDateTimeToLocalSysTime - converts UTC msdos date and time to local SYSTEMTIME structure */
|
|||
|
/* UTCDosDateTimeToLocalSysTime - converts UTC msdos date and time to local SYSTEMTIME structure */
|
|||
|
void UTCDosDateTimeToLocalSysTime(WORD msdos_date, WORD msdos_time, LPSYSTEMTIME pSysTime)
|
|||
|
{
|
|||
|
SYSTEMTIME utcSysTime;
|
|||
|
|
|||
|
utcSysTime.wYear = (msdos_date >> 9) + 1980;
|
|||
|
utcSysTime.wMonth = ((msdos_date >> 5) & 0x0F);
|
|||
|
utcSysTime.wDay = (msdos_date & 0x1F);
|
|||
|
utcSysTime.wDayOfWeek = 0;
|
|||
|
utcSysTime.wHour = (msdos_time >> 11);
|
|||
|
utcSysTime.wMinute = ((msdos_time >> 5) & 0x3F);
|
|||
|
utcSysTime.wSecond = ((msdos_time & 0x1F) * 2);
|
|||
|
utcSysTime.wMilliseconds = 0;
|
|||
|
|
|||
|
if (!SystemTimeToTzSpecificLocalTime(
|
|||
|
NULL, // [in] use active time zone
|
|||
|
&utcSysTime, // [in] utc system time
|
|||
|
pSysTime)) // [out] local time
|
|||
|
{
|
|||
|
// if the utc time could not be converted to local time,
|
|||
|
// just return the utc time
|
|||
|
memcpy(&utcSysTime, pSysTime, sizeof(SYSTEMTIME));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/* AddSWInstalled - Add a row to HrSWInstalled Table */
|
|||
|
/* AddSWInstalled - Add a row to HrSWInstalled Table */
|
|||
|
/* AddSWInstalled - Add a row to HrSWInstalled Table */
|
|||
|
|
|||
|
BOOL
|
|||
|
AddSWInstalled(
|
|||
|
HKEY sw_key,
|
|||
|
FILETIME *ft
|
|||
|
)
|
|||
|
/*
|
|||
|
| EXPLICIT INPUTS:
|
|||
|
|
|
|||
|
| "sw_key" - an opened key for a piece of software whose Values we
|
|||
|
| must enumerate looking for "DisplayName"
|
|||
|
|
|
|||
|
| "ft" - This is the time that the key was last written, and we
|
|||
|
| take it as the time the software was installed.
|
|||
|
|
|
|||
|
| IMPLICIT INPUTS:
|
|||
|
|
|
|||
|
| The module-local head of the cache for the HrSWInstalled table,
|
|||
|
| "hrSWInstalled_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:
|
|||
|
|
|
|||
|
| The Gen_SWInstalled_cache() function has been invoked to populate
|
|||
|
| the cache, and this function is called when it has found another
|
|||
|
| piece of software for which a row-entry needs to be placed into
|
|||
|
| the cache.
|
|||
|
|
|
|||
|
| OTHER THINGS TO KNOW:
|
|||
|
|
|
|||
|
*/
|
|||
|
|
|||
|
#define VALUE_LEN 32 // Long enough for "UninstallString"
|
|||
|
#define VALUE_DATA_LEN 128 // Long enough for a long "casual" name
|
|||
|
{
|
|||
|
DWORD index; /* Index counter for enumerating subkeys */
|
|||
|
LONG enum_status=ERROR_SUCCESS; /* Status from subkey enumeration */
|
|||
|
CHAR value_name[VALUE_LEN]; /* Value name returned here */
|
|||
|
DWORD value_len; /* Value name buffer size */
|
|||
|
DWORD value_type; /* Type code for value string */
|
|||
|
CHAR value_data[VALUE_DATA_LEN]; /* Value's value returned here */
|
|||
|
DWORD value_data_len; /* Value's value buffer length resides here*/
|
|||
|
|
|||
|
static /* NOTE: "static" is a 'must' */
|
|||
|
ULONG table_index=0; /* HrDeviceTable index counter */
|
|||
|
CACHEROW *row; /* --> Cache structure for row-being built */
|
|||
|
WORD msdos_date; /* Conversion area for software date/time */
|
|||
|
WORD msdos_time; /* Conversion area for software date/time */
|
|||
|
char *octet_string; /* Alias for building DateAndTime */
|
|||
|
UINT i; /* Loop index */
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
| Now go a-lookin' for "DisplayName", the value whose data will give us
|
|||
|
| the name of the installed software.
|
|||
|
|
|
|||
|
| For each Value associated with this software's key . . .
|
|||
|
*/
|
|||
|
for (index = 0; enum_status != ERROR_NO_MORE_ITEMS; index += 1) {
|
|||
|
|
|||
|
/* Make sure these cells continues to reflect the buffer size */
|
|||
|
value_len = VALUE_LEN;
|
|||
|
value_data_len = VALUE_DATA_LEN;
|
|||
|
|
|||
|
enum_status = RegEnumValue(sw_key, // Key whose values we're enuming
|
|||
|
index, // index of next value
|
|||
|
value_name, // Value name buffer
|
|||
|
&value_len, // length of Value name buffer
|
|||
|
NULL, // reserved
|
|||
|
&value_type, // type of value data
|
|||
|
value_data, // Buffer for value's data
|
|||
|
&value_data_len// Length of data buffer
|
|||
|
);
|
|||
|
|
|||
|
/* Only if we managed to fetch this key do we try to recognize it */
|
|||
|
if (enum_status == ERROR_SUCCESS) {
|
|||
|
|
|||
|
/* If the value we just read is for "DisplayName" */
|
|||
|
if ( strcmp(value_name, REGSTR_VAL_UNINSTALLER_DISPLAYNAME) == 0) {
|
|||
|
|
|||
|
/*
|
|||
|
| Get a row-entry created.
|
|||
|
*/
|
|||
|
if ((row = CreateTableRow( HRIN_ATTRIB_COUNT ) ) == NULL) {
|
|||
|
return ( FALSE ); // Out of memory
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
| Set up the cached hrSWInstalled attributes in the new row
|
|||
|
*/
|
|||
|
|
|||
|
/* =========== hrSWInstalledIndex ==========*/
|
|||
|
row->attrib_list[HRIN_INDEX].attrib_type = CA_NUMBER;
|
|||
|
row->attrib_list[HRIN_INDEX].u.unumber_value = (table_index += 1) ;
|
|||
|
|
|||
|
|
|||
|
/* =========== hrSWInstalledName ==========*/
|
|||
|
row->attrib_list[HRIN_NAME].attrib_type = CA_STRING;
|
|||
|
if ( (row->attrib_list[HRIN_NAME].u.string_value
|
|||
|
= ( LPSTR ) malloc(value_data_len + 1)) == NULL) {
|
|||
|
return ( FALSE ); /* out of memory */
|
|||
|
}
|
|||
|
strcpy(row->attrib_list[HRIN_NAME].u.string_value, value_data);
|
|||
|
|
|||
|
|
|||
|
/* =========== hrSWInstalledDate ==========
|
|||
|
|
|
|||
|
| Here's the deal on this one. We've got a 64-bit FILETIME
|
|||
|
| representation of when the Registry entry was made for the
|
|||
|
| software. We're taking this as the install time of the software.
|
|||
|
|
|
|||
|
| So we convert to MS-DOS time, then to DateAndTime (in the
|
|||
|
| 8-octet form) below:
|
|||
|
|========================== From RFC1514 ========================
|
|||
|
|
|
|||
|
| DateAndTime ::= OCTET STRING (SIZE (8 | 11))
|
|||
|
| -- A date-time specification for the local time of day.
|
|||
|
| -- This data type is intended to provide a consistent
|
|||
|
| -- method of reporting date information.
|
|||
|
| --
|
|||
|
| -- field octets contents range
|
|||
|
| -- _____ ______ ________ _____
|
|||
|
| -- 1 1-2 year 0..65536
|
|||
|
| -- (in network byte order)
|
|||
|
| -- 2 3 month 1..12
|
|||
|
| -- 3 4 day 1..31
|
|||
|
| -- 4 5 hour 0..23
|
|||
|
| -- 5 6 minutes 0..59
|
|||
|
| -- 6 7 seconds 0..60
|
|||
|
| -- (use 60 for leap-second)
|
|||
|
| -- 7 8 deci-seconds 0..9
|
|||
|
| -- 8 9 direction from UTC "+" / "-"
|
|||
|
| -- (in ascii notation)
|
|||
|
| -- 9 10 hours from UTC 0..11
|
|||
|
| -- 10 11 minutes from UTC 0..59
|
|||
|
| --
|
|||
|
| -- Note that if only local time is known, then
|
|||
|
| -- timezone information (fields 8-10) is not present.
|
|||
|
|
|
|||
|
| MS-DOS records file dates and times as packed 16-bit values.
|
|||
|
| An MS-DOS date has the following format:
|
|||
|
| Bits Contents
|
|||
|
| ---- --------
|
|||
|
| 0-4 Days of the month (1-31).
|
|||
|
| 5-8 Months (1 = January, 2 = February, and so forth).
|
|||
|
| 9-15 Year offset from 1980 (add 1980 to get actual year).
|
|||
|
|
|
|||
|
| An MS-DOS time has the following format:
|
|||
|
| Bits Contents
|
|||
|
| ---- --------
|
|||
|
| 0-4 Seconds divided by 2.
|
|||
|
| 5-10 Minutes (0-59).
|
|||
|
| 11-15 Hours (0-23 on a 24-hour clock).
|
|||
|
|
|
|||
|
*/
|
|||
|
row->attrib_list[HRIN_DATE].attrib_type = CA_STRING;
|
|||
|
if ( (row->attrib_list[HRIN_DATE].u.string_value
|
|||
|
= octet_string = ( LPSTR ) malloc(8)) == NULL) {
|
|||
|
return ( FALSE ); /* out of memory */
|
|||
|
}
|
|||
|
for (i=0; i < 8; i += 1) octet_string[i] = '\0';
|
|||
|
|
|||
|
if (CoFileTimeToDosDateTime(ft, &msdos_date, &msdos_time) == TRUE) {
|
|||
|
SYSTEMTIME localInstTime;
|
|||
|
USHORT year;
|
|||
|
|
|||
|
UTCDosDateTimeToLocalSysTime(msdos_date, msdos_time, &localInstTime);
|
|||
|
|
|||
|
year = htons(localInstTime.wYear);
|
|||
|
octet_string[0] = (year & 0xFF);
|
|||
|
octet_string[1] = (year >> 8);
|
|||
|
octet_string[2] = (char)localInstTime.wMonth;
|
|||
|
octet_string[3] = (char)localInstTime.wDay;
|
|||
|
octet_string[4] = (char)localInstTime.wHour;
|
|||
|
octet_string[5] = (char)localInstTime.wMinute;
|
|||
|
octet_string[6] = (char)localInstTime.wSecond;
|
|||
|
octet_string[7] = (char)localInstTime.wMilliseconds / 10;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
| The other standard hrSWInstalled attributes are currently
|
|||
|
| "hardwired" in the Get functions.
|
|||
|
*/
|
|||
|
|
|||
|
/*
|
|||
|
| Now insert the filled-in CACHEROW structure into the
|
|||
|
| cache-list for the hrDeviceTable.
|
|||
|
*/
|
|||
|
if (AddTableRow(row->attrib_list[HRIN_INDEX].u.unumber_value, /* Index */
|
|||
|
row, /* Row */
|
|||
|
&hrSWInstalled_cache /* Cache */
|
|||
|
) == FALSE) {
|
|||
|
return ( FALSE ); /* Internal Logic Error! */
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
| Break from the Enumeration loop on the values, we've found
|
|||
|
| the one we want.
|
|||
|
*/
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
} /* for */
|
|||
|
|
|||
|
/* Add succeeded */
|
|||
|
return ( TRUE );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
#if defined(CACHE_DUMP)
|
|||
|
|
|||
|
|
|||
|
/* debug_print_hrswinstalled - Prints a Row from HrSWInstalled table */
|
|||
|
/* debug_print_hrswinstalled - Prints a Row from HrSWInstalled table */
|
|||
|
/* debug_print_hrswinstalled - Prints a Row from HrSWInstalled table */
|
|||
|
|
|||
|
static void
|
|||
|
debug_print_hrswinstalled(
|
|||
|
CACHEROW *row /* Row in hrSWInstalled 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:
|
|||
|
*/
|
|||
|
{
|
|||
|
UINT i;
|
|||
|
|
|||
|
if (row == NULL) {
|
|||
|
fprintf(OFILE, "=========================\n");
|
|||
|
fprintf(OFILE, "hrSWInstalled Table Cache\n");
|
|||
|
fprintf(OFILE, "=========================\n");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
fprintf(OFILE, "hrSWInstalledIndex . . . . %d\n",
|
|||
|
row->attrib_list[HRIN_INDEX].u.unumber_value);
|
|||
|
|
|||
|
fprintf(OFILE, "hrSWInstalledName . . . . %s\n",
|
|||
|
row->attrib_list[HRIN_NAME].u.string_value);
|
|||
|
|
|||
|
fprintf(OFILE, "hrSWInstalledDate . . . . ");
|
|||
|
for (i = 0; i < 8; i += 1) {
|
|||
|
fprintf(OFILE, "%2.2x ",row->attrib_list[HRIN_DATE].u.string_value[i]);
|
|||
|
}
|
|||
|
fprintf(OFILE, "\n");
|
|||
|
}
|
|||
|
#endif
|