240 lines
6.4 KiB
C
240 lines
6.4 KiB
C
|
/*
|
|||
|
* user.c v0.10
|
|||
|
*
|
|||
|
****************************************************************************
|
|||
|
* *
|
|||
|
* (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:
|
|||
|
*
|
|||
|
* SNMP Extension Agent
|
|||
|
*
|
|||
|
* Abstract:
|
|||
|
*
|
|||
|
* This module contains support functions for the HostMIB Subagent.
|
|||
|
*
|
|||
|
*
|
|||
|
* Author:
|
|||
|
*
|
|||
|
* D. D. Burns @ WebEnable, Inc.
|
|||
|
*
|
|||
|
*
|
|||
|
* Revision History:
|
|||
|
*
|
|||
|
* V0.01 - 04/16/97 D. D. Burns Original Creation
|
|||
|
*
|
|||
|
*
|
|||
|
*/
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
|
|||
|
|
|
|||
|
| Support Functions accessible from outside this module:
|
|||
|
|
|
|||
|
|
|||
|
Spt_GetProcessCount
|
|||
|
This function supports hrSystem table attribute "hrSystemProcesses"
|
|||
|
by returning the number of active processes in the system. This
|
|||
|
code is derived from PERFDLL code in files "PERFSPRC.C" and
|
|||
|
"PERFPROC.C".
|
|||
|
|
|||
|
|
|
|||
|
| Support Functions accessible only from inside this module:
|
|||
|
|
|
|||
|
|
|||
|
*/
|
|||
|
|
|||
|
|
|||
|
#include <nt.h>
|
|||
|
#include <ntrtl.h>
|
|||
|
#include <nturtl.h>
|
|||
|
#include <windows.h>
|
|||
|
#include <stdlib.h>
|
|||
|
#include <malloc.h>
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
|| LOCAL DEFINES
|
|||
|
*/
|
|||
|
|
|||
|
/*
|
|||
|
| Spt_GetProcessCount
|
|||
|
*/
|
|||
|
#define INCREMENT_BUFFER_SIZE ((DWORD)(4096*2))
|
|||
|
#define LARGE_BUFFER_SIZE ((DWORD)(4096*16))
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/* Spt_GetProcessCount - Retrieve count of number of active processes */
|
|||
|
/* Spt_GetProcessCount - Retrieve count of number of active processes */
|
|||
|
/* Spt_GetProcessCount - Retrieve count of number of active processes */
|
|||
|
|
|||
|
ULONG
|
|||
|
Spt_GetProcessCount(
|
|||
|
void
|
|||
|
)
|
|||
|
/*
|
|||
|
| IN SUPPORT OF:
|
|||
|
|
|
|||
|
| HRSYSTEM.C - "hrSystemProcesses"
|
|||
|
|
|
|||
|
| EXPLICIT INPUTS:
|
|||
|
|
|
|||
|
| None.
|
|||
|
|
|
|||
|
| IMPLICIT INPUTS:
|
|||
|
|
|
|||
|
| System performance information is fetched thru
|
|||
|
| "NtQuerySystemInformation()".
|
|||
|
|
|
|||
|
| OUTPUTS:
|
|||
|
|
|
|||
|
| On Success:
|
|||
|
| Function returns the count of active processes as determined by
|
|||
|
| the number of performance information blocks for processes that
|
|||
|
| have both a name and a non-zero thread count (in the style of code in
|
|||
|
| "PERFPROC.C").
|
|||
|
|
|
|||
|
| On any Failure:
|
|||
|
| Function returns zero (not a legal number of processes).
|
|||
|
|
|
|||
|
| THE BIG PICTURE:
|
|||
|
|
|
|||
|
| The generated function "GetHrSystemProcesses()" in HRSYSTEM.C is
|
|||
|
| invoked by the generic subagent to retrieve the current value of
|
|||
|
| the SNMP attribute "GetHrSystemProcesses". All the work of
|
|||
|
| retrieving that value is done by this support function.
|
|||
|
|
|
|||
|
| OTHER THINGS TO KNOW:
|
|||
|
|
|
|||
|
| This function incurs a rather substantial bit of overhead in that
|
|||
|
| to determine the number of processes active it actually fetches
|
|||
|
| a large slug of performance data (a "slug" per process) for all
|
|||
|
| processes and merely counts the number of slugs returned.
|
|||
|
| This seems to be the only available way to acquire this information.
|
|||
|
|
|
|||
|
*/
|
|||
|
{
|
|||
|
DWORD dwReturnedBufferSize;
|
|||
|
NTSTATUS Status;
|
|||
|
DWORD ProcessBufSize = LARGE_BUFFER_SIZE; // Initial Process-Buf size
|
|||
|
LPBYTE pProcessBuffer = NULL; // Pointer to Process-Buf
|
|||
|
PSYSTEM_PROCESS_INFORMATION ProcessInfo; // Walking ptr thru Process-Buf
|
|||
|
ULONG ProcessBufferOffset = 0; //
|
|||
|
ULONG Process_count = 0; // Count of Live processes
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Get process data from system.
|
|||
|
//
|
|||
|
|
|||
|
// Grab an initially-sized buffer to receive data
|
|||
|
pProcessBuffer = malloc(ProcessBufSize);
|
|||
|
if (pProcessBuffer == NULL) {
|
|||
|
return (0); // Out of memory
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
| Loop until we've allocated a buffer big enough to receive all the data
|
|||
|
| NtQuery wants to give us.
|
|||
|
|
|
|||
|
| Exit with the buffer loaded with info or on some kind of non-mismatch error.
|
|||
|
*/
|
|||
|
|
|||
|
while( (Status = NtQuerySystemInformation(
|
|||
|
SystemProcessInformation,
|
|||
|
pProcessBuffer,
|
|||
|
ProcessBufSize,
|
|||
|
&dwReturnedBufferSize))
|
|||
|
== STATUS_INFO_LENGTH_MISMATCH ) {
|
|||
|
|
|||
|
LPBYTE pNewProcessBuffer; // 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 (0); // Out of memory
|
|||
|
}
|
|||
|
else {
|
|||
|
/* Successful Realloc */
|
|||
|
pProcessBuffer = pNewProcessBuffer;
|
|||
|
}
|
|||
|
|
|||
|
/* Try another query */
|
|||
|
}
|
|||
|
|
|||
|
/* If we didn't meet with full success. . . */
|
|||
|
if ( !NT_SUCCESS(Status) ) {
|
|||
|
if (pProcessBuffer != NULL) {
|
|||
|
free(pProcessBuffer);
|
|||
|
}
|
|||
|
|
|||
|
return (0); // Unknown error that prevents us from continuing
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
| At this point, "pProcessBuffer" points to a buffer formatted as a
|
|||
|
| "System Process Information" structure.
|
|||
|
|
|
|||
|
| Setup to go a-walking it.
|
|||
|
*/
|
|||
|
ProcessInfo = (PSYSTEM_PROCESS_INFORMATION) pProcessBuffer;
|
|||
|
|
|||
|
while ( TRUE ) {
|
|||
|
|
|||
|
// check for Live processes
|
|||
|
// (i.e. name or threads)
|
|||
|
|
|||
|
if ((ProcessInfo->ImageName.Buffer != NULL) ||
|
|||
|
(ProcessInfo->NumberOfThreads > 0)) {
|
|||
|
|
|||
|
/* thread is not Dead */
|
|||
|
Process_count += 1;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
// exit if this was the last process in list
|
|||
|
if (ProcessInfo->NextEntryOffset == 0) {
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
// point to next buffer in list
|
|||
|
ProcessBufferOffset += ProcessInfo->NextEntryOffset;
|
|||
|
ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)
|
|||
|
&pProcessBuffer[ProcessBufferOffset];
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
free(pProcessBuffer);
|
|||
|
|
|||
|
return (Process_count);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|