You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1841 lines
59 KiB
1841 lines
59 KiB
/*
|
|
* HrSWRunEntry.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 HrSWRunEntry. 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 - 05/14/97 D. D. Burns Genned: Thu Nov 07 16:47:29 1996
|
|
*
|
|
*/
|
|
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <windows.h>
|
|
#include <malloc.h>
|
|
|
|
#include <snmp.h>
|
|
|
|
#include "mib.h"
|
|
#include "smint.h"
|
|
#include "hostmsmi.h"
|
|
#include "user.h" /* Developer supplied include file */
|
|
#include "HMCACHE.H" /* Cache-related definitions */
|
|
#include <string.h>
|
|
|
|
|
|
|
|
/*
|
|
|==============================================================================
|
|
| Function prototypes for this module.
|
|
|
|
|
*/
|
|
/* AddHrSWRunRow - Generate another Row Entry in HrSWRun/Perf Table cache */
|
|
static BOOL
|
|
AddHrSWRunRow(PSYSTEM_PROCESS_INFORMATION ProcessInfo);
|
|
|
|
/* FetchProcessParams - Fetch Path & Parameter String from Process Cmd line */
|
|
void
|
|
FetchProcessParams(
|
|
PSYSTEM_PROCESS_INFORMATION ProcessInfo, /* Process for parameters */
|
|
CHAR **path_str, /* Returned PATH string */
|
|
CHAR **params_str /* Returned Parameters string */
|
|
);
|
|
|
|
#if defined(CACHE_DUMP)
|
|
|
|
/* debug_print_hrswrun - Prints a Row from HrSWRun(Perf) Table */
|
|
static void
|
|
debug_print_hrswrun(
|
|
CACHEROW *row /* Row in hrSWRun(Perf) table */
|
|
);
|
|
#endif
|
|
|
|
|
|
/*
|
|
|==============================================================================
|
|
| Cache Refresh Time
|
|
|
|
|
| The cache for the hrSWRun and hrSWRunPerf tables is refreshed automatically
|
|
| when a request arrives --AND-- the cache is older than CACHE_MAX_AGE
|
|
| in seconds.
|
|
|
|
|
*/
|
|
static
|
|
LARGE_INTEGER cache_time; // 100ns Timestamp of cache (when last refreshed)
|
|
|
|
#define CACHE_MAX_AGE 120 // Maximum age in seconds
|
|
|
|
|
|
/*
|
|
|==============================================================================
|
|
| Create the list-head for the HrSWRun(Perf) Table cache.
|
|
|
|
|
| This cache contains info for both the hrSWRun and hrSWRunPerf tables.
|
|
| (This macro is defined in "HMCACHE.H").
|
|
|
|
|
| This is global so code for the hrSWRunPerf table ("HRSWPREN.C") can
|
|
| reference it.
|
|
*/
|
|
CACHEHEAD_INSTANCE(hrSWRunTable_cache, debug_print_hrswrun);
|
|
|
|
|
|
|
|
/*
|
|
|==============================================================================
|
|
| Operating System Index
|
|
|
|
|
| SNMP attribute "HrSWOSIndex" is the index into hrSWRun to the entry that
|
|
| primary operating system running on the host. This value is computed in
|
|
| this module in function "AddHrSWRunRow()" and stored here for reference
|
|
| by code in "HRSWRUN.C".
|
|
*/
|
|
ULONG SWOSIndex;
|
|
|
|
|
|
|
|
/*
|
|
* GetHrSWRunIndex
|
|
* A unique value for each piece of software running on the host. Wherever
|
|
* possible, this should be the system's native, unique id
|
|
*
|
|
* Gets the value for HrSWRunIndex.
|
|
*
|
|
* 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==================
|
|
| hrSWRunIndex
|
|
|
|
|
| ACCESS SYNTAX
|
|
| read-only INTEGER (1..2147483647)
|
|
|
|
|
| "A unique value for each piece of software running on the host. Wherever
|
|
| possible, this should be the system's native, unique identification number."
|
|
|
|
|
| DISCUSSION:
|
|
|
|
|
| By using performance monitoring information from the Registry (using code
|
|
| from "PVIEW") this attribute is given the value of the Process ID.
|
|
|
|
|
|============================================================================
|
|
| 1.3.6.1.2.1.25.4.2.1.1.<instance>
|
|
| | | | |
|
|
| | | | *-hrSWRunIndex
|
|
| | | *-hrSWRunEntry
|
|
| | *-hrSWRunTable
|
|
| *-hrSWRun
|
|
*/
|
|
|
|
UINT
|
|
GetHrSWRunIndex(
|
|
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, &hrSWRunTable_cache)) == NULL) {
|
|
return SNMP_ERRORSTATUS_GENERR;
|
|
}
|
|
|
|
*outvalue = row->attrib_list[HRSR_INDEX].u.number_value;
|
|
return SNMP_ERRORSTATUS_NOERROR ;
|
|
|
|
} /* end of GetHrSWRunIndex() */
|
|
|
|
|
|
/*
|
|
* GetHrSWRunName
|
|
* A textual description of this running piece of software, including the
|
|
* manufacturer, revision, and the name by which it is commo
|
|
*
|
|
* Gets the value for HrSWRunName.
|
|
*
|
|
* 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==================
|
|
| hrSWRunName
|
|
|
|
|
| ACCESS SYNTAX
|
|
| read-only InternationalDisplayString (SIZE (0..64))
|
|
|
|
|
| "A textual description of this running piece of software, including the
|
|
| manufacturer, revision, and the name by which it is commonly known. If this
|
|
| software was installed locally, this should be the same string as used in the
|
|
| corresponding hrSWInstalledName."
|
|
|
|
|
| DISCUSSION:
|
|
|
|
|
| By using performance monitoring information from the Registry (using code
|
|
| from "PVIEW") this attribute is given the value of the Process name.
|
|
|
|
|
|============================================================================
|
|
| 1.3.6.1.2.1.25.4.2.1.2.<instance>
|
|
| | | | |
|
|
| | | | *-hrSWRunName
|
|
| | | *-hrSWRunEntry
|
|
| | *-hrSWRunTable
|
|
| *-hrSWRun
|
|
*/
|
|
|
|
UINT
|
|
GetHrSWRunName(
|
|
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, &hrSWRunTable_cache)) == NULL) {
|
|
return SNMP_ERRORSTATUS_GENERR;
|
|
}
|
|
|
|
/* Return the name that was computed at cache-build time */
|
|
outvalue->length = strlen(row->attrib_list[HRSR_NAME].u.string_value);
|
|
outvalue->string = row->attrib_list[HRSR_NAME].u.string_value;
|
|
if (outvalue->length > 64) {
|
|
outvalue->length = 64; /* Truncate */
|
|
}
|
|
|
|
return SNMP_ERRORSTATUS_NOERROR ;
|
|
|
|
} /* end of GetHrSWRunName() */
|
|
|
|
|
|
/*
|
|
* GetHrSWRunID
|
|
* The product ID of this running piece of software.
|
|
*
|
|
* Gets the value for HrSWRunID.
|
|
*
|
|
* 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==================
|
|
| hrSWRunID
|
|
|
|
|
| ACCESS SYNTAX
|
|
| read-only ProductID
|
|
|
|
|
| "The product ID of this running piece of software."
|
|
|
|
|
| DISCUSSION:
|
|
|
|
|
| <POA-16> 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 process software to be used as the value for this attribute.
|
|
|
|
|
| RESOLVED >>>>>>>
|
|
| <POA-16> Returning an unknown Product ID is acceptable.
|
|
| RESOLVED >>>>>>>
|
|
|
|
|
|============================================================================
|
|
| 1.3.6.1.2.1.25.4.2.1.3.<instance>
|
|
| | | | |
|
|
| | | | *-hrSWRunID
|
|
| | | *-hrSWRunEntry
|
|
| | *-hrSWRunTable
|
|
| *-hrSWRun
|
|
*/
|
|
|
|
UINT
|
|
GetHrSWRunID(
|
|
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 GetHrSWRunID() */
|
|
|
|
|
|
/*
|
|
* GetHrSWRunPath
|
|
* A description of the location on long-term storage (e.g. a disk drive)
|
|
* from which this software was loaded.
|
|
*
|
|
* Gets the value for HrSWRunPath.
|
|
*
|
|
* 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==================
|
|
| hrSWRunPath
|
|
|
|
|
| ACCESS SYNTAX
|
|
| read-only InternationalDisplayString (SIZE(0..128))
|
|
|
|
|
| "A description of the location on long-term storage (e.g. a disk drive) from
|
|
| which this software was loaded."
|
|
|
|
|
| DISCUSSION:
|
|
|
|
|
| <POA-17> This information is not extracted by the sample PVIEW code from the
|
|
| performance monitoring statistics kept in the Registry. If this information
|
|
| is available from the Registry or some other source, I need to acquire the
|
|
| description of how to get it.
|
|
|
|
|
| RESOLVED >>>>>>>>
|
|
| <POA-17> This is obtained using PerfMon code pointers provided by Bob Watson.
|
|
| RESOLVED >>>>>>>>
|
|
|
|
|
|============================================================================
|
|
| 1.3.6.1.2.1.25.4.2.1.4.<instance>
|
|
| | | | |
|
|
| | | | *-hrSWRunPath
|
|
| | | *-hrSWRunEntry
|
|
| | *-hrSWRunTable
|
|
| *-hrSWRun
|
|
*/
|
|
|
|
UINT
|
|
GetHrSWRunPath(
|
|
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, &hrSWRunTable_cache)) == NULL) {
|
|
return SNMP_ERRORSTATUS_GENERR;
|
|
}
|
|
|
|
/*
|
|
| Return the Path string that was computed at cache-build time.
|
|
| NOTE: This string might be NULL.
|
|
*/
|
|
if (row->attrib_list[HRSR_PATH].u.string_value == NULL) {
|
|
outvalue->length = 0;
|
|
}
|
|
else {
|
|
outvalue->length = strlen(row->attrib_list[HRSR_PATH].u.string_value);
|
|
outvalue->string = row->attrib_list[HRSR_PATH].u.string_value;
|
|
if (outvalue->length > 128) {
|
|
outvalue->length = 128; /* Truncate */
|
|
}
|
|
}
|
|
|
|
return SNMP_ERRORSTATUS_NOERROR ;
|
|
|
|
} /* end of GetHrSWRunPath() */
|
|
|
|
/*
|
|
* GetHrSWRunParameters
|
|
*
|
|
* A description of the parameters supplied to this software when it was
|
|
* initially loaded."
|
|
*
|
|
* Gets the value for HrSWRunParameters.
|
|
*
|
|
* 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==================
|
|
| hrSWRunParameters
|
|
|
|
|
| ACCESS SYNTAX
|
|
| read-only InternationalDisplayString (SIZE(0..128))
|
|
|
|
|
| "A description of the parameters supplied to this software when it was
|
|
| initially loaded."
|
|
|
|
|
| DISCUSSION:
|
|
|
|
|
| <POA-18> This information is not extracted by the sample PVIEW code from the
|
|
| performance monitoring statistics kept in the Registry. If this information
|
|
| is available from the Registry or some other source, I need to acquire the
|
|
| description of how to get it.
|
|
|
|
|
| RESOLVED >>>>>>>>
|
|
| <POA-18> See discussion for "hrSWRunPath" above.
|
|
| RESOLVED >>>>>>>>
|
|
|
|
|
|============================================================================
|
|
| NOTE: This function edited in by hand, as it was not originally generated.
|
|
|============================================================================
|
|
| 1.3.6.1.2.1.25.4.2.1.5.<instance>
|
|
| | | | |
|
|
| | | | *-hrSWRunParameters
|
|
| | | *-hrSWRunEntry
|
|
| | *-hrSWRunTable
|
|
| *-hrSWRun
|
|
*/
|
|
|
|
UINT
|
|
GetHrSWRunParameters(
|
|
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, &hrSWRunTable_cache)) == NULL) {
|
|
return SNMP_ERRORSTATUS_GENERR;
|
|
}
|
|
|
|
/*
|
|
| Return the Parameter string that was computed at cache-build time.
|
|
| NOTE: This string might be NULL.
|
|
*/
|
|
if (row->attrib_list[HRSR_PARAM].u.string_value == NULL) {
|
|
outvalue->length = 0;
|
|
}
|
|
else {
|
|
outvalue->length = strlen(row->attrib_list[HRSR_PARAM].u.string_value);
|
|
outvalue->string = row->attrib_list[HRSR_PARAM].u.string_value;
|
|
if (outvalue->length > 128) {
|
|
outvalue->length = 128; /* Truncate */
|
|
}
|
|
}
|
|
|
|
return SNMP_ERRORSTATUS_NOERROR ;
|
|
|
|
} /* end of GetHrSWRunParameters() */
|
|
|
|
|
|
/*
|
|
* GetHrSWRunType
|
|
* The type of this software.
|
|
*
|
|
* Gets the value for HrSWRunType.
|
|
*
|
|
* 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==================
|
|
| hrSWRunType
|
|
|
|
|
| ACCESS SYNTAX
|
|
| read-only INTEGER {unknown(1),operatingSystem(2),deviceDriver(3),
|
|
| application(4)}
|
|
|
|
|
| "The type of this software."
|
|
|
|
|
| DISCUSSION:
|
|
|
|
|
| <POA-19> This information is not extracted by the sample PVIEW code from the
|
|
| performance monitoring statistics kept in the Registry. If this information
|
|
| is available from the Registry or some other source, I need to acquire the
|
|
| description of how to get it.
|
|
|
|
|
| >>>>>>>>
|
|
| <POA-19> I am not sure whether this information is included in the perfmon
|
|
| data block. I will investigate further.
|
|
| >>>>>>>>
|
|
|
|
|
|============================================================================
|
|
| 1.3.6.1.2.1.25.4.2.1.6.<instance>
|
|
| | | | |
|
|
| | | | *-hrSWRunType
|
|
| | | *-hrSWRunEntry
|
|
| | *-hrSWRunTable
|
|
| *-hrSWRun
|
|
*/
|
|
|
|
UINT
|
|
GetHrSWRunType(
|
|
OUT INTSWType *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, &hrSWRunTable_cache)) == NULL) {
|
|
return SNMP_ERRORSTATUS_GENERR;
|
|
}
|
|
|
|
*outvalue = row->attrib_list[HRSR_TYPE].u.number_value;
|
|
return SNMP_ERRORSTATUS_NOERROR ;
|
|
|
|
} /* end of GetHrSWRunType() */
|
|
|
|
|
|
/*
|
|
* GetHrSWRunStatus
|
|
* The status of this running piece of software. Setting this value to
|
|
* invalid(4) shall cause this software to stop running and be
|
|
*
|
|
* Gets the value for HrSWRunStatus.
|
|
*
|
|
* 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==================
|
|
| hrSWRunStatus
|
|
|
|
|
| ACCESS SYNTAX
|
|
| read-write INTEGER {
|
|
| running(1),
|
|
| runnable(2), -- waiting for resource (CPU, memory, IO)
|
|
| notRunnable(3), -- loaded but waiting for event
|
|
| invalid(4) -- not loaded
|
|
| }
|
|
|
|
|
| "The status of this running piece of software. Setting this value to
|
|
| invalid(4) shall cause this software to stop running and to be unloaded."
|
|
|
|
|
| DISCUSSION:
|
|
|
|
|
| <POA-20> For an SNMP "GET" on this attribute, this information is not extracted
|
|
| by the sample PVIEW code from the performance monitoring statistics kept in
|
|
| the Registry. If this information is available from the Registry or some
|
|
| other source, I need to acquire the description of how to get it.
|
|
|
|
|
| RESOLVED >>>>>>>
|
|
| <POA-20> I think running and notRunnable will be all that are applicable
|
|
| here (that latter being returned in situations which are currently labeled
|
|
| "not responding").
|
|
| RESOLVED >>>>>>>
|
|
|
|
|
|============================================================================
|
|
| 1.3.6.1.2.1.25.4.2.1.7.<instance>
|
|
| | | | |
|
|
| | | | *-hrSWRunStatus
|
|
| | | *-hrSWRunEntry
|
|
| | *-hrSWRunTable
|
|
| *-hrSWRun
|
|
*/
|
|
|
|
UINT
|
|
GetHrSWRunStatus(
|
|
OUT INThrSWRunStatus *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, &hrSWRunTable_cache)) == NULL) {
|
|
return SNMP_ERRORSTATUS_GENERR;
|
|
}
|
|
|
|
*outvalue = row->attrib_list[HRSR_STATUS].u.number_value;
|
|
return SNMP_ERRORSTATUS_NOERROR ;
|
|
|
|
} /* end of GetHrSWRunStatus() */
|
|
|
|
|
|
/*
|
|
* SetHrSWRunStatus
|
|
* The status of this running piece of software. Setting this value to
|
|
* invalid(4) shall cause this software to stop running and be
|
|
*
|
|
* Sets the HrSWRunStatus value.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* invalue address of value to set the variable
|
|
* outvalue address to return the set variable value
|
|
* access Reserved for future security use
|
|
* instance address of instance name as ordered native
|
|
* data type(s)
|
|
*
|
|
* Return Codes:
|
|
*
|
|
* Standard PDU error codes.
|
|
*
|
|
* SNMP_ERRORSTATUS_NOERROR Successful get
|
|
* SNMP_ERRORSTATUS_BADVALUE Set value not in range
|
|
* SNMP_ERRORSTATUS_GENERR Catch-all failure code
|
|
* mibtset.ntc v0.10
|
|
*/
|
|
|
|
UINT
|
|
SetHrSWRunStatus(
|
|
IN INThrSWRunStatus *invalue ,
|
|
OUT INThrSWRunStatus *outvalue ,
|
|
IN Access_Credential *access ,
|
|
IN InstanceName *instance )
|
|
|
|
{
|
|
|
|
return SNMP_ERRORSTATUS_NOSUCHNAME ;
|
|
|
|
} /* end of SetHrSWRunStatus() */
|
|
|
|
|
|
/*
|
|
* HrSWRunEntryFindInstance
|
|
*
|
|
* 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
|
|
HrSWRunEntryFindInstance( 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 <= HRSWRUNENTRY_VAR_INDEX )
|
|
// No instance was specified
|
|
return SNMP_ERRORSTATUS_NOSUCHNAME ;
|
|
else if ( FullOid->idLength != HRSWRUNENTRY_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[ HRSWRUNENTRY_VAR_INDEX ] ;
|
|
|
|
/*
|
|
| Check for age-out and possibly refresh the entire cache for the
|
|
| hrSWRun table before we check to see if the instance is there.
|
|
*/
|
|
if (hrSWRunCache_Refresh() == FALSE) {
|
|
return SNMP_ERRORSTATUS_GENERR;
|
|
}
|
|
|
|
/*
|
|
| For hrSWRun, the instance arc(s) is a single arc, and it must
|
|
| correctly select an entry in the hrSWRun Table cache.
|
|
| Check that here.
|
|
*/
|
|
if ( FindTableRow(tmp_instance, &hrSWRunTable_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 HrSWRunEntryFindInstance() */
|
|
|
|
|
|
|
|
/*
|
|
* HrSWRunEntryFindNextInstance
|
|
*
|
|
* 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
|
|
HrSWRunEntryFindNextInstance( 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 <= HRSWRUNENTRY_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[ HRSWRUNENTRY_VAR_INDEX ] ;
|
|
}
|
|
|
|
/*
|
|
| Check for age-out and possibly refresh the entire cache for the
|
|
| hrSWRun table before we check to see if the instance is there.
|
|
*/
|
|
if (hrSWRunCache_Refresh() == FALSE) {
|
|
return SNMP_ERRORSTATUS_GENERR;
|
|
}
|
|
|
|
/* Now go off and try to find the next instance in the table */
|
|
if ((row = FindNextTableRow(tmp_instance, &hrSWRunTable_cache)) == NULL) {
|
|
return SNMP_ERRORSTATUS_NOSUCHNAME ;
|
|
}
|
|
|
|
instance->ids[ 0 ] = row->index ;
|
|
instance->idLength = 1 ;
|
|
|
|
return SNMP_ERRORSTATUS_NOERROR ;
|
|
|
|
} /* end of HrSWRunEntryFindNextInstance() */
|
|
|
|
|
|
|
|
/*
|
|
* HrSWRunEntryConvertInstance
|
|
*
|
|
* 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
|
|
HrSWRunEntryConvertInstance( 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 HrSWRunEntryConvertInstance() */
|
|
|
|
|
|
|
|
|
|
/*
|
|
* HrSWRunEntryFreeInstance
|
|
*
|
|
* 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
|
|
HrSWRunEntryFreeInstance( IN OUT InstanceName *instance )
|
|
{
|
|
|
|
//
|
|
// Developer supplied code to free native representation of instance name goes here.
|
|
//
|
|
|
|
} /* end of HrSWRunEntryFreeInstance() */
|
|
|
|
/*
|
|
| End of Generated Code
|
|
*/
|
|
|
|
/* Gen_HrSWRun_Cache - Generate a initial cache for HrSWRun(Perf) Table */
|
|
/* Gen_HrSWRun_Cache - Generate a initial cache for HrSWRun(Perf) Table */
|
|
/* Gen_HrSWRun_Cache - Generate a initial cache for HrSWRun(Perf) Table */
|
|
|
|
BOOL
|
|
Gen_HrSWRun_Cache(
|
|
void
|
|
)
|
|
|
|
/*
|
|
| EXPLICIT INPUTS:
|
|
|
|
|
| None.
|
|
|
|
|
| IMPLICIT INPUTS:
|
|
|
|
|
| The module-local head of the cache for the HrSWRun table,
|
|
| "hrSWRunTable_cache".
|
|
|
|
|
| OUTPUTS:
|
|
|
|
|
| On Success:
|
|
| Function returns TRUE indicating that the cache has been fully
|
|
| populated with all "static" cache-able values. This function populates
|
|
| the hrSWRun Table cache, but this cache also includes the two
|
|
| attributes for the hrSWRunPerf Table. So in effect, one cache serves
|
|
| two tables, but the hrSWRunPerf table is a "one-to-one" extension
|
|
| of hrSWRun table.. that is a row in hrSWRun always has a corresponding
|
|
| "two-entry" row in hrSWRunPerf.
|
|
|
|
|
| On any Failure:
|
|
| Function returns FALSE (indicating "not enough storage").
|
|
|
|
|
| THE BIG PICTURE:
|
|
|
|
|
| At subagent startup time, the cache for each table in the MIB is
|
|
| populated with rows for each row in the table. This function is
|
|
| invoked by the start-up code in "UserMibInit()" ("MIB.C") to
|
|
| populate the cache for the HrSWRun table (which also serves the
|
|
| hrSWRunPerf Table).
|
|
|
|
|
| It is also re-entered whenever a request for information from this
|
|
| cache comes in and the cache is older than a certain age (symbol
|
|
| "CACHE_MAX_AGE" defined at the beginning of this module). In this
|
|
| case the cache is rebuilt, and in this way this function is different
|
|
| from all the other "Gen_*_Cache()" functions which only build their
|
|
| caches once (in the initial release).
|
|
|
|
|
|
|
|
| OTHER THINGS TO KNOW:
|
|
|
|
|
| There is one of these function for every table that has a cache.
|
|
| Each cachehead is found in the respective table's source file.
|
|
|
|
|
| The strategy on getting running software enumerated revolves around
|
|
| NtQuerySystemInformation(SystemProcessInformation...) invocation.
|
|
|
|
|
| Once we have a list of processes, additional information (such as
|
|
| the parameters on the command-line) are fetched by opening the
|
|
| process (if possible) and reading process memory.
|
|
|
|
|
| Note that unlike the other cache's in the initial release, this cache
|
|
| for hrSWRun and hrSWRunPerf is updated before it is read if it is
|
|
| older than a specified period of time (set by #define at the beginning
|
|
| of this file).
|
|
|
|
|
|============================================================================
|
|
| 1.3.6.1.2.1.25.4.1.0
|
|
| | |
|
|
| | *-hrSWOSIndex
|
|
| *-hrSWRun
|
|
|
|
|
| 1.3.6.1.2.1.25.4.2.1..
|
|
| | | |
|
|
| | | *-hrSWRunEntry
|
|
| | *-hrSWRunTable
|
|
| *-hrSWRun
|
|
*/
|
|
#define LARGE_BUFFER_SIZE (4096*8)
|
|
#define INCREMENT_BUFFER_SIZE (4096*2)
|
|
{
|
|
DWORD ProcessBufSize = LARGE_BUFFER_SIZE; /* Initial ProcessBuffer size */
|
|
LPBYTE pProcessBuffer = NULL; /* Re-used and re-expanded as needed */
|
|
|
|
PSYSTEM_PROCESS_INFORMATION
|
|
ProcessInfo; /* --> Next process to process */
|
|
ULONG ProcessBufferOffset=0; /* Accumulating offset cell */
|
|
NTSTATUS ntstatus; /* Generic return status */
|
|
DWORD dwReturnedBufferSize; /* From NtQuerySystemInformation() */
|
|
|
|
|
|
/*
|
|
| Blow away any old copy of the cache
|
|
*/
|
|
DestroyTable( &hrSWRunTable_cache );
|
|
|
|
|
|
/*
|
|
| Grab an initial buffer for Process Information
|
|
*/
|
|
if ((pProcessBuffer = malloc ( ProcessBufSize )) == NULL) {
|
|
return ( FALSE );
|
|
}
|
|
|
|
|
|
/*
|
|
| Go for a (new/refreshed) buffer of current Process Info
|
|
*/
|
|
while( (ntstatus = NtQuerySystemInformation(
|
|
SystemProcessInformation,
|
|
pProcessBuffer,
|
|
ProcessBufSize,
|
|
&dwReturnedBufferSize
|
|
)
|
|
) == STATUS_INFO_LENGTH_MISMATCH )
|
|
{
|
|
|
|
LPBYTE pNewProcessBuffer = NULL; // For use on realloc
|
|
|
|
/* expand buffer & retry */
|
|
ProcessBufSize += INCREMENT_BUFFER_SIZE;
|
|
|
|
if ( !(pNewProcessBuffer = realloc(pProcessBuffer,ProcessBufSize)) )
|
|
{
|
|
// If realloc failed and left us with the old buffer, free it
|
|
if (pProcessBuffer != NULL)
|
|
{
|
|
free(pProcessBuffer);
|
|
}
|
|
return (FALSE); // Out of memory
|
|
}
|
|
else
|
|
{
|
|
// Successful Realloc
|
|
pProcessBuffer = pNewProcessBuffer;
|
|
}
|
|
}
|
|
|
|
/*
|
|
| Freshen the time on the cache
|
|
|
|
|
| Get the current system-time in 100ns intervals . . . */
|
|
ntstatus = NtQuerySystemTime (&cache_time);
|
|
if (ntstatus != STATUS_SUCCESS)
|
|
{
|
|
free( pProcessBuffer );
|
|
return ( FALSE );
|
|
}
|
|
|
|
|
|
/*
|
|
| Loop over each instance of Process Information in the ProcessBuffer
|
|
| and build a row in the cache for hrSWRun and hrSWRunPerf tables.
|
|
*/
|
|
for (ProcessInfo = (PSYSTEM_PROCESS_INFORMATION) pProcessBuffer;
|
|
; /* Exit check below */
|
|
ProcessBufferOffset += ProcessInfo->NextEntryOffset,
|
|
ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)
|
|
&pProcessBuffer[ProcessBufferOffset]
|
|
) {
|
|
|
|
/* Add a Row to the cache */
|
|
if (AddHrSWRunRow(ProcessInfo) != TRUE) {
|
|
if (pProcessBuffer != NULL) {
|
|
free(pProcessBuffer);
|
|
}
|
|
return ( FALSE ); // Out of memory
|
|
}
|
|
|
|
/* If this is the last process, bag it */
|
|
if (ProcessInfo->NextEntryOffset == 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
#if defined(CACHE_DUMP)
|
|
PrintCache(&hrSWRunTable_cache);
|
|
#endif
|
|
|
|
if (pProcessBuffer != NULL) {
|
|
free(pProcessBuffer);
|
|
}
|
|
|
|
/* Cache (re)-build successful */
|
|
return ( TRUE );
|
|
}
|
|
|
|
/* AddHrSWRunRow - Generate another Row Entry in HrSWRun/Perf Table */
|
|
/* AddHrSWRunRow - Generate another Row Entry in HrSWRun/Perf Table */
|
|
/* AddHrSWRunRow - Generate another Row Entry in HrSWRun/Perf Table */
|
|
|
|
static BOOL
|
|
AddHrSWRunRow(
|
|
|
|
PSYSTEM_PROCESS_INFORMATION ProcessInfo /* --> Next process to process */
|
|
|
|
)
|
|
|
|
/*
|
|
| EXPLICIT INPUTS:
|
|
|
|
|
| "ProcessInfo" points to the next process (as described by a
|
|
| SYSTEM_PROCESS_INFORMATION structure) for which a row is to be
|
|
| inserted into the HrSWRun(Perf) table cache.
|
|
|
|
|
| IMPLICIT INPUTS:
|
|
|
|
|
| The module-local head of the cache for the HrDevice table,
|
|
| "hrSWRunTable_cache".
|
|
|
|
|
| OUTPUTS:
|
|
|
|
|
| On Success:
|
|
| Function creates a new row entry populated with all "static" cache-able
|
|
| values for HrSWRun(Perf) table and returns TRUE. Note that if the
|
|
| process is the "System Process", the row entry index is stored in
|
|
| module cell "SWOSIndex" for reference by code in "HRSWRUN.C".
|
|
|
|
|
| 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 cache-build code in "Gen_HrSWRun_Cache()" above.
|
|
|
|
|
| OTHER THINGS TO KNOW:
|
|
|
|
|
| The cache being (re)built by this function serves two tables, hrSWRun
|
|
| and hrSWRunPerf.
|
|
|
|
|
| In general, we use the Process's "ProcessID" as the index in the
|
|
| hrSWRun(Perf) table. However special handling is done for the Idle
|
|
| Process because it's Process ID is zero. We convert it to "1" to meet
|
|
| the SNMP requirement that indexes be greater than zero. We note that
|
|
| as of this writing, no process id of 1 is seen in build 1515 (the "System"
|
|
| process has a processID of 2).
|
|
|
|
|
| The "type" of software can be unknown(1), operatingSystem(2),
|
|
| deviceDriver(3) and application(4). We only detect the Idle and System
|
|
| processes (by their names) as "operatingSystem(2)", everything else
|
|
| is presumed "application(4)".
|
|
|
|
|
| As for "status", it can be running(1), runnable(2), notRunnable(3) or
|
|
| invalid(4). If the number of threads is greater than 0, it is presumed
|
|
| "running(1)", otherwise "invalid(4)".
|
|
*/
|
|
#define ANSI_PNAME_LEN 256
|
|
{
|
|
ANSI_STRING pname; /* ANSI version of UNICODE process name */
|
|
CHAR pbuf[ANSI_PNAME_LEN+1]; /* Buffer for "pname" */
|
|
CHAR *pname_str; /* Pointer to our final process name */
|
|
CHAR *path_str=NULL; /* Pointer to our Path name */
|
|
CHAR *params=NULL; /* Pointer to any parameters fnd on cmdline*/
|
|
UINT type; /* SNMP code for type of software */
|
|
UINT status; /* SNMP code for the status of software */
|
|
CACHEROW *row; /* --> Cache structure for row-being built */
|
|
NTSTATUS ntstatus; /* Generic return status */
|
|
|
|
/*
|
|
| OK, the caller wants another row in the table, get a row-entry created.
|
|
*/
|
|
if ((row = CreateTableRow( HRSR_ATTRIB_COUNT ) ) == NULL) {
|
|
return ( FALSE ); // Out of memory
|
|
}
|
|
|
|
/*
|
|
| Set up the standard-hrSWRun(Perf) attributes in the new row
|
|
*/
|
|
|
|
type = 4; /* Presume "application(4)" type software */
|
|
|
|
if (ProcessInfo->NumberOfThreads > 0) {
|
|
status = 1; /* Presume "running(1)" for software status */
|
|
}
|
|
else {
|
|
status = 4; /* "invalid(4)", process on the way out */
|
|
}
|
|
|
|
/* =========== HrSWRunIndex ==========*/
|
|
row->attrib_list[HRSR_INDEX].attrib_type = CA_NUMBER;
|
|
row->attrib_list[HRSR_INDEX].u.unumber_value =
|
|
HandleToUlong(ProcessInfo->UniqueProcessId) ;
|
|
|
|
/* Special check for system idle process, roll it from 0 to 1 */
|
|
if (ProcessInfo->UniqueProcessId == 0) {
|
|
row->attrib_list[HRSR_INDEX].u.unumber_value = 1;
|
|
}
|
|
|
|
|
|
|
|
/* =========== HrSWRunName ==========*/
|
|
row->attrib_list[HRSR_NAME].attrib_type = CA_STRING;
|
|
|
|
/* If we actually have a process name for this process . . . */
|
|
if (ProcessInfo->ImageName.Buffer != NULL) {
|
|
|
|
/* Prep the STRING structure */
|
|
pname.Buffer = pbuf;
|
|
pname.MaximumLength = ANSI_PNAME_LEN;
|
|
|
|
/* Convert from Unicode */
|
|
ntstatus = RtlUnicodeStringToAnsiString(&pname, // Target string
|
|
(PUNICODE_STRING)&ProcessInfo->ImageName,//Src
|
|
FALSE); // = Don't Allocate buf
|
|
|
|
if (ntstatus != STATUS_SUCCESS)
|
|
{
|
|
DestroyTableRow(row);
|
|
return ( FALSE );
|
|
}
|
|
/*
|
|
| Here we parse not only the process name but any path that may be
|
|
| prepended to it. (We make no attempt to eliminate any ".EXE" that
|
|
| may be on the end of the image name).
|
|
|
|
|
| NOTE: If you are going to rip off this code, be aware that as-of
|
|
| build 1515, we NEVER seem to get an image name that has the
|
|
| path prepended on the front... so most of this code to skip
|
|
| the possibly-present path is almost certainly superfluous.
|
|
*/
|
|
|
|
/* Try to "backup" until we hit any "\" */
|
|
if ( (pname_str = strrchr(pname.Buffer,'\\')) != NULL) {
|
|
pname_str++; /* Pop to first char after "\" */
|
|
}
|
|
else {
|
|
pname_str = pname.Buffer; /* Use entire string, no "\" found */
|
|
|
|
/*
|
|
| A piece of software with no path means it could be the "System"
|
|
| process. Check for that here.
|
|
*/
|
|
if (strcmp(pname_str, "System") == 0) {
|
|
type = 2; /* Mark the software as "operatingSystem(2)" type */
|
|
|
|
/*
|
|
| We're processing the main System Process, so record it's index
|
|
| in module-level cell for reference from "HRSWRUN.C".
|
|
*/
|
|
SWOSIndex = row->attrib_list[HRSR_INDEX].u.unumber_value;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
/* The system idle process has no name */
|
|
pname_str = "System Idle Process";
|
|
type = 2; /* Mark the software as "operatingSystem(2)" type */
|
|
}
|
|
|
|
/* Allocate cache storage and copy the process name to it */
|
|
if ( (row->attrib_list[HRSR_NAME].u.string_value
|
|
= ( LPSTR ) malloc(strlen(pname_str) + 1)) == NULL) {
|
|
DestroyTableRow(row);
|
|
return ( FALSE ); /* out of memory */
|
|
}
|
|
strcpy(row->attrib_list[HRSR_NAME].u.string_value, pname_str);
|
|
|
|
/*
|
|
| We bother to do the overhead of trying to extract path & parameters from
|
|
| the command-line that started the process by reading process memory
|
|
| only if the type of the software is "application(4)" and status is
|
|
| "running(1)".
|
|
*/
|
|
if (status == 1 && type == 4) { /* If it is a runnable application . . . */
|
|
|
|
FetchProcessParams(ProcessInfo, &path_str, ¶ms);
|
|
}
|
|
|
|
|
|
/* =========== HrSWRunPath ==========*/
|
|
row->attrib_list[HRSR_PATH].attrib_type = CA_STRING;
|
|
row->attrib_list[HRSR_PATH].u.string_value = NULL;
|
|
|
|
/* If we did detect a path . . . */
|
|
if (path_str != NULL) {
|
|
|
|
/* Allocate cache storage and copy the path string to it */
|
|
if ( (row->attrib_list[HRSR_PATH].u.string_value
|
|
= ( LPSTR ) malloc(strlen(path_str) + 1)) == NULL) {
|
|
DestroyTableRow(row);
|
|
return ( FALSE ); /* out of memory */
|
|
}
|
|
strcpy(row->attrib_list[HRSR_PATH].u.string_value, path_str);
|
|
}
|
|
|
|
|
|
/* =========== HrSWRunParameters ==========*/
|
|
row->attrib_list[HRSR_PARAM].attrib_type = CA_STRING;
|
|
row->attrib_list[HRSR_PARAM].u.string_value = NULL; /* In case of none */
|
|
|
|
/* If we did find parameters . . . */
|
|
if (params != NULL) {
|
|
|
|
/* Allocate cache storage and copy the parameter string to it */
|
|
if ( (row->attrib_list[HRSR_PARAM].u.string_value
|
|
= ( LPSTR ) malloc(strlen(params) + 1)) == NULL) {
|
|
DestroyTableRow(row);
|
|
return ( FALSE ); /* out of memory */
|
|
}
|
|
strcpy(row->attrib_list[HRSR_PARAM].u.string_value, params);
|
|
}
|
|
|
|
|
|
/* =========== HrSWRunType ========== */
|
|
row->attrib_list[HRSR_TYPE].attrib_type = CA_NUMBER;
|
|
row->attrib_list[HRSR_TYPE].u.unumber_value = type;
|
|
|
|
|
|
/* =========== HrSWRunStatus ========== */
|
|
row->attrib_list[HRSR_STATUS].attrib_type = CA_NUMBER;
|
|
row->attrib_list[HRSR_STATUS].u.unumber_value = status;
|
|
|
|
/*
|
|
| For hrSWRunPerf Table:
|
|
*/
|
|
|
|
/* =========== HrSWRunPerfCPU ==========
|
|
| UserTime + KernelTime are in 100ns (1/10th of a millionth of a second)
|
|
| units and HrSWRunPerfCPU is supposed to be in 1/100th of a second units.
|
|
|
|
|
| So .01 - second intervals
|
|
| is .010 000 0 - 100nanoseconds intervals,
|
|
|
|
|
| so dividing 100ns intervals by 100,000 gives centi-seconds.
|
|
*/
|
|
|
|
row->attrib_list[HRSP_CPU].attrib_type = CA_NUMBER;
|
|
row->attrib_list[HRSP_CPU].u.unumber_value = (ULONG)
|
|
((ProcessInfo->UserTime.QuadPart + ProcessInfo->KernelTime.QuadPart) / 100000);
|
|
|
|
|
|
/* =========== HrSWRunPerfMem ========== */
|
|
row->attrib_list[HRSP_MEM].attrib_type = CA_NUMBER;
|
|
row->attrib_list[HRSP_MEM].u.unumber_value =
|
|
(ULONG)(ProcessInfo->WorkingSetSize / 1024);
|
|
|
|
|
|
/*
|
|
| Now insert the filled-in CACHEROW structure into the
|
|
| cache-list for the hrSWRun(Perf) Table.
|
|
*/
|
|
if (AddTableRow(row->attrib_list[HRSR_INDEX].u.unumber_value, /* Index */
|
|
row, /* Row */
|
|
&hrSWRunTable_cache /* Cache */
|
|
) == FALSE) {
|
|
DestroyTableRow(row);
|
|
return ( FALSE ); /* Internal Logic Error! */
|
|
}
|
|
|
|
return ( TRUE );
|
|
}
|
|
|
|
/* hrSWRunCache_Refresh - hrSWRun(Perf) Cache Refresh-Check Routine */
|
|
/* hrSWRunCache_Refresh - hrSWRun(Perf) Cache Refresh-Check Routine */
|
|
/* hrSWRunCache_Refresh - hrSWRun(Perf) Cache Refresh-Check Routine */
|
|
|
|
BOOL
|
|
hrSWRunCache_Refresh(
|
|
void
|
|
)
|
|
|
|
/*
|
|
| EXPLICIT INPUTS:
|
|
|
|
|
| None.
|
|
|
|
|
| IMPLICIT INPUTS:
|
|
|
|
|
| The "hrSWRunTable_cache" CACHEHEAD structure and the time when
|
|
| it was last refreshed in module-local cell "cache_time".
|
|
|
|
|
| OUTPUTS:
|
|
|
|
|
| On Success/Failure:
|
|
| The function returns TRUE. Only if the cache-time has aged-out
|
|
| is the cache actually rebuilt.
|
|
|
|
|
| On any Failure:
|
|
| If during a rebuild there is an error, this function returns FALSE.
|
|
| The state of the cache is indeterminate.
|
|
|
|
|
| THE BIG PICTURE:
|
|
|
|
|
| This function is invoked before any reference is made to any SNMP
|
|
| variable in the hrSWRun or hrSWRunPerf table. It checks to see
|
|
| if the cache needs to be rebuilt based on the last time it was built.
|
|
|
|
|
| The calls to this function are strategically located in the
|
|
| "FindInstance" and "FindNextInstance" functions in "HRSWRUNE.C"
|
|
| (this module) and "HRSWPREN.C" (for the RunPerf table) as well
|
|
| as in "HRSWRUN.C" for the stand-alone attribute "hrSWOSIndex".
|
|
|
|
|
| OTHER THINGS TO KNOW:
|
|
|
|
|
*/
|
|
{
|
|
LARGE_INTEGER now_time; /* Current System time in 100 ns ticks */
|
|
|
|
|
|
/* Get the current time in 100 ns ticks*/
|
|
if (NtQuerySystemTime (&now_time) != STATUS_SUCCESS )
|
|
return FALSE;
|
|
|
|
/* If the cache is older than the maximum allowed time (in ticks) . . . */
|
|
if ( (now_time.QuadPart - cache_time.QuadPart) > (CACHE_MAX_AGE * 10000000) ){
|
|
return ( Gen_HrSWRun_Cache() );
|
|
}
|
|
|
|
return ( TRUE ); /* No Error (because no refresh) */
|
|
}
|
|
|
|
/* FetchProcessParams - Fetch Path & Parameter String from Process Cmd line */
|
|
/* FetchProcessParams - Fetch Path & Parameter String from Process Cmd line */
|
|
/* FetchProcessParams - Fetch Path & Parameter String from Process Cmd line */
|
|
|
|
void
|
|
FetchProcessParams(
|
|
|
|
PSYSTEM_PROCESS_INFORMATION ProcessInfo, /* Process for parameters */
|
|
CHAR **path_str, /* Returned PATH string */
|
|
CHAR **params_str /* Returned Parameters string */
|
|
)
|
|
/*
|
|
| EXPLICIT INPUTS:
|
|
|
|
|
| "ProcessInfo" points to the process (as described by a
|
|
| SYSTEM_PROCESS_INFORMATION structure) for which the path & parameters
|
|
| (from the command-line) are desired.
|
|
|
|
|
| "path_str" is the address of a pointer to be set to any "path" string.
|
|
| "params" is the address of a pointer to be set to any "parameters"
|
|
| string.
|
|
|
|
|
| IMPLICIT INPUTS:
|
|
|
|
|
| None.
|
|
|
|
|
| OUTPUTS:
|
|
|
|
|
| On Success:
|
|
| Function returns pointers to a static buffer containing the
|
|
| path & parameters section of the command line. There may be nothing
|
|
| in the buffer (ie just the null-termination).
|
|
|
|
|
| On any Failure:
|
|
| Function returns NULLS indicating a problem was encountered
|
|
| attempting to obtain the command-line image from which the
|
|
| path & parameter portion is to be extracted, or indicating that
|
|
| one or both were not present.
|
|
|
|
|
| THE BIG PICTURE:
|
|
|
|
|
| Called from "AddHrSWRunRow()" above, this is a helper function
|
|
| that serves to isolate the code lifted from "TLIST" from
|
|
| the rest of the subagent.
|
|
|
|
|
| OTHER THINGS TO KNOW:
|
|
|
|
|
| The black magic here was lifted from sections of "TLIST".
|
|
*/
|
|
{
|
|
HANDLE hProcess;
|
|
PEB Peb;
|
|
NTSTATUS Status;
|
|
PROCESS_BASIC_INFORMATION BasicInfo;
|
|
WCHAR szT[(MAX_PATH * 2)+1];
|
|
UNICODE_STRING u_param;
|
|
RTL_USER_PROCESS_PARAMETERS ProcessParameters;
|
|
|
|
#define ANSI_PARAM_LEN (MAX_PATH * 2)
|
|
ANSI_STRING param; /* ANSI version of UNICODE command line */
|
|
static
|
|
CHAR pbuf[ANSI_PARAM_LEN+1]; /* Buffer for "parameters" */
|
|
CHAR *param_str; /* Pointer to our final parameter string */
|
|
SIZE_T dwbytesret; /* Count of bytes read from process memory */
|
|
|
|
|
|
pbuf[ANSI_PARAM_LEN] = 0;
|
|
szT[MAX_PATH * 2] = 0;
|
|
|
|
/* Presume failure/nothing obtained */
|
|
*path_str = NULL;
|
|
*params_str = NULL;
|
|
|
|
/* get a handle to the process */
|
|
hProcess = OpenProcess(PROCESS_VM_READ|PROCESS_QUERY_INFORMATION,
|
|
FALSE,
|
|
HandleToUlong(ProcessInfo->UniqueProcessId));
|
|
if (!hProcess) {
|
|
return;
|
|
}
|
|
|
|
|
|
Status = NtQueryInformationProcess(hProcess, ProcessBasicInformation,
|
|
&BasicInfo, sizeof(BasicInfo), NULL);
|
|
if (!NT_SUCCESS(Status)) {
|
|
CloseHandle(hProcess);
|
|
return;
|
|
}
|
|
|
|
|
|
// get the PEB
|
|
if (ReadProcessMemory(hProcess, BasicInfo.PebBaseAddress, &Peb,
|
|
sizeof(PEB), NULL)) {
|
|
|
|
// get the processparameters
|
|
if (ReadProcessMemory(hProcess, Peb.ProcessParameters,
|
|
&ProcessParameters, sizeof(ProcessParameters), NULL)) {
|
|
|
|
// get cmdline
|
|
if (ReadProcessMemory(hProcess,
|
|
ProcessParameters.CommandLine.Buffer,
|
|
szT,
|
|
sizeof(szT)-2, // minus the last 2 bytes
|
|
&dwbytesret
|
|
)
|
|
) {
|
|
|
|
CHAR *scanner; /* Used for parsing the command-line */
|
|
|
|
/* Prep the STRING structure */
|
|
param.Buffer = pbuf;
|
|
param.MaximumLength = ANSI_PARAM_LEN;
|
|
u_param.Length = (USHORT) ((wcslen(szT) + 1) * 2); // bytes incl. NULL
|
|
u_param.Buffer = szT;
|
|
|
|
/* Convert from Unicode */
|
|
Status = RtlUnicodeStringToAnsiString(¶m, // Target string
|
|
&u_param, /* Src */
|
|
FALSE); /* = Don't Allocate buf */
|
|
|
|
if (Status != STATUS_SUCCESS)
|
|
{
|
|
CloseHandle(hProcess);
|
|
return;
|
|
}
|
|
|
|
|
|
// Firstly, we need to check for command line of the form:
|
|
// "c:\program files\blah\blah" -parameter1 -parameter2
|
|
// "C:\Program Files\Internet Explorer\IEXPLORE.EXE"
|
|
// but not:
|
|
// C:\WINDOWS\system32\mmc.exe "C:\WINDOWS\system32\tsmmc.msc" /s
|
|
if ( pbuf[0] == '\"')
|
|
|
|
{
|
|
// get first '\"', see if there is another one
|
|
|
|
if ((scanner = strchr(pbuf+1, '\"')) != NULL)
|
|
{
|
|
// found the 2nd terminating '\"'
|
|
*params_str = (scanner + 1);
|
|
*scanner = 0; // Terminate the base string
|
|
// Path
|
|
if ((scanner = strrchr(pbuf, '\\')) != NULL)
|
|
{
|
|
// Terminate the path
|
|
*(scanner+1) = 0;
|
|
|
|
// Return start of buffer as path
|
|
*path_str = pbuf+1;
|
|
}
|
|
else
|
|
{
|
|
// No path
|
|
*path_str = NULL;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
/*
|
|
| OK, we can have the following situations:
|
|
|
|
|
| 1) "\system\system32\smss.exe -parameter1 -parameter2"
|
|
| --------path----- -------parameters------
|
|
|
|
|
| 2) "\system\system32\smss.exe"
|
|
| --------path-----
|
|
|
|
|
| 3) "smss.exe -parameter1 -parameter2"
|
|
| -------parameters------
|
|
|
|
|
| and we want to handle this by returning "path" and "parameter"
|
|
| as shown, where:
|
|
|
|
|
| 1) both path and parameters are present
|
|
| 2) only path is present
|
|
| 3) only parameters are present
|
|
|
|
|
| We do this:
|
|
|
|
|
| - Scan forward for a blank.
|
|
| If we get one:
|
|
| + return the address following it as "parameters"
|
|
| + set the blank to a null byte (cutting off parameters)
|
|
| If not:
|
|
| + return NULL as "parameters"
|
|
|
|
|
| ----Parameters are done.
|
|
|
|
|
| - Perform a reverse search for "\" on whatever is now in the
|
|
| buffer
|
|
| If we find a "\":
|
|
| + Step forward one character and turn it into a null
|
|
| byte (turning buffer into string containing path).
|
|
| + Return the buffer address as "path"
|
|
| If not:
|
|
| + return NULL as "path"
|
|
*/
|
|
/* Parameter */
|
|
{
|
|
if ((scanner = strchr(pbuf, ' ')) != NULL) {
|
|
|
|
/* Return address of char after blank as start of parameters */
|
|
*params_str = (scanner + 1);
|
|
*scanner = '\0'; /* Terminate base string */
|
|
}
|
|
else {
|
|
/* No parameters */
|
|
*params_str = NULL;
|
|
}
|
|
|
|
/* Path */
|
|
if ((scanner = strrchr(pbuf, '\\')) != NULL) {
|
|
/* Terminate the path */
|
|
*(scanner+1) = '\0';
|
|
|
|
/* Return start of buffer as path */
|
|
*path_str = pbuf;
|
|
}
|
|
else {
|
|
/* No path */
|
|
*path_str = NULL;
|
|
}
|
|
}
|
|
|
|
CloseHandle(hProcess);
|
|
|
|
/* Return address of static ANSI string buffer */
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
CloseHandle(hProcess);
|
|
|
|
/* Nothing back */
|
|
return;
|
|
}
|
|
|
|
#if defined(CACHE_DUMP)
|
|
|
|
/* debug_print_hrswrun - Prints a Row from HrSWRun(Perf) Table */
|
|
/* debug_print_hrswrun - Prints a Row from HrSWRun(Perf) Table */
|
|
/* debug_print_hrswrun - Prints a Row from HrSWRun(Perf) Table */
|
|
|
|
static void
|
|
debug_print_hrswrun(
|
|
CACHEROW *row /* Row in hrSWRun(Perf) table */
|
|
)
|
|
/*
|
|
| EXPLICIT INPUTS:
|
|
|
|
|
| "row" - points to the row to be dumped, if NULL, the function
|
|
| merely prints a suitable title.
|
|
|
|
|
| IMPLICIT INPUTS:
|
|
|
|
|
| - Symbols used to reference the attributes in the row entry.
|
|
| - File handle defined by OFILE, presumed to be open.
|
|
|
|
|
| OUTPUTS:
|
|
|
|
|
| On Success:
|
|
| Function prints a dump of the row in ASCII for debugging purposes
|
|
| on file handle OFILE.
|
|
|
|
|
| THE BIG PICTURE:
|
|
|
|
|
| Debugging only.
|
|
|
|
|
| OTHER THINGS TO KNOW:
|
|
*/
|
|
{
|
|
|
|
if (row == NULL) {
|
|
fprintf(OFILE, "=================================\n");
|
|
fprintf(OFILE, "hrSWRun & hrSWRunPerf Table Cache\n");
|
|
fprintf(OFILE, "=================================\n");
|
|
return;
|
|
}
|
|
|
|
|
|
fprintf(OFILE, "HrSWRunIndex . . . . . . %d\n",
|
|
row->attrib_list[HRSR_INDEX].u.unumber_value);
|
|
|
|
fprintf(OFILE, "HrSWRunName. . . . . . . \"%s\"\n",
|
|
row->attrib_list[HRSR_NAME].u.string_value);
|
|
|
|
fprintf(OFILE, "HrSWRunPath. . . . . . . \"%s\"\n",
|
|
row->attrib_list[HRSR_PATH].u.string_value);
|
|
|
|
fprintf(OFILE, "HRSWRunParameters. . . . \"%s\"\n",
|
|
row->attrib_list[HRSR_PARAM].u.string_value);
|
|
|
|
fprintf(OFILE, "HrSWRunType. . . . . . . %d ",
|
|
row->attrib_list[HRSR_TYPE].u.unumber_value);
|
|
|
|
switch (row->attrib_list[HRSR_TYPE].u.unumber_value) {
|
|
case 1: fprintf(OFILE, "(unknown)\n"); break;
|
|
case 2: fprintf(OFILE, "(operatingSystem)\n"); break;
|
|
case 3: fprintf(OFILE, "(deviceDriver)\n"); break;
|
|
case 4: fprintf(OFILE, "(application)\n"); break;
|
|
default:
|
|
fprintf(OFILE, "(???)\n");
|
|
}
|
|
|
|
fprintf(OFILE, "HrSWRunStatus. . . . . . %d ",
|
|
row->attrib_list[HRSR_STATUS].u.unumber_value);
|
|
|
|
switch (row->attrib_list[HRSR_STATUS].u.unumber_value) {
|
|
case 1: fprintf(OFILE, "(running)\n"); break;
|
|
case 2: fprintf(OFILE, "(runnable)\n"); break;
|
|
case 3: fprintf(OFILE, "(notRunnable)\n"); break;
|
|
case 4: fprintf(OFILE, "(invalid)\n"); break;
|
|
default:
|
|
fprintf(OFILE, "(???)\n");
|
|
}
|
|
|
|
fprintf(OFILE, "HrSWRunPerfCpu . . . . . %d (Centi-seconds)\n",
|
|
row->attrib_list[HRSP_CPU].u.unumber_value);
|
|
|
|
fprintf(OFILE, "HrSWRunPerfMem . . . . . %d (Kbytes)\n",
|
|
row->attrib_list[HRSP_MEM].u.unumber_value);
|
|
}
|
|
#endif
|