Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

2009 lines
70 KiB

/*++ BUILD Version: 0001 // Increment this if a change has global effects
Copyright (c) 1992 Microsoft Corporation
Module Name:
perftcp.c
Abstract:
This file implements the Extensible Objects for
the TCP/IP LAN object types
Created:
Christos Tsollis 08/26/92
Revision History:
10/28/92 a-robw (Bob Watson)
added Message Logging and Foreign Computer Support interface.
--*/
//
// Disable SNMP interface
//
// This file has been modified to circumvent the SNMP service and
// go right to the agent DLL. In doing this, performance has been
// improved at the expense of only being able to query the local
// machine. The USE_SNMP flag has been used to save as much of the
// old code as possible (it used to work) but the emphesis of this
// modification is to make it work "around" SNMP and, as such, the
// USE_SNMP blocks of code HAVE NOT (at this time) BEEN TESTED!
// Caveat Emptor! (a-robw)
//
#ifdef USE_SNMP
#undef USE_SNMP
#endif
//#define LOAD_MGMTAPI
#ifdef LOAD_MGMTAPI
#undef LOAD_MGMTAPI
#endif
#define LOAD_INETMIB1
//#ifdef LOAD_INETMIB1
//#undef LOAD_INETMIB1
//#endif
//
// Disable DSIS interface for now
//
#ifdef USE_DSIS
#undef USE_DSIS
#endif
//
// Use IPHLPAPI.DLL
//
#ifndef USE_SNMP
#define USE_IPHLPAPI
#ifdef LOAD_INETMIB1
#undef LOAD_INETMIB1
#endif
#endif
//
// Include Files
//
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <ntprfctr.h>
#include <windows.h>
#include <winperf.h>
#include <winbase.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#ifdef USE_SNMP
#include <mgmtapi.h>
#endif
#include <snmp.h>
#ifdef USE_IPHLPAPI
#include <iphlpapi.h>
#endif
#include "perfctr.h" // error message definition
#include "perfmsg.h"
#include "perfutil.h"
#include "perfnbt.h"
//#include "perfdsis.h" ! not yet !
#ifndef USE_IPHLPAPI
#include "perftcp.h"
#endif
#include "datatcp.h"
#define ALIGN_SIZE 0x00000008
//
// Global Variables
//
//
// References to constants which initialize the Object type definitions
//
extern NET_INTERFACE_DATA_DEFINITION NetInterfaceDataDefinition;
extern IP_DATA_DEFINITION IpDataDefinition;
extern ICMP_DATA_DEFINITION IcmpDataDefinition;
extern TCP_DATA_DEFINITION TcpDataDefinition;
extern UDP_DATA_DEFINITION UdpDataDefinition;
#ifndef USE_SNMP // only include if not using SNMP interface
//
HANDLE hSnmpEvent = NULL; // handler for SNMP Extension Agent
#endif
//
// TCP/IP data structures
//
#ifdef USE_SNMP
LPSNMP_MGR_SESSION TcpIpSession = (LPSNMP_MGR_SESSION) NULL;
// The SNMP manager session providing
// the requested information.
#else
BOOL TcpIpSession = FALSE;
// The SNMP manager session providing
// the requested information.
#endif
#ifdef USE_IPHLPAPI
#define MAX_INTERFACE_LEN MAX_PATH // Maximum length of a network interface
// name
#define DEFAULT_INTERFACES 20 // Default interfaces count
DWORD IfNum;
MIB_IPSTATS IpStats;
MIB_ICMP IcmpStats;
MIB_TCPSTATS TcpStats;
MIB_UDPSTATS UdpStats;
PMIB_IFTABLE IfTable = NULL;
DWORD IfTableSize = 0;
#else
AsnObjectName RefNames[NO_OF_OIDS];
RFC1157VarBind RefVariableBindingsArray[NO_OF_OIDS],
VariableBindingsArray[NO_OF_OIDS];
// The array of the variable bindings,
// used by the SNMP agent functions
// to record the info we want for the
// IP, ICMP, TCP and UDP protocols
RFC1157VarBind IFPermVariableBindingsArray[NO_OF_IF_OIDS];
// The initialization array of the
// variable bindings,
// used by the SNMP agent functions
// to record the info we want for each
// of the Network Interfaces
RFC1157VarBindList RefVariableBindings;
RFC1157VarBindList RefIFVariableBindings;
RFC1157VarBindList RefVariableBindingsICMP;
// The headers of the lists with the
// variable bindings.
// The headers of the lists with the
// variable bindings.
RFC1157VarBind NetIfRequest; // structure for net request
RFC1157VarBindList NetIfRequestList;
//
// Constants
//
#define TIMEOUT 500 // Communication timeout in milliseconds
#define RETRIES 5 // Communication time-out/retry count
#define MAX_INTERFACE_LEN 10 // Maximum length of a network interface
// name
#define OIDS_OFFSET 0 // Offset of other than the ICMP Oids
// in the VariableBindingsArray[]
#define ICMP_OIDS_OFFSET 29 // Offset of the ICMP Oids in the array
#define OIDS_LENGTH 29 // Number of the other than the ICMP
// Oids in the VariableBindingsArray[]
#define ICMP_OIDS_LENGTH 26 // Number of the ICMP Oids in the array
//
// Macro Definitions (To avoid long expressions)
//
#define IF_COUNTER(INDEX) \
(IFVariableBindings.list[(INDEX)].value.asnValue.counter)
#define IF_GAUGE(INDEX) \
(IFVariableBindings.list[(INDEX)].value.asnValue.gauge)
#define IP_COUNTER(INDEX) \
(VariableBindings.list[(INDEX)].value.asnValue.counter)
#define ICMP_COUNTER(INDEX) \
(VariableBindingsICMP.list[(INDEX)].value.asnValue.counter)
#define TCP_COUNTER(INDEX) \
(VariableBindings.list[(INDEX)].value.asnValue.counter)
#define UDP_COUNTER(INDEX) \
(VariableBindings.list[(INDEX)].value.asnValue.counter)
#define TCP_GAUGE(INDEX) \
(VariableBindings.list[(INDEX)].value.asnValue.gauge)
#endif
#define TCP_OBJECT 0x00000001
#define UDP_OBJECT 0x00000002
#define IP_OBJECT 0x00000004
#define ICMP_OBJECT 0x00000008
#define NET_OBJECT 0x00000010
#define NBT_OBJECT 0x00000020
#define SNMP_OBJECTS (TCP_OBJECT+UDP_OBJECT+IP_OBJECT+ICMP_OBJECT+NET_OBJECT)
#define SNMP_ERROR 0x40000000
#define DO_COUNTER_OBJECT(flags,counter) \
((((flags) & (counter)) == (counter)) ? TRUE : FALSE)
//
// Function Prototypes
//
PM_OPEN_PROC OpenTcpIpPerformanceData;
PM_COLLECT_PROC CollectTcpIpPerformanceData;
PM_CLOSE_PROC CloseTcpIpPerformanceData;
#ifdef LOAD_INETMIB1
HANDLE hInetMibDll;
PFNSNMPEXTENSIONINIT pSnmpExtensionInit;
PFNSNMPEXTENSIONQUERY pSnmpExtensionQuery;
#endif
DWORD dwTcpRefCount = 0;
static const WCHAR szFriendlyNetworkInterfaceNames[] = {L"FriendlyNetworkInterfaceNames"};
static const WCHAR szTcpipPerformancePath[] = {L"SYSTEM\\CurrentControlSet\\Services\\TcpIp\\Performance"};
static BOOL bUseFriendlyNames = FALSE;
__inline Assign64(
IN LONGLONG qwSrc,
IN PLARGE_INTEGER pqwDest
)
{
PLARGE_INTEGER pqwSrc = (PLARGE_INTEGER) &qwSrc;
pqwDest->LowPart = pqwSrc->LowPart;
pqwDest->HighPart = pqwSrc->HighPart;
}
static
BOOL
FriendlyNameIsSet ()
{
BOOL bReturn = TRUE;
DWORD dwStatus = ERROR_SUCCESS;
HKEY hKeyTcpipPerformance = NULL;
DWORD dwType = 0;
DWORD dwSize = 0;
DWORD dwValue = 0;
dwStatus = RegOpenKeyExW (
HKEY_LOCAL_MACHINE,
szTcpipPerformancePath,
0L,
KEY_READ,
&hKeyTcpipPerformance);
if (dwStatus == ERROR_SUCCESS) {
dwSize = sizeof(dwValue);
dwStatus = RegQueryValueExW (
hKeyTcpipPerformance,
szFriendlyNetworkInterfaceNames,
NULL,
&dwType,
(LPBYTE)&dwValue,
&dwSize);
if ((dwStatus == ERROR_SUCCESS) && (dwValue == 0) &&
((dwType == REG_DWORD) || ((dwType == REG_BINARY) && (dwSize == sizeof (DWORD))))) {
bReturn = FALSE;
}
RegCloseKey (hKeyTcpipPerformance);
}
return bReturn;
}
DWORD
OpenTcpIpPerformanceData (
IN LPWSTR dwVoid // Argument needed only to conform to calling
// interface for this routine. (NT > 312) RBW
)
/*++
Routine Description:
This routine will open all the TCP/IP devices and remember the handles
returned by the devices.
Arguments:
IN LPWSTR dwVoid
not used
Return Value:
ERROR_SUCCESS if successful completion
error returned by OpenNbtPerformanceData
error returned by OpenDsisPerformanceData
or Win32 Error value
--*/
{
DWORD Status;
TCHAR ComputerName[MAX_COMPUTERNAME_LENGTH+1];
DWORD cchBuffer = MAX_COMPUTERNAME_LENGTH+1;
DWORD dwDataReturn[2]; // event log data
#ifdef LOAD_INETMIB1
UINT nErrorMode;
#endif
#ifndef USE_IPHLPAPI
register i;
#ifdef LOAD_MGMTAPI
HANDLE hMgmtApiDll; // handle to library
FARPROC SnmpMgrStrToOid; // address of function
#else
#define SnmpMgrStrToOid(a,b) SnmpMgrText2Oid((a),(b))
#endif
#ifdef LOAD_INETMIB1
AsnObjectIdentifier SnmpOid;
#endif
#endif
UNREFERENCED_PARAMETER (dwVoid);
MonOpenEventLog ();
REPORT_INFORMATION (TCP_OPEN_ENTERED, LOG_VERBOSE);
HEAP_PROBE();
if (dwTcpRefCount == 0) {
// Open NBT
Status = OpenNbtPerformanceData (0L);
if ( Status != ERROR_SUCCESS ) {
// NBT reports any Open errors to the user
REPORT_ERROR (TCP_NBT_OPEN_FAIL, LOG_DEBUG);
return Status;
}
REPORT_INFORMATION (TCP_NBT_OPEN_SUCCESS, LOG_VERBOSE);
#ifdef USE_DSIS
Status = OpenDsisPerformanceData (0L);
if (Status != ERROR_SUCCESS) {
// DSIS Open reports Open errors to the user
REPORT_ERROR (TCP_DSIS_OPEN_FAIL, LOG_DEBUG);
return (Status);
}
REPORT_INFORMATION (TCP_DSIS_OPEN_SUCCESS, LOG_VERBOSE);
#endif // USE_DSIS
#ifdef LOAD_MGMTAPI // this STILL craps out
hMgmtApiDll = LoadLibrary ("MGMTAPI.DLL");
if (hMgmtApiDll == NULL) {
dwDataReturn[0] = GetLastError ();
REPORT_ERROR_DATA (TCP_LOAD_LIBRARY_FAIL, LOG_USER,
&dwDataReturn[0], (sizeof (DWORD)));
return (dwDataReturn[0]);
}
SnmpMgrStrToOid = GetProcAddress (hMgmtApiDll, "SnmpMgrStrToOid");
if (!(BOOL)SnmpMgrStrToOid) {
dwDataReturn[0] = GetLastError();
REPORT_ERROR_DATA (TCP_GET_STRTOOID_ADDR_FAIL, LOG_USER,
&dwDataReturn[0], (sizeof (DWORD)));
CloseNbtPerformanceData ();
FreeLibrary (hMgmtApiDll);
return (dwDataReturn[0]);
}
#else
// SnmpMgrStrToOid is defined as a macro above
#endif // LOAD_MGMTAPI
#ifdef LOAD_INETMIB1 // this STILL craps out
// don't pop up any dialog boxes
nErrorMode = SetErrorMode (SEM_FAILCRITICALERRORS);
hInetMibDll = LoadLibrary ("INETMIB1.DLL");
if (hInetMibDll == NULL) {
dwDataReturn[0] = GetLastError ();
REPORT_ERROR_DATA (TCP_LOAD_LIBRARY_FAIL, LOG_USER,
&dwDataReturn[0], (sizeof (DWORD)));
CloseNbtPerformanceData ();
// restore Error Mode
SetErrorMode (nErrorMode);
return (dwDataReturn[0]);
} else {
// restore Error Mode
SetErrorMode (nErrorMode);
}
pSnmpExtensionInit = (PFNSNMPEXTENSIONINIT)GetProcAddress
(hInetMibDll, "SnmpExtensionInit");
pSnmpExtensionQuery = (PFNSNMPEXTENSIONQUERY)GetProcAddress
(hInetMibDll, "SnmpExtensionQuery");
if (!pSnmpExtensionInit || !pSnmpExtensionQuery) {
dwDataReturn[0] = GetLastError();
REPORT_ERROR_DATA (TCP_LOAD_ROUTINE_FAIL, LOG_USER,
&dwDataReturn[0], (sizeof (DWORD)));
FreeLibrary (hInetMibDll);
CloseNbtPerformanceData ();
return (dwDataReturn[0]);
}
#endif // LOAD_INETMIB1
// Initialize the Variable Binding list for IP, ICMP, TCP and UDP
Status = 0; // initialize error count
HEAP_PROBE();
#ifndef USE_IPHLPAPI
for (i = 0; i < NO_OF_OIDS; i++) {
if (!SnmpMgrStrToOid (OidStr[i], &(RefNames[i]))) {
Status++;
REPORT_ERROR_DATA (TCP_BAD_OBJECT, LOG_DEBUG,
OidStr[i], strlen(OidStr[i]));
RefNames[i].ids = NULL;
RefNames[i].idLength = 0;
}
RefVariableBindingsArray[i].value.asnType = ASN_NULL;
}
if (Status == 0) {
REPORT_INFORMATION (TCP_BINDINGS_INIT, LOG_VERBOSE);
}
HEAP_PROBE();
// Initialize the Variable Binding list for Network interfaces
Status = 0;
for (i = 0; i < NO_OF_IF_OIDS; i++) {
if (!SnmpMgrStrToOid (IfOidStr[i], &(IFPermVariableBindingsArray[i].name))) {
Status++;
REPORT_ERROR_DATA (TCP_BAD_OBJECT, LOG_DEBUG,
IfOidStr[i], strlen(IfOidStr[i]));
}
IFPermVariableBindingsArray[i].value.asnType = ASN_NULL;
}
HEAP_PROBE();
#ifdef LOAD_MGMTAPI
FreeLibrary (hMgmtApiDll); // done with SnmpMgrStrToOid routine
#endif
// initialize list structures
RefVariableBindings.list = RefVariableBindingsArray + OIDS_OFFSET;
RefVariableBindings.len = OIDS_LENGTH;
RefVariableBindingsICMP.list =
RefVariableBindingsArray + ICMP_OIDS_OFFSET;
RefVariableBindingsICMP.len = ICMP_OIDS_LENGTH;
RefIFVariableBindings.list = IFPermVariableBindingsArray;
RefIFVariableBindings.len = NO_OF_IF_OIDS;
#endif
if ( GetComputerName ((LPTSTR)ComputerName, (LPDWORD)&cchBuffer) == FALSE ) {
dwDataReturn[0] = GetLastError();
dwDataReturn[1] = 0;
REPORT_ERROR_DATA (TCP_COMPUTER_NAME, LOG_USER,
&dwDataReturn, sizeof(dwDataReturn));
CloseNbtPerformanceData ();
return dwDataReturn[0];
}
#ifdef USE_IPHLPAPI
// enforce that TcpIpSession is on.
//
TcpIpSession = TRUE;
#else
#ifdef USE_SNMP
// Establish the SNMP connection to communicate with the local SNMP agent
/* This portion of the code for OpenTcpIpPerformanceData() could be used in
the CollectTcpIpPerformanceData() routine to open an SNMP Manager session
and collect data for the Network Interfaces, and IP, ICMP, TCP and UDP
protocols for a remote machine.
So, name this portion of the code: A
*/
if ( (TcpIpSession = SnmpMgrOpen ((LPSTR) ComputerName,
(LPSTR) "public",
TIMEOUT,
RETRIES)) == NULL ) {
dwDataReturn[0] = GetLastError();
REPORT_ERROR_DATA (TCP_SNMP_MGR_OPEN, LOG_USER,
&dwDataReturn, sizeof(DWORD));
return dwDataReturn[0];
}
/* End of code A
*/
#else
// if not using the standard SNMP interface, then TcpIpSession is
// a "boolean" to indicate if a session has been initialized and
// can therefore be used
TcpIpSession = FALSE; // make sure it's FALSE
// initialize inet mib routines
Status = (*pSnmpExtensionInit)(
0L,
&hSnmpEvent, // event is created by Init Routine
&SnmpOid
);
if (Status) {
TcpIpSession = TRUE; // return TRUE to indicate OK
}
#endif // USE_SNMP
#endif
bUseFriendlyNames = FriendlyNameIsSet();
}
dwTcpRefCount++;
HEAP_PROBE();
REPORT_INFORMATION (TCP_OPEN_PERFORMANCE_DATA, LOG_DEBUG);
return ERROR_SUCCESS;
} // OpenTcpIpPerformanceData
#pragma warning ( disable : 4127)
DWORD
CollectTcpIpPerformanceData(
LPWSTR lpValueName,
LPVOID *lppData,
LPDWORD lpcbTotalBytes,
LPDWORD lpNumObjectTypes
)
/*++
Routine Description:
This routine will return the data for all the TCP/IP counters.
Arguments:
Pointer to unicode string which is value passed to the registry for the
query.
Pointer to pointer to where to place the data.
Size in bytes of the data buffer.
Return Value:
Win32 Status. If successful, pointer to where to place the data
will be set to location following this routine's returned data block.
--*/
{
DWORD Status;
// Variables for reformatting the TCP/IP data
register PDWORD pdwCounter, pdwPackets;
NET_INTERFACE_DATA_DEFINITION *pNetInterfaceDataDefinition;
IP_DATA_DEFINITION *pIpDataDefinition;
ICMP_DATA_DEFINITION *pIcmpDataDefinition;
TCP_DATA_DEFINITION *pTcpDataDefinition;
UDP_DATA_DEFINITION *pUdpDataDefinition;
DWORD SpaceNeeded;
UNICODE_STRING InterfaceName;
ANSI_STRING AnsiInterfaceName;
WCHAR InterfaceNameBuffer[MAX_INTERFACE_LEN+1];
CHAR AnsiInterfaceNameBuffer[MAX_INTERFACE_LEN+1];
register PERF_INSTANCE_DEFINITION *pPerfInstanceDefinition;
PERF_COUNTER_BLOCK *pPerfCounterBlock;
LPVOID lpDataTemp;
DWORD NumObjectTypesTemp;
LPWSTR lpFromString;
DWORD dwQueryType;
DWORD dwCounterFlags;
DWORD dwThisChar;
DWORD dwBlockSize;
// Variables for collecting the TCP/IP data
AsnInteger ErrorStatus;
AsnInteger ErrorIndex;
AsnInteger NetInterfaces;
AsnInteger Interface;
DWORD SentTemp;
DWORD ReceivedTemp;
DWORD dwDataReturn[2]; // for error values
BOOL bFreeName;
#ifndef USE_IPHLPAPI
int i;
BOOL bStatus;
#if USE_SNMP
RFC1157VarBind IFVariableBindingsArray[NO_OF_IF_OIDS];
// The array of the variable bindings,
// used by the SNMP agent functions
// to record the info we want for each
// of the Network Interfaces
RFC1157VarBind *VBElem;
AsnInteger VBItem;
#endif
RFC1157VarBindList IFVariableBindings,
IFVariableBindingsCall,
VariableBindings,
VariableBindingsICMP;
// The header of the above list with
// the variable bindings.
#endif
//
// ***************** executable code starts here *******************
//
ErrorStatus = 0L;
ErrorIndex = 0L;
if (lpValueName == NULL) {
REPORT_INFORMATION (TCP_COLLECT_ENTERED, LOG_VERBOSE);
} else {
REPORT_INFORMATION_DATA (TCP_COLLECT_ENTERED, LOG_VERBOSE,
(LPVOID)lpValueName, (DWORD)(lstrlenW(lpValueName)*sizeof(WCHAR)));
}
//
// IF_DATA are all in DWORDS. We need to allow 1 of the octets which
// will be __int64
//
dwBlockSize = SIZE_OF_IF_DATA + (1 * sizeof(DWORD));
HEAP_PROBE();
//
// before doing anything else,
// see if this is a foreign (i.e. non-NT) computer data request
//
dwQueryType = GetQueryType (lpValueName);
if (dwQueryType == QUERY_FOREIGN) {
// find start of computer name to pass to CollectDsisPerformanceData
// this should put the pointer at the first character after the space
// presumably the computer name
lpFromString = lpValueName +
((sizeof(L"Foreign ")/sizeof(WCHAR))+1);
// check for double slash notation and move past if found
while (*lpFromString == '\\') {
lpFromString++;
}
//
// initialize local variables for sending to CollectDsisPerformanceData
// routine
//
lpDataTemp = *lppData;
SpaceNeeded = *lpcbTotalBytes;
NumObjectTypesTemp = *lpNumObjectTypes;
REPORT_INFORMATION_DATA (TCP_FOREIGN_COMPUTER_CMD, LOG_VERBOSE,
(LPVOID)lpFromString, (DWORD)(lstrlenW(lpFromString)*sizeof(WCHAR)));
#ifdef USE_DSIS
Status = CollectDsisPerformanceData (
lpFromString,
(LPVOID *) &lpDataTemp,
(LPDWORD) &SpaceNeeded,
(LPDWORD) &NumObjectTypesTemp);
//
// look at returned arguments to see if an error occured
// and send the appropriate event to the event log
//
if (Status == ERROR_SUCCESS) {
if (NumObjectTypesTemp > 0) {
REPORT_INFORMATION_DATA (TCP_DSIS_COLLECT_DATA_SUCCESS, LOG_DEBUG,
&NumObjectTypesTemp, sizeof (NumObjectTypesTemp));
} else {
REPORT_ERROR (TCP_DSIS_NO_OBJECTS, LOG_DEBUG);
}
//
// update main return variables
//
*lppData = ALIGN_ON_QWORD(lpDataTemp);
*lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
*lpNumObjectTypes = NumObjectTypesTemp;
return ERROR_SUCCESS;
} else {
REPORT_ERROR_DATA (TCP_DSIS_COLLECT_DATA_ERROR, LOG_DEBUG,
&Status, sizeof (Status));
*lpcbTotalBytes = 0;
*lpNumObjectTypes = 0;
return Status;
}
#else
// no foreign data interface supported
*lpcbTotalBytes = 0;
*lpNumObjectTypes = 0;
return ERROR_SUCCESS;
#endif // USE_DSIS
} // endif QueryType == Foreign
dwCounterFlags = 0;
// determine what to return
if (dwQueryType == QUERY_GLOBAL) {
dwCounterFlags |= NBT_OBJECT;
dwCounterFlags |= SNMP_OBJECTS;
} else if (dwQueryType == QUERY_ITEMS) {
// check for the items provided by this routine
//
// Since the data requests for the following protocols are all
// bundled together, we'll send back all the data. Collecting it
// via SNMP is the hard part. once that's done, sending it back
// is trivial.
//
if (IsNumberInUnicodeList (TCP_OBJECT_TITLE_INDEX, lpValueName)) {
dwCounterFlags |= SNMP_OBJECTS;
} else if (IsNumberInUnicodeList (UDP_OBJECT_TITLE_INDEX, lpValueName)) {
dwCounterFlags |= SNMP_OBJECTS;
} else if (IsNumberInUnicodeList (IP_OBJECT_TITLE_INDEX, lpValueName)) {
dwCounterFlags |= SNMP_OBJECTS;
} else if (IsNumberInUnicodeList (ICMP_OBJECT_TITLE_INDEX, lpValueName)) {
dwCounterFlags |= SNMP_OBJECTS;
} else if (IsNumberInUnicodeList (NET_OBJECT_TITLE_INDEX, lpValueName)) {
dwCounterFlags |= SNMP_OBJECTS;
}
if (IsNumberInUnicodeList (NBT_OBJECT_TITLE_INDEX, lpValueName)) {
dwCounterFlags |= NBT_OBJECT;
}
}
#ifndef USE_IPHLPAPI
// copy Binding array structures to working buffers for Snmp queries
RtlMoveMemory (VariableBindingsArray,
RefVariableBindingsArray,
sizeof (RefVariableBindingsArray));
VariableBindings.list = VariableBindingsArray + OIDS_OFFSET;
VariableBindings.len = OIDS_LENGTH;
VariableBindingsICMP.list = VariableBindingsArray + ICMP_OIDS_OFFSET;
VariableBindingsICMP.len = ICMP_OIDS_LENGTH;
#endif
if (DO_COUNTER_OBJECT (dwCounterFlags, NBT_OBJECT)) {
// Copy the parameters. We'll call the NBT Collect routine with these
// parameters
lpDataTemp = *lppData;
SpaceNeeded = *lpcbTotalBytes;
NumObjectTypesTemp = *lpNumObjectTypes;
// Collect NBT data
Status = CollectNbtPerformanceData (lpValueName,
(LPVOID *) &lpDataTemp,
(LPDWORD) &SpaceNeeded,
(LPDWORD) &NumObjectTypesTemp) ;
if (Status != ERROR_SUCCESS) {
// NBT Collection routine logs error messages to user
REPORT_ERROR_DATA (TCP_NBT_COLLECT_DATA, LOG_DEBUG,
&Status, sizeof (Status));
*lpcbTotalBytes = 0L;
*lpNumObjectTypes = 0L;
return Status;
}
} else {
// Initialize the parameters. We'll use these local
// parameters for remaining routines if NBT didn't use them
lpDataTemp = *lppData;
SpaceNeeded = 0;
NumObjectTypesTemp = 0;
}
/* To collect data for the Network Interfaces, and IP, ICMP, TCP and UDP
protocols for a remote machine whose name is in the Unicode string pointed
to by the lpValueName argument of CollectTcpIpData() routine, modify the
routine as follows:
1. Remove all the Nbt stuff from the code.
2. Convert the remote machine name from Unicode to Ansi, and have a local
LPSTR variable pointing to the Ansi remote machine name.
3. Place the above portion of the code named A after this comment.
4. Place the code named B (which is at the end of the file) at the end
of this routine to close the opened SNMP session.
*/
// get network info from SNMP agent
if ((dwCounterFlags & SNMP_OBJECTS) > 0) { // if any SNMP Objects selected
if (TRUE) { // and not a skeleton request
#ifdef USE_SNMP
if ( TcpIpSession == (LPSNMP_MGR_SESSION) NULL ) {
REPORT_WARNING (TCP_NULL_SESSION, LOG_DEBUG);
*lppData = ALIGN_ON_QWORD(lpDataTemp);
*lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
*lpNumObjectTypes = NumObjectTypesTemp;
return ERROR_SUCCESS;
}
#else
if (!TcpIpSession) {
REPORT_WARNING (TCP_NULL_SESSION, LOG_DEBUG);
*lppData = ALIGN_ON_QWORD(lpDataTemp);
*lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
*lpNumObjectTypes = NumObjectTypesTemp;
return ERROR_SUCCESS;
}
#endif
// Get the data for the IP, ICMP, TCP and UDP protocols, as well as
// the number of existing network interfaces.
// create local query list
HEAP_PROBE();
#ifdef USE_IPHLPAPI
Status = GetNumberOfInterfaces(&IfNum);
if (Status)
{
dwDataReturn[0] = Status;
dwDataReturn[1] = 0;
REPORT_ERROR_DATA (TCP_SNMP_MGR_REQUEST, LOG_DEBUG,
&dwDataReturn, sizeof(dwDataReturn));
*lppData = ALIGN_ON_QWORD(lpDataTemp);
*lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
*lpNumObjectTypes = NumObjectTypesTemp;
return ERROR_SUCCESS;
}
Status = GetIpStatistics(&IpStats);
if (Status)
{
dwDataReturn[0] = Status;
dwDataReturn[1] = 0;
REPORT_ERROR_DATA (TCP_SNMP_MGR_REQUEST, LOG_DEBUG,
&dwDataReturn, sizeof(dwDataReturn));
*lppData = ALIGN_ON_QWORD(lpDataTemp);
*lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
*lpNumObjectTypes = NumObjectTypesTemp;
return ERROR_SUCCESS;
}
Status = GetTcpStatistics(&TcpStats);
if (Status)
{
dwDataReturn[0] = Status;
dwDataReturn[1] = 0;
REPORT_ERROR_DATA (TCP_SNMP_MGR_REQUEST, LOG_DEBUG,
&dwDataReturn, sizeof(dwDataReturn));
*lppData = ALIGN_ON_QWORD(lpDataTemp);
*lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
*lpNumObjectTypes = NumObjectTypesTemp;
return ERROR_SUCCESS;
}
Status = GetUdpStatistics(&UdpStats);
if (Status)
{
dwDataReturn[0] = Status;
dwDataReturn[1] = 0;
REPORT_ERROR_DATA (TCP_SNMP_MGR_REQUEST, LOG_DEBUG,
&dwDataReturn, sizeof(dwDataReturn));
*lppData = ALIGN_ON_QWORD(lpDataTemp);
*lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
*lpNumObjectTypes = NumObjectTypesTemp;
return ERROR_SUCCESS;
}
Status = GetIcmpStatistics(&IcmpStats);
if (Status)
{
dwDataReturn[0] = Status;
dwDataReturn[1] = 0;
REPORT_ERROR_DATA (TCP_ICMP_REQUEST, LOG_DEBUG,
&dwDataReturn, sizeof(dwDataReturn));
*lppData = ALIGN_ON_QWORD(lpDataTemp);
*lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
*lpNumObjectTypes = NumObjectTypesTemp;
return ERROR_SUCCESS;
}
HEAP_PROBE();
} // endif (TRUE)
#else
#ifdef USE_SNMP
SnmpUtilVarBindListCpy (&VariableBindings,
&RefVariableBindings);
#else
for (i = 0; i < NO_OF_OIDS; i++) {
SnmpUtilOidCpy (&(RefVariableBindingsArray[i].name),
&(RefNames[i]));
}
VariableBindings.list = RtlAllocateHeap (
RtlProcessHeap(),
0L,
(RefVariableBindings.len * sizeof(RFC1157VarBind)));
if (!VariableBindings.list) {
REPORT_ERROR (TCP_SNMP_BUFFER_ALLOC_FAIL, LOG_DEBUG);
*lppData = ALIGN_ON_QWORD(lpDataTemp);
*lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
*lpNumObjectTypes = NumObjectTypesTemp;
return ERROR_SUCCESS;
} else {
RtlMoveMemory (
VariableBindings.list,
RefVariableBindings.list,
(RefVariableBindings.len * sizeof(RFC1157VarBind)));
VariableBindings.len = RefVariableBindings.len;
}
#endif
HEAP_PROBE();
#ifdef USE_SNMP
bStatus = SnmpMgrRequest (TcpIpSession,
ASN_RFC1157_GETREQUEST,
&VariableBindings,
&ErrorStatus,
&ErrorIndex);
#else
bStatus = (*pSnmpExtensionQuery) (ASN_RFC1157_GETREQUEST,
&VariableBindings,
&ErrorStatus,
&ErrorIndex);
#endif
if ( !bStatus ) {
dwDataReturn[0] = ErrorStatus;
dwDataReturn[1] = ErrorIndex;
REPORT_ERROR_DATA (TCP_SNMP_MGR_REQUEST, LOG_DEBUG,
&dwDataReturn, sizeof(dwDataReturn));
*lppData = ALIGN_ON_QWORD(lpDataTemp);
*lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
*lpNumObjectTypes = NumObjectTypesTemp;
SnmpUtilVarBindListFree (&VariableBindings);
return ERROR_SUCCESS;
}
if ( ErrorStatus > 0 ) {
dwDataReturn[0] = ErrorStatus;
dwDataReturn[1] = ErrorIndex;
REPORT_ERROR_DATA (TCP_SNMP_MGR_REQUEST, LOG_DEBUG,
&dwDataReturn, sizeof(dwDataReturn));
*lppData = ALIGN_ON_QWORD(lpDataTemp);
*lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
*lpNumObjectTypes = NumObjectTypesTemp;
SnmpUtilVarBindListFree (&VariableBindings);
return ERROR_SUCCESS;
}
HEAP_PROBE();
#ifdef USE_SNMP
SnmpUtilVarBindListCpy (&VariableBindingsICMP,
&RefVariableBindingsICMP);
#else
VariableBindingsICMP.list = RtlAllocateHeap (
RtlProcessHeap(),
0L,
(RefVariableBindingsICMP.len * sizeof(RFC1157VarBind)));
if (!VariableBindingsICMP.list) {
REPORT_ERROR (TCP_SNMP_BUFFER_ALLOC_FAIL, LOG_DEBUG);
*lppData = ALIGN_ON_QWORD(lpDataTemp);
*lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded;
*lpNumObjectTypes = NumObjectTypesTemp;
return ERROR_SUCCESS;
} else {
RtlMoveMemory (
VariableBindingsICMP.list,
RefVariableBindingsICMP.list,
(RefVariableBindingsICMP.len * sizeof(RFC1157VarBind)));
VariableBindingsICMP.len = RefVariableBindingsICMP.len;
}
#endif
HEAP_PROBE();
#ifdef USE_SNMP
bStatus = SnmpMgrRequest (TcpIpSession,
ASN_RFC1157_GETREQUEST,
&VariableBindingsICMP,
&ErrorStatus,
#else
bStatus = (*pSnmpExtensionQuery) (ASN_RFC1157_GETREQUEST,
&VariableBindingsICMP,
&ErrorStatus,
&ErrorIndex);
#endif
if ( !bStatus ) {
dwDataReturn[0] = ErrorStatus;
dwDataReturn[1] = ErrorIndex;
REPORT_ERROR_DATA (TCP_ICMP_REQUEST, LOG_DEBUG,
&dwDataReturn, sizeof(dwDataReturn));
*lppData = ALIGN_ON_QWORD(lpDataTemp);
*lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
*lpNumObjectTypes = NumObjectTypesTemp;
SnmpUtilVarBindListFree (&VariableBindings);
SnmpUtilVarBindListFree (&VariableBindingsICMP);
return ERROR_SUCCESS;
}
if ( ErrorStatus > 0 ) {
dwDataReturn[0] = ErrorStatus;
dwDataReturn[1] = ErrorIndex;
REPORT_ERROR_DATA (TCP_ICMP_REQUEST, LOG_DEBUG,
&dwDataReturn, sizeof(dwDataReturn));
*lppData = ALIGN_ON_QWORD(lpDataTemp);
*lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
*lpNumObjectTypes = NumObjectTypesTemp;
SnmpUtilVarBindListFree (&VariableBindings);
SnmpUtilVarBindListFree (&VariableBindingsICMP);
return ERROR_SUCCESS;
}
} // endif (TRUE)
HEAP_PROBE();
// make sure everything made it back OK
if (VariableBindingsICMP.list == 0) {
REPORT_WARNING (TCP_NULL_ICMP_BUFF, LOG_DEBUG);
dwCounterFlags |= (SNMP_ERROR); // return null data
}
if (VariableBindings.list == 0) {
REPORT_WARNING (TCP_NULL_TCP_BUFF, LOG_DEBUG);
dwCounterFlags |= (SNMP_ERROR); // return null data
dwCounterFlags &= ~NET_OBJECT; // don't do NET Interface ctrs.
}
#endif
if (DO_COUNTER_OBJECT(dwCounterFlags, SNMP_ERROR)) {
REPORT_WARNING (TCP_NULL_SNMP_BUFF, LOG_USER);
}
if (DO_COUNTER_OBJECT (dwCounterFlags, NET_OBJECT)) {
SpaceNeeded += sizeof (NET_INTERFACE_DATA_DEFINITION);
if ( *lpcbTotalBytes < SpaceNeeded ) {
dwDataReturn[0] = *lpcbTotalBytes;
dwDataReturn[1] = SpaceNeeded;
REPORT_WARNING_DATA (TCP_NET_IF_BUFFER_SIZE, LOG_DEBUG,
&dwDataReturn, sizeof(dwDataReturn));
//
// if the buffer size is too small here, throw everything
// away (including the NBT stuff) and return buffer size
// error. If all goes well the caller will call back shortly
// with a larger buffer and everything will be re-collected.
//
*lpcbTotalBytes = 0;
*lpNumObjectTypes = 0;
#ifndef USE_IPHLPAPI
SnmpUtilVarBindListFree (&VariableBindings);
SnmpUtilVarBindListFree (&VariableBindingsICMP);
#endif
return ERROR_MORE_DATA;
}
pNetInterfaceDataDefinition =
(NET_INTERFACE_DATA_DEFINITION *) lpDataTemp;
RtlMoveMemory (pNetInterfaceDataDefinition,
&NetInterfaceDataDefinition,
sizeof (NET_INTERFACE_DATA_DEFINITION));
pPerfInstanceDefinition = (PERF_INSTANCE_DEFINITION *)
(pNetInterfaceDataDefinition + 1);
#ifdef USE_IPHLPAPI
NetInterfaces = IfNum;
#else
NetInterfaces =
VariableBindings.list[IF_NUMBER_INDEX].value.asnValue.number;
#endif
REPORT_INFORMATION_DATA (TCP_NET_INTERFACE, LOG_VERBOSE,
&NetInterfaces, sizeof(NetInterfaces));
if ( NetInterfaces ) {
// Initialize the Variable Binding list for the
// Network Interface Performance Data
#ifndef USE_IPHLPAPI
HEAP_PROBE();
#ifdef USE_SNMP
SnmpUtilVarBindListCpy (&IFVariableBindings,
&RefIFVariableBindings);
#else
SnmpUtilVarBindListCpy (&IFVariableBindingsCall,
&RefIFVariableBindings);
IFVariableBindings.list = RtlAllocateHeap (
RtlProcessHeap(),
0L,
(RefIFVariableBindings.len * sizeof(RFC1157VarBind)));
if (!IFVariableBindings.list) {
REPORT_ERROR (TCP_SNMP_BUFFER_ALLOC_FAIL, LOG_DEBUG);
*lppData = ALIGN_ON_QWORD(lpDataTemp);
*lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
*lpNumObjectTypes = NumObjectTypesTemp;
return ERROR_SUCCESS;
} else {
RtlMoveMemory (
IFVariableBindings.list,
IFVariableBindingsCall.list,
(IFVariableBindingsCall.len * sizeof(RFC1157VarBind)));
IFVariableBindings.len = RefIFVariableBindings.len;
}
#endif
#endif
HEAP_PROBE();
// Initialize buffer for the network interfaces' names
AnsiInterfaceName.Length =
AnsiInterfaceName.MaximumLength = MAX_INTERFACE_LEN + 1;
AnsiInterfaceName.Buffer = AnsiInterfaceNameBuffer;
}
#ifdef USE_IPHLPAPI
Status = GetNumberOfInterfaces(&NetInterfaces);
if ((Status != ERROR_SUCCESS) || (NetInterfaces < DEFAULT_INTERFACES)) {
NetInterfaces = DEFAULT_INTERFACES;
}
IfTableSize = SIZEOF_IFTABLE(NetInterfaces);
Status = ERROR_INSUFFICIENT_BUFFER;
SentTemp = 0;
IfTable = NULL;
while ((Status == ERROR_INSUFFICIENT_BUFFER) &&
(SentTemp++ < 10)) {
if (IfTable) {
HeapFree(RtlProcessHeap(), 0L, IfTable);
}
IfTable = (PMIB_IFTABLE) RtlAllocateHeap(
RtlProcessHeap(), 0L, IfTableSize);
if (!IfTable)
{
REPORT_ERROR (TCP_SNMP_BUFFER_ALLOC_FAIL, LOG_DEBUG);
*lppData = ALIGN_ON_QWORD(lpDataTemp);
*lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
*lpNumObjectTypes = NumObjectTypesTemp;
return ERROR_SUCCESS;
}
Status = GetIfTable(IfTable, & IfTableSize, FALSE);
}
if (Status)
{
dwDataReturn[0] = Status;
dwDataReturn[1] = 0;
REPORT_ERROR_DATA (TCP_NET_GETNEXT_REQUEST, LOG_DEBUG,
&dwDataReturn, sizeof(dwDataReturn));
#ifdef USE_IPHLPAPI
if (IfTable) {
RtlFreeHeap(RtlProcessHeap(), 0L, IfTable);
IfTable = NULL;
}
#endif
*lppData = ALIGN_ON_QWORD(lpDataTemp);
*lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
*lpNumObjectTypes = NumObjectTypesTemp;
return ERROR_SUCCESS;
}
NetInterfaces = IfTable->dwNumEntries;
#endif
// Loop for every network interface
for ( Interface = 0; Interface < NetInterfaces; Interface++ ) {
// Get the data for the network interface
HEAP_PROBE();
#ifndef USE_IPHLPAPI
#ifdef USE_SNMP
bStatus = SnmpMgrRequest ( TcpIpSession,
ASN_RFC1157_GETNEXTREQUEST,
&IFVariableBindings,
&ErrorStatus,
&ErrorIndex);
#else
bStatus = (*pSnmpExtensionQuery) (ASN_RFC1157_GETNEXTREQUEST,
&IFVariableBindings,
&ErrorStatus,
&ErrorIndex);
#endif
HEAP_PROBE();
if ( ! bStatus ) {
continue;
}
if ( ErrorStatus > 0 ) {
dwDataReturn[0] = ErrorStatus;
dwDataReturn[1] = ErrorIndex;
REPORT_ERROR_DATA (TCP_NET_GETNEXT_REQUEST, LOG_DEBUG,
&dwDataReturn, sizeof(dwDataReturn));
continue;
}
#endif
bFreeName = FALSE;
// Everything is fine, so go get the data (prepare a new instance)
#ifdef USE_IPHLPAPI
RtlInitAnsiString(&AnsiInterfaceName, IfTable->table[Interface].bDescr);
#else
AnsiInterfaceName.Length = (USHORT)sprintf (AnsiInterfaceNameBuffer,
"%ld",
IFVariableBindings.list[IF_INDEX_INDEX].value.asnValue.number);
#endif
if (AnsiInterfaceName.Length <= MAX_INTERFACE_LEN) {
RtlInitUnicodeString(&InterfaceName, NULL);
RtlAnsiStringToUnicodeString(
&InterfaceName,
&AnsiInterfaceName,
TRUE);
bFreeName = TRUE;
}
else {
InterfaceName.Length =
InterfaceName.MaximumLength = (MAX_INTERFACE_LEN + 1) * sizeof (WCHAR);
InterfaceName.Buffer = InterfaceNameBuffer;
RtlAnsiStringToUnicodeString (&InterfaceName,
&AnsiInterfaceName,
FALSE);
}
SpaceNeeded += sizeof (PERF_INSTANCE_DEFINITION) +
QWORD_MULTIPLE(InterfaceName.Length+sizeof(UNICODE_NULL)) +
dwBlockSize;
if ( *lpcbTotalBytes < SpaceNeeded ) {
dwDataReturn[0] = *lpcbTotalBytes;
dwDataReturn[1] = SpaceNeeded;
REPORT_WARNING_DATA (TCP_NET_BUFFER_SIZE, LOG_DEBUG,
&dwDataReturn, sizeof(dwDataReturn));
//
// if the buffer size is too small here, throw everything
// away (including the NBT stuff) and return buffer size
// error. If all goes well the caller will call back shortly
// with a larger buffer and everything will be re-collected.
//
*lpcbTotalBytes = 0;
*lpNumObjectTypes = 0;
#ifndef USE_IPHLPAPI
SnmpUtilVarBindListFree (&IFVariableBindings);
SnmpUtilVarBindListFree (&VariableBindings);
SnmpUtilVarBindListFree (&VariableBindingsICMP);
#else
if (IfTable) {
RtlFreeHeap(RtlProcessHeap(), 0L, IfTable);
IfTable = NULL;
}
#endif
return ERROR_MORE_DATA;
}
if (bUseFriendlyNames) {
// replace any reserved characters in the instance name with safe ones
for (dwThisChar = 0; dwThisChar <= (InterfaceName.Length / sizeof (WCHAR)); dwThisChar++) {
switch (InterfaceName.Buffer[dwThisChar]) {
case L'(': InterfaceName.Buffer[dwThisChar] = L'['; break;
case L')': InterfaceName.Buffer[dwThisChar] = L']'; break;
case L'#': InterfaceName.Buffer[dwThisChar] = L'_'; break;
case L'/': InterfaceName.Buffer[dwThisChar] = L'_'; break;
case L'\\': InterfaceName.Buffer[dwThisChar] = L'_'; break;
default: break;
}
}
}
MonBuildInstanceDefinition (pPerfInstanceDefinition,
(PVOID *) &pPerfCounterBlock,
0,
0,
(bUseFriendlyNames ? (DWORD)PERF_NO_UNIQUE_ID : (DWORD)(Interface + 1)),
&InterfaceName);
if (bFreeName) {
RtlFreeUnicodeString(&InterfaceName);
}
pPerfCounterBlock->ByteLength = dwBlockSize;
pdwCounter = (PDWORD) (pPerfCounterBlock + 1);
#ifdef USE_IPHLPAPI
Assign64( IfTable->table[Interface].dwInOctets
+ IfTable->table[Interface].dwOutOctets,
(PLARGE_INTEGER) pdwCounter);
REPORT_INFORMATION (TCP_COPYING_DATA, LOG_VERBOSE);
pdwPackets = pdwCounter + 2;
pdwCounter += 4; // skip packet counters first
*++pdwCounter = IfTable->table[Interface].dwSpeed;
*++pdwCounter = IfTable->table[Interface].dwInOctets;
ReceivedTemp = *++pdwCounter = IfTable->table[Interface].dwInUcastPkts;
ReceivedTemp += *++pdwCounter = IfTable->table[Interface].dwInNUcastPkts;
ReceivedTemp += *++pdwCounter = IfTable->table[Interface].dwInDiscards;
ReceivedTemp += *++pdwCounter = IfTable->table[Interface].dwInErrors;
ReceivedTemp += *++pdwCounter = IfTable->table[Interface].dwInUnknownProtos;
*++pdwCounter = IfTable->table[Interface].dwOutOctets;
SentTemp = *++pdwCounter = IfTable->table[Interface].dwOutUcastPkts;
SentTemp += *++pdwCounter = IfTable->table[Interface].dwOutNUcastPkts;
*++pdwCounter = IfTable->table[Interface].dwOutDiscards;
*++pdwCounter = IfTable->table[Interface].dwOutErrors;
*++pdwCounter = IfTable->table[Interface].dwOutQLen;
#else
Assign64( IF_COUNTER(IF_INOCTETS_INDEX) +
IF_COUNTER(IF_OUTOCTETS_INDEX,
(PLARGE_INTEGER) pdwCounter);
REPORT_INFORMATION (TCP_COPYING_DATA, LOG_VERBOSE);
pdwPackets = pdwCounter + 2;
pdwCounter += 4; // skip packet counters first
//
// NOTE: We are skipping 2 words for Total bytes,
// and one each for total packets, in packets & out packets
//
*++pdwCounter = IF_GAUGE(IF_SPEED_INDEX);
*++pdwCounter = IF_COUNTER(IF_INOCTETS_INDEX);
ReceivedTemp = *++pdwCounter = IF_COUNTER(IF_INUCASTPKTS_INDEX);
ReceivedTemp += *++pdwCounter = IF_COUNTER(IF_INNUCASTPKTS_INDEX);
ReceivedTemp += *++pdwCounter = IF_COUNTER(IF_INDISCARDS_INDEX);
ReceivedTemp += *++pdwCounter = IF_COUNTER(IF_INERRORS_INDEX);
ReceivedTemp += *++pdwCounter = IF_COUNTER(IF_INUNKNOWNPROTOS_INDEX);
*++pdwCounter = IF_COUNTER(IF_OUTOCTETS_INDEX);
SentTemp = *pdwCounter = IF_COUNTER(IF_OUTUCASTPKTS_INDEX);
SentTemp += *++pdwCounter = IF_COUNTER(IF_OUTNUCASTPKTS_INDEX);
*++pdwCounter = IF_COUNTER(IF_OUTDISCARDS_INDEX);
*++pdwCounter = IF_COUNTER(IF_OUTERRORS_INDEX);
*++pdwCounter = IF_COUNTER(IF_OUTQLEN_INDEX);
#endif
*pdwPackets = ReceivedTemp + SentTemp;
*++pdwPackets = ReceivedTemp;
*++pdwPackets = SentTemp;
pPerfInstanceDefinition = (PERF_INSTANCE_DEFINITION *)
(((PBYTE) pPerfCounterBlock) + dwBlockSize);
#ifndef USE_IPHLPAPI
#if USE_SNMP
// Prepare to get the data for the next network interface
if ( Interface < NetInterfaces ) {
for ( i = 0; i < NO_OF_IF_OIDS; i++ ) {
// SnmpUtilOidFree (&IFVariableBindingsArray[i].name);
SnmpUtilOidCpy (&IFVariableBindingsArray[i].name,
&IFVariableBindings.list[i].name);
}
}
SnmpUtilVarBindListFree (&IFVariableBindings);
IFVariableBindings.list = IFVariableBindingsArray;
IFVariableBindings.len = NO_OF_IF_OIDS;
#else
if ( Interface < NetInterfaces ) {
// since SnmpExtesionQuery returned newly allocated
// OID buffers, we need to:
// 1. free the original OID Buffers
// 2. copy the new into the old
// 3. free the returned buffers (OID's and data)
// 4. realloc a clean "new" buffer and
// 5. copy the new OIDS (with empty data) into
// new buffer
for ( i = 0; i < NO_OF_IF_OIDS; i++ ) {
// SnmpUtilOidFree (&IFVariableBindingsCall.list[i].name);
SnmpUtilOidCpy (&IFVariableBindingsCall.list[i].name,
&IFVariableBindings.list[i].name);
}
SnmpUtilVarBindListFree (&IFVariableBindings);
IFVariableBindings.list = RtlAllocateHeap (
RtlProcessHeap(),
0L,
(RefIFVariableBindings.len * sizeof(RFC1157VarBind)));
if (!VariableBindings.list) {
REPORT_ERROR (TCP_SNMP_BUFFER_ALLOC_FAIL, LOG_DEBUG);
*lppData = lpDataTemp;
*lpcbTotalBytes = SpaceNeeded;
*lpNumObjectTypes = NumObjectTypesTemp;
#ifdef USE_IPHLPAPI
if (IfTable) {
RtlFreeHeap(RtlProcessHeap(), 0L, IfTable);
IfTable = NULL;
}
#endif
return ERROR_SUCCESS;
} else {
RtlMoveMemory (
IFVariableBindings.list,
IFVariableBindingsCall.list,
(IFVariableBindingsCall.len * sizeof(RFC1157VarBind)));
IFVariableBindings.len = RefIFVariableBindings.len;
}
}
#endif
#endif
HEAP_PROBE();
}
pNetInterfaceDataDefinition->NetInterfaceObjectType.TotalByteLength =
(DWORD)((PBYTE) pPerfInstanceDefinition - (PBYTE) pNetInterfaceDataDefinition);
pNetInterfaceDataDefinition->NetInterfaceObjectType.NumInstances =
NetInterfaces;
// setup counters and pointers for next counter
NumObjectTypesTemp += 1;
lpDataTemp = (LPVOID)pPerfInstanceDefinition;
// SpaceNeeded is kept up already
HEAP_PROBE();
if ( NetInterfaces ) {
#ifndef USE_IPHLPAPI
SnmpUtilVarBindListFree (&IFVariableBindings);
// SnmpUtilVarBindListFree (&IFVariableBindingsCall);
RtlFreeHeap (RtlProcessHeap(), 0L, IFVariableBindingsCall.list);
#endif
}
HEAP_PROBE();
} // end if Net Counters
// Get IP data
#ifdef USE_IPHLPAPI
if (IfTable) {
RtlFreeHeap(RtlProcessHeap(), 0L, IfTable);
IfTable = NULL;
}
#endif
HEAP_PROBE();
if (DO_COUNTER_OBJECT (dwCounterFlags, IP_OBJECT)) {
SpaceNeeded += (sizeof(IP_DATA_DEFINITION) + SIZE_OF_IP_DATA);
if ( *lpcbTotalBytes < SpaceNeeded ) {
dwDataReturn[0] = *lpcbTotalBytes;
dwDataReturn[1] = SpaceNeeded;
REPORT_WARNING_DATA (TCP_NET_IF_BUFFER_SIZE, LOG_DEBUG,
&dwDataReturn, sizeof(dwDataReturn));
//
// if the buffer size is too small here, throw everything
// away (including the NBT stuff) and return buffer size
// error. If all goes well the caller will call back shortly
// with a larger buffer and everything will be re-collected.
//
*lpcbTotalBytes = 0;
*lpNumObjectTypes = 0;
#ifndef USE_IPHLPAPI
SnmpUtilVarBindListFree (&VariableBindings);
SnmpUtilVarBindListFree (&VariableBindingsICMP);
#endif
return ERROR_MORE_DATA;
}
pIpDataDefinition = (IP_DATA_DEFINITION *) lpDataTemp;
RtlMoveMemory (pIpDataDefinition,
&IpDataDefinition,
sizeof (IP_DATA_DEFINITION));
pPerfCounterBlock = (PERF_COUNTER_BLOCK *) (pIpDataDefinition + 1);
pPerfCounterBlock->ByteLength = SIZE_OF_IP_DATA;
pdwCounter = (PDWORD) (pPerfCounterBlock + 1);
#ifdef USE_IPHLPAPI
*pdwCounter = IpStats.dwInReceives + IpStats.dwOutRequests;
*++pdwCounter = IpStats.dwInReceives;
*++pdwCounter = IpStats.dwInHdrErrors;
*++pdwCounter = IpStats.dwInAddrErrors;
*++pdwCounter = IpStats.dwForwDatagrams;
*++pdwCounter = IpStats.dwInUnknownProtos;
*++pdwCounter = IpStats.dwInDiscards;
*++pdwCounter = IpStats.dwInDelivers;
*++pdwCounter = IpStats.dwOutRequests;
*++pdwCounter = IpStats.dwOutDiscards;
*++pdwCounter = IpStats.dwOutNoRoutes;
*++pdwCounter = IpStats.dwReasmReqds;
*++pdwCounter = IpStats.dwReasmOks;
*++pdwCounter = IpStats.dwReasmFails;
*++pdwCounter = IpStats.dwFragOks;
*++pdwCounter = IpStats.dwFragFails;
*++pdwCounter = IpStats.dwFragCreates;
#else
*pdwCounter = IP_COUNTER(IP_INRECEIVES_INDEX) +
IP_COUNTER(IP_OUTREQUESTS_INDEX);
*++pdwCounter = IP_COUNTER(IP_INRECEIVES_INDEX);
*++pdwCounter = IP_COUNTER(IP_INHDRERRORS_INDEX);
*++pdwCounter = IP_COUNTER(IP_INADDRERRORS_INDEX);
*++pdwCounter = IP_COUNTER(IP_FORWDATAGRAMS_INDEX);
*++pdwCounter = IP_COUNTER(IP_INUNKNOWNPROTOS_INDEX);
*++pdwCounter = IP_COUNTER(IP_INDISCARDS_INDEX);
*++pdwCounter = IP_COUNTER(IP_INDELIVERS_INDEX);
*++pdwCounter = IP_COUNTER(IP_OUTREQUESTS_INDEX);
*++pdwCounter = IP_COUNTER(IP_OUTDISCARDS_INDEX);
*++pdwCounter = IP_COUNTER(IP_OUTNOROUTES_INDEX);
*++pdwCounter = IP_COUNTER(IP_REASMREQDS_INDEX);
*++pdwCounter = IP_COUNTER(IP_REASMOKS_INDEX);
*++pdwCounter = IP_COUNTER(IP_REASMFAILS_INDEX);
*++pdwCounter = IP_COUNTER(IP_FRAGOKS_INDEX);
*++pdwCounter = IP_COUNTER(IP_FRAGFAILS_INDEX);
*++pdwCounter = IP_COUNTER(IP_FRAGCREATES_INDEX);
#endif
// setup counters and pointers for next counter
NumObjectTypesTemp +=1;
lpDataTemp = (LPVOID)++pdwCounter;
// SpaceNeeded is kept up already
}
HEAP_PROBE();
// Get ICMP data
if (DO_COUNTER_OBJECT (dwCounterFlags, ICMP_OBJECT)) {
// The data for the network interfaces are now ready. So, let's get
// the data for the IP, ICMP, TCP and UDP protocols.
SpaceNeeded += (sizeof(ICMP_DATA_DEFINITION) + SIZE_OF_ICMP_DATA);
if ( *lpcbTotalBytes < SpaceNeeded ) {
dwDataReturn[0] = *lpcbTotalBytes;
dwDataReturn[1] = SpaceNeeded;
REPORT_WARNING_DATA (TCP_NET_IF_BUFFER_SIZE, LOG_DEBUG,
&dwDataReturn, sizeof(dwDataReturn));
//
// if the buffer size is too small here, throw everything
// away (including the NBT stuff) and return buffer size
// error. If all goes well the caller will call back shortly
// with a larger buffer and everything will be re-collected.
//
*lpcbTotalBytes = 0;
*lpNumObjectTypes = 0;
#ifndef USE_IPHLPAPI
SnmpUtilVarBindListFree (&VariableBindings);
SnmpUtilVarBindListFree (&VariableBindingsICMP);
#endif
return ERROR_MORE_DATA;
}
pIcmpDataDefinition = (ICMP_DATA_DEFINITION *) lpDataTemp;;
RtlMoveMemory (pIcmpDataDefinition,
&IcmpDataDefinition,
sizeof (ICMP_DATA_DEFINITION));
pPerfCounterBlock = (PERF_COUNTER_BLOCK *) (pIcmpDataDefinition + 1);
pPerfCounterBlock->ByteLength = SIZE_OF_ICMP_DATA;
pdwCounter = (PDWORD) (pPerfCounterBlock + 1);
#ifdef USE_IPHLPAPI
*pdwCounter = IcmpStats.stats.icmpInStats.dwMsgs
+ IcmpStats.stats.icmpOutStats.dwMsgs;
*++pdwCounter = IcmpStats.stats.icmpInStats.dwMsgs;
*++pdwCounter = IcmpStats.stats.icmpInStats.dwErrors;
*++pdwCounter = IcmpStats.stats.icmpInStats.dwDestUnreachs;
*++pdwCounter = IcmpStats.stats.icmpInStats.dwTimeExcds;
*++pdwCounter = IcmpStats.stats.icmpInStats.dwParmProbs;
*++pdwCounter = IcmpStats.stats.icmpInStats.dwSrcQuenchs;
*++pdwCounter = IcmpStats.stats.icmpInStats.dwRedirects;
*++pdwCounter = IcmpStats.stats.icmpInStats.dwEchos;
*++pdwCounter = IcmpStats.stats.icmpInStats.dwEchoReps;
*++pdwCounter = IcmpStats.stats.icmpInStats.dwTimestamps;
*++pdwCounter = IcmpStats.stats.icmpInStats.dwTimestampReps;
*++pdwCounter = IcmpStats.stats.icmpInStats.dwAddrMasks;
*++pdwCounter = IcmpStats.stats.icmpInStats.dwAddrMaskReps;
*++pdwCounter = IcmpStats.stats.icmpOutStats.dwMsgs;
*++pdwCounter = IcmpStats.stats.icmpOutStats.dwErrors;
*++pdwCounter = IcmpStats.stats.icmpOutStats.dwDestUnreachs;
*++pdwCounter = IcmpStats.stats.icmpOutStats.dwTimeExcds;
*++pdwCounter = IcmpStats.stats.icmpOutStats.dwParmProbs;
*++pdwCounter = IcmpStats.stats.icmpOutStats.dwSrcQuenchs;
*++pdwCounter = IcmpStats.stats.icmpOutStats.dwRedirects;
*++pdwCounter = IcmpStats.stats.icmpOutStats.dwEchos;
*++pdwCounter = IcmpStats.stats.icmpOutStats.dwEchoReps;
*++pdwCounter = IcmpStats.stats.icmpOutStats.dwTimestamps;
*++pdwCounter = IcmpStats.stats.icmpOutStats.dwTimestampReps;
*++pdwCounter = IcmpStats.stats.icmpOutStats.dwAddrMasks;
*++pdwCounter = IcmpStats.stats.icmpOutStats.dwAddrMaskReps;
#else
*pdwCounter = ICMP_COUNTER(ICMP_INMSGS_INDEX) +
ICMP_COUNTER(ICMP_OUTMSGS_INDEX);
*++pdwCounter = ICMP_COUNTER(ICMP_INMSGS_INDEX);
*++pdwCounter = ICMP_COUNTER(ICMP_INERRORS_INDEX);
*++pdwCounter = ICMP_COUNTER(ICMP_INDESTUNREACHS_INDEX);
*++pdwCounter = ICMP_COUNTER(ICMP_INTIMEEXCDS_INDEX);
*++pdwCounter = ICMP_COUNTER(ICMP_INPARMPROBS_INDEX);
*++pdwCounter = ICMP_COUNTER(ICMP_INSRCQUENCHS_INDEX);
*++pdwCounter = ICMP_COUNTER(ICMP_INREDIRECTS_INDEX);
*++pdwCounter = ICMP_COUNTER(ICMP_INECHOS_INDEX);
*++pdwCounter = ICMP_COUNTER(ICMP_INECHOREPS_INDEX);
*++pdwCounter = ICMP_COUNTER(ICMP_INTIMESTAMPS_INDEX);
*++pdwCounter = ICMP_COUNTER(ICMP_INTIMESTAMPREPS_INDEX);
*++pdwCounter = ICMP_COUNTER(ICMP_INADDRMASKS_INDEX);
*++pdwCounter = ICMP_COUNTER(ICMP_INADDRMASKREPS_INDEX);
*++pdwCounter = ICMP_COUNTER(ICMP_OUTMSGS_INDEX);
*++pdwCounter = ICMP_COUNTER(ICMP_OUTERRORS_INDEX);
*++pdwCounter = ICMP_COUNTER(ICMP_OUTDESTUNREACHS_INDEX);
*++pdwCounter = ICMP_COUNTER(ICMP_OUTTIMEEXCDS_INDEX);
*++pdwCounter = ICMP_COUNTER(ICMP_OUTPARMPROBS_INDEX);
*++pdwCounter = ICMP_COUNTER(ICMP_OUTSRCQUENCHS_INDEX);
*++pdwCounter = ICMP_COUNTER(ICMP_OUTREDIRECTS_INDEX);
*++pdwCounter = ICMP_COUNTER(ICMP_OUTECHOS_INDEX);
*++pdwCounter = ICMP_COUNTER(ICMP_OUTECHOREPS_INDEX);
*++pdwCounter = ICMP_COUNTER(ICMP_OUTTIMESTAMPS_INDEX);
*++pdwCounter = ICMP_COUNTER(ICMP_OUTTIMESTAMPREPS_INDEX);
*++pdwCounter = ICMP_COUNTER(ICMP_OUTADDRMASKS_INDEX);
*++pdwCounter = ICMP_COUNTER(ICMP_OUTADDRMASKREPS_INDEX);
#endif
HEAP_PROBE();
// SnmpUtilVarBindListFree (&VariableBindingsICMP);
HEAP_PROBE();
// setup counters and pointers for next counter
NumObjectTypesTemp += 1;
lpDataTemp = (LPVOID)++pdwCounter;
// SpaceNeeded is kept up already
}
#ifndef USE_IPHLPAPI
SnmpUtilVarBindListFree (&VariableBindingsICMP);
#endif
HEAP_PROBE();
// Get TCP data
if (DO_COUNTER_OBJECT (dwCounterFlags, TCP_OBJECT)) {
// The data for the network interfaces are now ready. So, let's get
// the data for the IP, ICMP, TCP and UDP protocols.
SpaceNeeded += (sizeof(TCP_DATA_DEFINITION) + SIZE_OF_TCP_DATA);
if ( *lpcbTotalBytes < SpaceNeeded ) {
dwDataReturn[0] = *lpcbTotalBytes;
dwDataReturn[1] = SpaceNeeded;
REPORT_WARNING_DATA (TCP_NET_IF_BUFFER_SIZE, LOG_DEBUG,
&dwDataReturn, sizeof(dwDataReturn));
//
// if the buffer size is too small here, throw everything
// away (including the NBT stuff) and return buffer size
// error. If all goes well the caller will call back shortly
// with a larger buffer and everything will be re-collected.
//
*lpcbTotalBytes = 0;
*lpNumObjectTypes = 0;
#ifndef USE_IPHLPAPI
SnmpUtilVarBindListFree (&VariableBindings);
#endif
return ERROR_MORE_DATA;
}
pTcpDataDefinition = (TCP_DATA_DEFINITION *) lpDataTemp;
RtlMoveMemory (pTcpDataDefinition,
&TcpDataDefinition,
sizeof (TCP_DATA_DEFINITION));
pPerfCounterBlock = (PERF_COUNTER_BLOCK *) (pTcpDataDefinition + 1);
pPerfCounterBlock->ByteLength = SIZE_OF_TCP_DATA;
pdwCounter = (PDWORD) (pPerfCounterBlock + 1);
#ifdef USE_IPHLPAPI
*pdwCounter = TcpStats.dwInSegs + TcpStats.dwOutSegs;
*++pdwCounter = TcpStats.dwCurrEstab;
*++pdwCounter = TcpStats.dwActiveOpens;
*++pdwCounter = TcpStats.dwPassiveOpens;
*++pdwCounter = TcpStats.dwAttemptFails;
*++pdwCounter = TcpStats.dwEstabResets;
*++pdwCounter = TcpStats.dwInSegs;
*++pdwCounter = TcpStats.dwOutSegs;
*++pdwCounter = TcpStats.dwRetransSegs;
#else
*pdwCounter = TCP_COUNTER(TCP_INSEGS_INDEX) +
TCP_COUNTER(TCP_OUTSEGS_INDEX);
*++pdwCounter = TCP_GAUGE(TCP_CURRESTAB_INDEX);
*++pdwCounter = TCP_COUNTER(TCP_ACTIVEOPENS_INDEX);
*++pdwCounter = TCP_COUNTER(TCP_PASSIVEOPENS_INDEX);
*++pdwCounter = TCP_COUNTER(TCP_ATTEMPTFAILS_INDEX);
*++pdwCounter = TCP_COUNTER(TCP_ESTABRESETS_INDEX);
*++pdwCounter = TCP_COUNTER(TCP_INSEGS_INDEX);
*++pdwCounter = TCP_COUNTER(TCP_OUTSEGS_INDEX);
*++pdwCounter = TCP_COUNTER(TCP_RETRANSSEGS_INDEX);
#endif
// setup counters and pointers for next counter
NumObjectTypesTemp += 1;
lpDataTemp = (LPVOID)++pdwCounter;
// SpaceNeeded is kept up already
}
HEAP_PROBE();
// Get UDP data
if (DO_COUNTER_OBJECT (dwCounterFlags, UDP_OBJECT)) {
// The data for the network interfaces are now ready. So, let's get
// the data for the IP, ICMP, TCP and UDP protocols.
SpaceNeeded += (sizeof(UDP_DATA_DEFINITION) + SIZE_OF_UDP_DATA);
if ( *lpcbTotalBytes < SpaceNeeded ) {
dwDataReturn[0] = *lpcbTotalBytes;
dwDataReturn[1] = SpaceNeeded;
REPORT_WARNING_DATA (TCP_NET_IF_BUFFER_SIZE, LOG_DEBUG,
&dwDataReturn, sizeof(dwDataReturn));
//
// if the buffer size is too small here, throw everything
// away (including the NBT stuff) and return buffer size
// error. If all goes well the caller will call back shortly
// with a larger buffer and everything will be re-collected.
//
*lpcbTotalBytes = 0;
*lpNumObjectTypes = 0;
#ifndef USE_IPHLPAPI
SnmpUtilVarBindListFree (&VariableBindings);
#endif
return ERROR_MORE_DATA;
}
pUdpDataDefinition = (UDP_DATA_DEFINITION *) lpDataTemp;
RtlMoveMemory (pUdpDataDefinition,
&UdpDataDefinition,
sizeof (UDP_DATA_DEFINITION));
pPerfCounterBlock = (PERF_COUNTER_BLOCK *) (pUdpDataDefinition + 1);
pPerfCounterBlock->ByteLength = SIZE_OF_UDP_DATA;
pdwCounter = (PDWORD) (pPerfCounterBlock + 1);
#ifdef USE_IPHLPAPI
*pdwCounter = UdpStats.dwInDatagrams + UdpStats.dwOutDatagrams;
*++pdwCounter = UdpStats.dwInDatagrams;
*++pdwCounter = UdpStats.dwNoPorts;
*++pdwCounter = UdpStats.dwInErrors;
*++pdwCounter = UdpStats.dwOutDatagrams;
#else
*pdwCounter = UDP_COUNTER(UDP_INDATAGRAMS_INDEX) +
UDP_COUNTER(UDP_OUTDATAGRAMS_INDEX);
*++pdwCounter = UDP_COUNTER(UDP_INDATAGRAMS_INDEX);
*++pdwCounter = UDP_COUNTER(UDP_NOPORTS_INDEX);
*++pdwCounter = UDP_COUNTER(UDP_INERRORS_INDEX);
*++pdwCounter = UDP_COUNTER(UDP_OUTDATAGRAMS_INDEX);
#endif
// setup counters and pointers for next counter
NumObjectTypesTemp += 1;
lpDataTemp = (LPVOID)++pdwCounter;
// SpaceNeeded is kept up already
}
#ifndef USE_IPHLPAPI
#ifdef USE_SNMP
// Get prepared for the next data collection
VariableBindings.list = VariableBindingsArray + OIDS_OFFSET;
VariableBindings.len = OIDS_LENGTH;
VariableBindingsICMP.list = VariableBindingsArray + ICMP_OIDS_OFFSET;
VariableBindingsICMP.len = ICMP_OIDS_LENGTH;
#else
HEAP_PROBE();
SnmpUtilVarBindListFree (&VariableBindings);
HEAP_PROBE();
#endif
#endif
} // endif SNMP Objects
// Set the returned values
*lppData = ALIGN_ON_QWORD((LPVOID) lpDataTemp);
*lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
*lpNumObjectTypes = NumObjectTypesTemp;
HEAP_PROBE();
REPORT_SUCCESS (TCP_COLLECT_DATA, LOG_DEBUG);
return ERROR_SUCCESS;
} // CollectTcpIpPerformanceData
#pragma warning ( default : 4127)
DWORD
CloseTcpIpPerformanceData(
)
/*++
Routine Description:
This routine closes the open handles to TCP/IP devices.
Arguments:
None.
Return Value:
Win32 Status.
--*/
{
#ifndef USE_IPHLPAPI
int i;
#endif
REPORT_INFORMATION (TCP_ENTERING_CLOSE, LOG_VERBOSE);
if (dwTcpRefCount > 0) {
dwTcpRefCount--;
if (dwTcpRefCount == 0) {
// Close NBT
CloseNbtPerformanceData ();
#ifdef USE_DSIS
// Close DSIS
CloseDsisPerformanceData ();
#endif // USE_DSIS
/* This portion of the code for CloseTcpIpPerformanceData() could be used in
the CollectTcpIpPerformanceData() routine to close an open SNMP Manager
session.
So, name this portion of the code: B
*/
#ifdef USE_SNMP
if ( TcpIpSession != (LPSNMP_MGR_SESSION) NULL ) {
if ( ! SnmpMgrClose (TcpIpSession) ) {
REPORT_ERROR_DATA (TCP_SNMP_MGR_CLOSE, LOG_DEBUG,
GetLastError (), sizeof(DWORD));
}
TcpIpSession = (LPSNMP_MGR_SESSION) NULL;
} else {
REPORT_WARNING (TCP_NULL_SESSION, LOG_DEBUG);
}
/* End of code B
*/
#endif
HEAP_PROBE();
#ifndef USE_IPHLPAPI
for (i = 0; i < NO_OF_OIDS; i++) {
SnmpUtilOidFree ( &(RefNames[i]));
}
HEAP_PROBE();
for (i = 0; i < NO_OF_IF_OIDS; i++) {
SnmpUtilOidFree (&(IFPermVariableBindingsArray[i].name));
}
HEAP_PROBE();
#else
if (IfTable) {
RtlFreeHeap(RtlProcessHeap(), 0L, IfTable);
IfTable = NULL;
}
#endif
#if 0
// this is closed by the INETMIB1 on process detach
// so we don't need to do it here.
// close event handle used by SNMP
if (CloseHandle (hSnmpEvent)) {
hSnmpEvent = NULL;
}
#endif
#ifdef LOAD_INETMIB1
FreeLibrary (hInetMibDll);
#endif
}
}
MonCloseEventLog();
return ERROR_SUCCESS;
} // CloseTcpIpPerformanceData