1474 lines
44 KiB
C
1474 lines
44 KiB
C
|
/*++ BUILD Version: 0001 // Increment this if a change has global effects
|
|||
|
|
|||
|
Copyright (c) 1992 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
perfnbf.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This file implements the Extensible Objects for
|
|||
|
the Nbf LAN object types
|
|||
|
|
|||
|
This code originally existed for NetBEUI only. Later, it was
|
|||
|
adaped to handle Netrware protocol level NWNB, SPX, and IPX.
|
|||
|
The code was not everywhere changed to reflect this, due to the
|
|||
|
lateness of the change. Therefore, sometimes you will see NBF
|
|||
|
where you should see TDI.
|
|||
|
|
|||
|
Created:
|
|||
|
|
|||
|
Russ Blake 07/30/92
|
|||
|
|
|||
|
Revision History
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
//
|
|||
|
// Include Files
|
|||
|
//
|
|||
|
|
|||
|
#include <nt.h>
|
|||
|
#include <ntrtl.h>
|
|||
|
#include <nturtl.h>
|
|||
|
#include <ntprfctr.h>
|
|||
|
#include <windows.h>
|
|||
|
#include <string.h>
|
|||
|
#include <stdlib.h>
|
|||
|
#include <nb30.h>
|
|||
|
#include <tdi.h>
|
|||
|
#include <winperf.h>
|
|||
|
#include "perfctr.h" // error message definition
|
|||
|
#include "perfmsg.h"
|
|||
|
#include "perfutil.h"
|
|||
|
#include "datanbf.h"
|
|||
|
|
|||
|
//
|
|||
|
// References to constants which initialize the Object type definitions
|
|||
|
//
|
|||
|
|
|||
|
extern NBF_DATA_DEFINITION NbfDataDefinition;
|
|||
|
extern NBF_RESOURCE_DATA_DEFINITION NbfResourceDataDefinition;
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// TDI data structures
|
|||
|
//
|
|||
|
|
|||
|
#define NBF_PROTOCOL 0
|
|||
|
#define IPX_PROTOCOL 1
|
|||
|
#define SPX_PROTOCOL 2
|
|||
|
#define NWNB_PROTOCOL 3
|
|||
|
#define NUMBER_OF_PROTOCOLS_HANDLED 4
|
|||
|
|
|||
|
typedef struct _TDI_DATA_DEFINITION {
|
|||
|
int NumberOfResources;
|
|||
|
HANDLE fileHandle;
|
|||
|
UNICODE_STRING DeviceName;
|
|||
|
} TDI_DATA_DEFINITION, *PTDI_DATA_DEFINITION;
|
|||
|
|
|||
|
typedef struct _TDI_PROTOCOLS_DATA {
|
|||
|
int NumOfDevices;
|
|||
|
int MaxDeviceName;
|
|||
|
int MaxNumOfResources;
|
|||
|
PTDI_DATA_DEFINITION pTDIData;
|
|||
|
} TDI_PROTOCOLS_DATA;
|
|||
|
|
|||
|
TDI_PROTOCOLS_DATA TDITbl[NUMBER_OF_PROTOCOLS_HANDLED];
|
|||
|
|
|||
|
DWORD dwTdiProtocolRefCount[NUMBER_OF_PROTOCOLS_HANDLED] = {0,0,0,0};
|
|||
|
DWORD dwTdiRefCount = 0;
|
|||
|
|
|||
|
DWORD ObjectNameTitleIndices[NUMBER_OF_PROTOCOLS_HANDLED] = { 492,
|
|||
|
488,
|
|||
|
490,
|
|||
|
398 };
|
|||
|
|
|||
|
//
|
|||
|
// NBF data structures
|
|||
|
//
|
|||
|
|
|||
|
ULONG ProviderStatsLength; // Resource-dependent size
|
|||
|
PTDI_PROVIDER_STATISTICS ProviderStats = NULL;
|
|||
|
// Provider statistics
|
|||
|
|
|||
|
//
|
|||
|
// NetBUEI Resource Instance Names
|
|||
|
//
|
|||
|
LPCWSTR NetResourceName[] =
|
|||
|
{
|
|||
|
(LPCWSTR)L"Link(11)",
|
|||
|
(LPCWSTR)L"Address(12)",
|
|||
|
(LPCWSTR)L"Address File(13)",
|
|||
|
(LPCWSTR)L"Connection(14)",
|
|||
|
(LPCWSTR)L"Request(15)",
|
|||
|
(LPCWSTR)L"UI Frame(21)",
|
|||
|
(LPCWSTR)L"Packet(22)",
|
|||
|
(LPCWSTR)L"Receive Packet(23)",
|
|||
|
(LPCWSTR)L"Receive Buffer(24)"
|
|||
|
};
|
|||
|
#define NUMBER_OF_NAMES sizeof(NetResourceName)/sizeof(NetResourceName[0])
|
|||
|
#define MAX_NBF_RESOURCE_NAME_LENGTH 20
|
|||
|
|
|||
|
//
|
|||
|
// Function Prototypes
|
|||
|
//
|
|||
|
|
|||
|
PM_OPEN_PROC OpenNbfPerformanceData;
|
|||
|
PM_COLLECT_PROC CollectNbfPerformanceData;
|
|||
|
PM_CLOSE_PROC CloseNbfPerformanceData;
|
|||
|
|
|||
|
PM_OPEN_PROC OpenIPXPerformanceData;
|
|||
|
PM_COLLECT_PROC CollectIPXPerformanceData;
|
|||
|
PM_CLOSE_PROC CloseIPXPerformanceData;
|
|||
|
|
|||
|
PM_OPEN_PROC OpenSPXPerformanceData;
|
|||
|
PM_COLLECT_PROC CollectSPXPerformanceData;
|
|||
|
PM_CLOSE_PROC CloseSPXPerformanceData;
|
|||
|
|
|||
|
PM_OPEN_PROC OpenNWNBPerformanceData;
|
|||
|
PM_COLLECT_PROC CollectNWNBPerformanceData;
|
|||
|
PM_CLOSE_PROC CloseNWNBPerformanceData;
|
|||
|
|
|||
|
DWORD OpenTDIPerformanceData(LPWSTR lpDeviceNames,
|
|||
|
DWORD CurrentProtocol);
|
|||
|
DWORD CollectTDIPerformanceData(IN LPWSTR lpValueName,
|
|||
|
IN OUT LPVOID *lppData,
|
|||
|
IN OUT LPDWORD lpcbTotalBytes,
|
|||
|
IN OUT LPDWORD lpNumObjectTypes,
|
|||
|
IN DWORD CurrentProtocol);
|
|||
|
DWORD CloseTDIPerformanceData(DWORD CurrentProtocol);
|
|||
|
|
|||
|
|
|||
|
DWORD
|
|||
|
OpenNbfPerformanceData(
|
|||
|
LPWSTR lpDeviceNames
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine will open each device and remember the handle
|
|||
|
that the device returns.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Pointer to each device to be opened
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
return OpenTDIPerformanceData(lpDeviceNames, NBF_PROTOCOL);
|
|||
|
}
|
|||
|
|
|||
|
DWORD
|
|||
|
OpenIPXPerformanceData(
|
|||
|
LPWSTR lpDeviceNames
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine will open each device and remember the handle
|
|||
|
that the device returns.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Pointer to each device to be opened
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
return OpenTDIPerformanceData(lpDeviceNames, IPX_PROTOCOL);
|
|||
|
}
|
|||
|
|
|||
|
DWORD
|
|||
|
OpenSPXPerformanceData(
|
|||
|
LPWSTR lpDeviceNames
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine will open each device and remember the handle
|
|||
|
that the device returns.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Pointer to each device to be opened
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD dwStatus;
|
|||
|
|
|||
|
dwStatus = OpenTDIPerformanceData(lpDeviceNames, SPX_PROTOCOL);
|
|||
|
if (dwStatus == ERROR_FILE_NOT_FOUND) {
|
|||
|
// no devices is not really an error, even though no counters
|
|||
|
// will be collected, this presents a much less alarming
|
|||
|
// message to the user.
|
|||
|
REPORT_WARNING (SPX_NO_DEVICE, LOG_USER);
|
|||
|
dwStatus = ERROR_SUCCESS;
|
|||
|
}
|
|||
|
return dwStatus;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
DWORD
|
|||
|
OpenNWNBPerformanceData(
|
|||
|
LPWSTR lpDeviceNames
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine will open each device and remember the handle
|
|||
|
that the device returns.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Pointer to each device to be opened
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
return OpenTDIPerformanceData(lpDeviceNames, NWNB_PROTOCOL);
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
CleanUpTDIData (
|
|||
|
DWORD CurrentProtocol
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine will celanup all the memory allocated for the
|
|||
|
CurrentProtocol
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IN DWORD CurrentProtocol
|
|||
|
this is the index of the protocol for which we are currently
|
|||
|
gathering statistics
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
int NumOfDevices;
|
|||
|
int i;
|
|||
|
PTDI_DATA_DEFINITION pTDIData;
|
|||
|
|
|||
|
pTDIData = TDITbl[CurrentProtocol].pTDIData;
|
|||
|
if (pTDIData == NULL)
|
|||
|
// nothing to cleanup
|
|||
|
return;
|
|||
|
|
|||
|
NumOfDevices = TDITbl[CurrentProtocol].NumOfDevices;
|
|||
|
for (i=0; i < NumOfDevices; i++, pTDIData++) {
|
|||
|
if (pTDIData->DeviceName.Buffer) {
|
|||
|
RtlFreeHeap(RtlProcessHeap(), 0, pTDIData->DeviceName.Buffer);
|
|||
|
}
|
|||
|
if (pTDIData->fileHandle) {
|
|||
|
NtClose (pTDIData->fileHandle);
|
|||
|
}
|
|||
|
}
|
|||
|
RtlFreeHeap(RtlProcessHeap(), 0,
|
|||
|
TDITbl[CurrentProtocol].pTDIData);
|
|||
|
TDITbl[CurrentProtocol].pTDIData = NULL;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
#pragma warning ( disable : 4127)
|
|||
|
DWORD
|
|||
|
OpenTDIPerformanceData(
|
|||
|
LPWSTR lpDeviceNames,
|
|||
|
DWORD CurrentProtocol
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine will open each device and remember the handle
|
|||
|
that the device returns.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IN LPWSTR lpDeviceNames
|
|||
|
pointer to each device to be opened
|
|||
|
|
|||
|
IN DWORD CurrentProtocol
|
|||
|
this is the index of the protocol for which we are currently
|
|||
|
gathering statistics
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
UNICODE_STRING FileString;
|
|||
|
IO_STATUS_BLOCK IoStatusBlock;
|
|||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|||
|
TDI_REQUEST_USER_QUERY_INFO QueryInfo;
|
|||
|
HANDLE fileHandle;
|
|||
|
LPWSTR lpLocalDeviceNames;
|
|||
|
int NumOfDevices;
|
|||
|
LPWSTR lpSaveDeviceName;
|
|||
|
PTDI_DATA_DEFINITION pTemp;
|
|||
|
PTDI_PROVIDER_INFO ProviderInfo=NULL;
|
|||
|
BOOL bInitThisProtocol = FALSE;
|
|||
|
|
|||
|
MonOpenEventLog(); // this function maintains a reference count
|
|||
|
|
|||
|
lpLocalDeviceNames = lpDeviceNames;
|
|||
|
|
|||
|
if (dwTdiProtocolRefCount[CurrentProtocol] == 0) {
|
|||
|
bInitThisProtocol = TRUE;
|
|||
|
TDITbl[CurrentProtocol].MaxDeviceName = 0;
|
|||
|
NumOfDevices = TDITbl[CurrentProtocol].NumOfDevices = 0;
|
|||
|
TDITbl[CurrentProtocol].pTDIData = NULL;
|
|||
|
|
|||
|
while (TRUE) {
|
|||
|
|
|||
|
if (lpLocalDeviceNames == NULL || *lpLocalDeviceNames == L'\0') {
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
REPORT_INFORMATION_DATA (TDI_OPEN_ENTERED,
|
|||
|
LOG_VERBOSE,
|
|||
|
lpLocalDeviceNames,
|
|||
|
(lstrlenW(lpLocalDeviceNames) * sizeof(WCHAR)));
|
|||
|
|
|||
|
RtlInitUnicodeString (&FileString, lpLocalDeviceNames);
|
|||
|
lpSaveDeviceName = RtlAllocateHeap(RtlProcessHeap(),
|
|||
|
HEAP_ZERO_MEMORY,
|
|||
|
sizeof (WCHAR) * (lstrlenW(lpLocalDeviceNames) + 1));
|
|||
|
|
|||
|
if (!lpSaveDeviceName) {
|
|||
|
REPORT_ERROR (TDI_PROVIDER_STATS_MEMORY, LOG_USER);
|
|||
|
if (NumOfDevices == 0)
|
|||
|
return ERROR_OUTOFMEMORY;
|
|||
|
else
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
InitializeObjectAttributes(
|
|||
|
&ObjectAttributes,
|
|||
|
&FileString,
|
|||
|
OBJ_CASE_INSENSITIVE,
|
|||
|
NULL,
|
|||
|
NULL);
|
|||
|
|
|||
|
Status = NtOpenFile(
|
|||
|
&fileHandle,
|
|||
|
SYNCHRONIZE | FILE_READ_DATA,
|
|||
|
&ObjectAttributes,
|
|||
|
&IoStatusBlock,
|
|||
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|||
|
FILE_SYNCHRONOUS_IO_ALERT);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
RtlFreeHeap(RtlProcessHeap(), 0, lpSaveDeviceName);
|
|||
|
REPORT_ERROR_DATA (TDI_OPEN_FILE_ERROR, LOG_DEBUG,
|
|||
|
lpLocalDeviceNames, (lstrlenW(lpLocalDeviceNames) * sizeof(WCHAR)));
|
|||
|
REPORT_ERROR_DATA (TDI_OPEN_FILE_ERROR, LOG_DEBUG,
|
|||
|
&IoStatusBlock, sizeof(IoStatusBlock));
|
|||
|
if (NumOfDevices == 0) {
|
|||
|
return RtlNtStatusToDosError(Status);
|
|||
|
} else {
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (NumOfDevices == 0) {
|
|||
|
// allocate memory to hold the device data
|
|||
|
TDITbl[CurrentProtocol].pTDIData =
|
|||
|
RtlAllocateHeap(RtlProcessHeap(),
|
|||
|
HEAP_ZERO_MEMORY,
|
|||
|
sizeof(TDI_DATA_DEFINITION));
|
|||
|
|
|||
|
if (TDITbl[CurrentProtocol].pTDIData == NULL) {
|
|||
|
REPORT_ERROR (TDI_PROVIDER_STATS_MEMORY, LOG_DEBUG);
|
|||
|
NtClose(fileHandle);
|
|||
|
RtlFreeHeap(RtlProcessHeap(), 0, lpSaveDeviceName);
|
|||
|
return ERROR_OUTOFMEMORY;
|
|||
|
}
|
|||
|
} else {
|
|||
|
// resize to hold multiple devices
|
|||
|
|
|||
|
pTemp = RtlReAllocateHeap(RtlProcessHeap(), 0,
|
|||
|
TDITbl[CurrentProtocol].pTDIData,
|
|||
|
sizeof(TDI_DATA_DEFINITION) * (NumOfDevices + 1));
|
|||
|
if (pTemp == NULL) {
|
|||
|
NtClose(fileHandle);
|
|||
|
RtlFreeHeap(RtlProcessHeap(), 0, lpSaveDeviceName);
|
|||
|
CleanUpTDIData(CurrentProtocol);
|
|||
|
REPORT_ERROR (TDI_PROVIDER_STATS_MEMORY, LOG_USER);
|
|||
|
return ERROR_OUTOFMEMORY;
|
|||
|
} else {
|
|||
|
TDITbl[CurrentProtocol].pTDIData = pTemp;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// build the TDI Data structure for this device instance
|
|||
|
TDITbl[CurrentProtocol].pTDIData[NumOfDevices].fileHandle
|
|||
|
= fileHandle;
|
|||
|
TDITbl[CurrentProtocol].pTDIData[NumOfDevices].DeviceName.MaximumLength =
|
|||
|
(WORD)(sizeof (WCHAR) * (lstrlenW(lpLocalDeviceNames) + 1));
|
|||
|
TDITbl[CurrentProtocol].pTDIData[NumOfDevices].DeviceName.Length =
|
|||
|
(WORD)(TDITbl[CurrentProtocol].pTDIData[NumOfDevices].DeviceName.Length - sizeof(WCHAR));
|
|||
|
TDITbl[CurrentProtocol].pTDIData[NumOfDevices].DeviceName.Buffer =
|
|||
|
lpSaveDeviceName;
|
|||
|
RtlCopyUnicodeString (
|
|||
|
&(TDITbl[CurrentProtocol].pTDIData[NumOfDevices].DeviceName),
|
|||
|
&FileString);
|
|||
|
|
|||
|
if (TDITbl[CurrentProtocol].pTDIData[NumOfDevices].DeviceName.MaximumLength
|
|||
|
> TDITbl[CurrentProtocol].MaxDeviceName) {
|
|||
|
TDITbl[CurrentProtocol].MaxDeviceName =
|
|||
|
TDITbl[CurrentProtocol].pTDIData[NumOfDevices].DeviceName.MaximumLength;
|
|||
|
}
|
|||
|
|
|||
|
// now increment NumOfDevices
|
|||
|
NumOfDevices++;
|
|||
|
TDITbl[CurrentProtocol].NumOfDevices = NumOfDevices;
|
|||
|
|
|||
|
|
|||
|
// increment to the next device string
|
|||
|
lpLocalDeviceNames += lstrlenW(lpLocalDeviceNames) + 1;
|
|||
|
}
|
|||
|
REPORT_INFORMATION (TDI_OPEN_FILE_SUCCESS, LOG_VERBOSE);
|
|||
|
}
|
|||
|
|
|||
|
dwTdiProtocolRefCount[CurrentProtocol]++;
|
|||
|
|
|||
|
if (TDITbl[CurrentProtocol].NumOfDevices == 0) {
|
|||
|
return ERROR_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// The following common buffer is used by all protocols. NBF
|
|||
|
// is bigger because of resource data returned.
|
|||
|
//
|
|||
|
|
|||
|
if (ProviderStats == NULL && CurrentProtocol != NBF_PROTOCOL) {
|
|||
|
ProviderStatsLength = sizeof(TDI_PROVIDER_STATISTICS);
|
|||
|
|
|||
|
ProviderStats = RtlAllocateHeap(RtlProcessHeap(),
|
|||
|
HEAP_ZERO_MEMORY,
|
|||
|
ProviderStatsLength);
|
|||
|
|
|||
|
if (ProviderStats == NULL) {
|
|||
|
REPORT_ERROR (TDI_PROVIDER_STATS_MEMORY, LOG_USER);
|
|||
|
CleanUpTDIData(CurrentProtocol);
|
|||
|
return ERROR_OUTOFMEMORY;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if ((CurrentProtocol == NBF_PROTOCOL) && bInitThisProtocol) {
|
|||
|
|
|||
|
//
|
|||
|
// Query provider info to get resource count.
|
|||
|
//
|
|||
|
|
|||
|
ProviderInfo = RtlAllocateHeap(RtlProcessHeap(),
|
|||
|
HEAP_ZERO_MEMORY,
|
|||
|
sizeof(TDI_PROVIDER_INFO));
|
|||
|
if ( ProviderInfo == NULL ) {
|
|||
|
REPORT_ERROR (TDI_PROVIDER_INFO_MEMORY, LOG_USER);
|
|||
|
CleanUpTDIData(CurrentProtocol);
|
|||
|
return ERROR_OUTOFMEMORY;
|
|||
|
}
|
|||
|
|
|||
|
QueryInfo.QueryType = TDI_QUERY_PROVIDER_INFO;
|
|||
|
|
|||
|
pTemp = TDITbl[CurrentProtocol].pTDIData;
|
|||
|
TDITbl[CurrentProtocol].MaxNumOfResources = 0;
|
|||
|
|
|||
|
for (NumOfDevices = 0;
|
|||
|
NumOfDevices < TDITbl[CurrentProtocol].NumOfDevices;
|
|||
|
NumOfDevices++, pTemp++) {
|
|||
|
|
|||
|
// loop thru all the devices to see if they can be opened
|
|||
|
// if one of them fails, then stop the whole thing.
|
|||
|
// we should probably save the good ones but...
|
|||
|
Status = NtDeviceIoControlFile(
|
|||
|
pTemp->fileHandle,
|
|||
|
NULL,
|
|||
|
NULL,
|
|||
|
NULL,
|
|||
|
&IoStatusBlock,
|
|||
|
IOCTL_TDI_QUERY_INFORMATION,
|
|||
|
(PVOID)&QueryInfo,
|
|||
|
sizeof(TDI_REQUEST_USER_QUERY_INFO),
|
|||
|
(PVOID)ProviderInfo,
|
|||
|
sizeof(TDI_PROVIDER_INFO));
|
|||
|
|
|||
|
pTemp->NumberOfResources = ProviderInfo->NumberOfResources;
|
|||
|
if ((int)ProviderInfo->NumberOfResources >
|
|||
|
TDITbl[CurrentProtocol].MaxNumOfResources) {
|
|||
|
TDITbl[CurrentProtocol].MaxNumOfResources =
|
|||
|
ProviderInfo->NumberOfResources;
|
|||
|
}
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
RtlFreeHeap(RtlProcessHeap(), 0, ProviderInfo);
|
|||
|
REPORT_ERROR (TDI_UNABLE_READ_DEVICE, LOG_DEBUG);
|
|||
|
REPORT_ERROR_DATA (TDI_IOCTL_FILE_ERROR, LOG_DEBUG,
|
|||
|
&IoStatusBlock, sizeof(IoStatusBlock));
|
|||
|
CleanUpTDIData(CurrentProtocol);
|
|||
|
return RtlNtStatusToDosError(Status);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
REPORT_INFORMATION (TDI_IOCTL_FILE, LOG_VERBOSE);
|
|||
|
|
|||
|
ProviderStatsLength = sizeof(TDI_PROVIDER_STATISTICS) +
|
|||
|
(TDITbl[CurrentProtocol].MaxNumOfResources *
|
|||
|
sizeof(TDI_PROVIDER_RESOURCE_STATS));
|
|||
|
|
|||
|
//
|
|||
|
// Buffer may have been allocated smaller by other protocol.
|
|||
|
//
|
|||
|
|
|||
|
if (ProviderStats != NULL) {
|
|||
|
RtlFreeHeap(RtlProcessHeap(), 0, ProviderStats);
|
|||
|
}
|
|||
|
ProviderStats = RtlAllocateHeap(RtlProcessHeap(),
|
|||
|
HEAP_ZERO_MEMORY,
|
|||
|
ProviderStatsLength);
|
|||
|
|
|||
|
if (ProviderStats == NULL) {
|
|||
|
REPORT_ERROR (TDI_PROVIDER_STATS_MEMORY, LOG_USER);
|
|||
|
RtlFreeHeap(RtlProcessHeap(), 0, ProviderInfo);
|
|||
|
CleanUpTDIData(CurrentProtocol);
|
|||
|
return ERROR_OUTOFMEMORY;
|
|||
|
}
|
|||
|
|
|||
|
if (ProviderInfo) {
|
|||
|
RtlFreeHeap(RtlProcessHeap(), 0, ProviderInfo);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
dwTdiRefCount++;
|
|||
|
|
|||
|
REPORT_INFORMATION (TDI_OPEN_PERFORMANCE_DATA, LOG_DEBUG);
|
|||
|
return ERROR_SUCCESS;
|
|||
|
}
|
|||
|
#pragma warning ( default : 4127)
|
|||
|
|
|||
|
DWORD
|
|||
|
CollectNbfPerformanceData(
|
|||
|
IN LPWSTR lpValueName,
|
|||
|
IN OUT LPVOID *lppData,
|
|||
|
IN OUT LPDWORD lpcbTotalBytes,
|
|||
|
IN OUT LPDWORD lpNumObjectTypes
|
|||
|
)
|
|||
|
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine will return the data for the Nbf counters.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IN LPWSTR lpValueName
|
|||
|
pointer to a wide character string passed by registry.
|
|||
|
|
|||
|
IN OUT LPVOID *lppData
|
|||
|
IN: pointer to the address of the buffer to receive the completed
|
|||
|
PerfDataBlock and subordinate structures. This routine will
|
|||
|
append its data to the buffer starting at the point referenced
|
|||
|
by *lppData.
|
|||
|
OUT: points to the first byte after the data structure added by this
|
|||
|
routine. This routine updated the value at lppdata after appending
|
|||
|
its data.
|
|||
|
|
|||
|
IN OUT LPDWORD lpcbTotalBytes
|
|||
|
IN: the address of the DWORD that tells the size in bytes of the
|
|||
|
buffer referenced by the lppData argument
|
|||
|
OUT: the number of bytes added by this routine is writted to the
|
|||
|
DWORD pointed to by this argument
|
|||
|
|
|||
|
IN OUT LPDWORD NumObjectTypes
|
|||
|
IN: the address of the DWORD to receive the number of objects added
|
|||
|
by this routine
|
|||
|
OUT: the number of objects added by this routine is writted to the
|
|||
|
DWORD pointed to by this argument
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_MORE_DATA if buffer passed is too small to hold data
|
|||
|
any error conditions encountered are reported to the event log if
|
|||
|
event logging is enabled.
|
|||
|
|
|||
|
ERROR_SUCCESS if success or any other error. Errors, however are
|
|||
|
also reported to the event log.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
return CollectTDIPerformanceData(lpValueName,
|
|||
|
lppData,
|
|||
|
lpcbTotalBytes,
|
|||
|
lpNumObjectTypes,
|
|||
|
NBF_PROTOCOL);
|
|||
|
}
|
|||
|
|
|||
|
DWORD
|
|||
|
CollectIPXPerformanceData(
|
|||
|
IN LPWSTR lpValueName,
|
|||
|
IN OUT LPVOID *lppData,
|
|||
|
IN OUT LPDWORD lpcbTotalBytes,
|
|||
|
IN OUT LPDWORD lpNumObjectTypes
|
|||
|
)
|
|||
|
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine will return the data for the IPX counters.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IN LPWSTR lpValueName
|
|||
|
pointer to a wide character string passed by registry.
|
|||
|
|
|||
|
IN OUT LPVOID *lppData
|
|||
|
IN: pointer to the address of the buffer to receive the completed
|
|||
|
PerfDataBlock and subordinate structures. This routine will
|
|||
|
append its data to the buffer starting at the point referenced
|
|||
|
by *lppData.
|
|||
|
OUT: points to the first byte after the data structure added by this
|
|||
|
routine. This routine updated the value at lppdata after appending
|
|||
|
its data.
|
|||
|
|
|||
|
IN OUT LPDWORD lpcbTotalBytes
|
|||
|
IN: the address of the DWORD that tells the size in bytes of the
|
|||
|
buffer referenced by the lppData argument
|
|||
|
OUT: the number of bytes added by this routine is writted to the
|
|||
|
DWORD pointed to by this argument
|
|||
|
|
|||
|
IN OUT LPDWORD NumObjectTypes
|
|||
|
IN: the address of the DWORD to receive the number of objects added
|
|||
|
by this routine
|
|||
|
OUT: the number of objects added by this routine is writted to the
|
|||
|
DWORD pointed to by this argument
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_MORE_DATA if buffer passed is too small to hold data
|
|||
|
any error conditions encountered are reported to the event log if
|
|||
|
event logging is enabled.
|
|||
|
|
|||
|
ERROR_SUCCESS if success or any other error. Errors, however are
|
|||
|
also reported to the event log.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
return CollectTDIPerformanceData(lpValueName,
|
|||
|
lppData,
|
|||
|
lpcbTotalBytes,
|
|||
|
lpNumObjectTypes,
|
|||
|
IPX_PROTOCOL);
|
|||
|
}
|
|||
|
|
|||
|
DWORD
|
|||
|
CollectSPXPerformanceData(
|
|||
|
IN LPWSTR lpValueName,
|
|||
|
IN OUT LPVOID *lppData,
|
|||
|
IN OUT LPDWORD lpcbTotalBytes,
|
|||
|
IN OUT LPDWORD lpNumObjectTypes
|
|||
|
)
|
|||
|
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine will return the data for the SPX counters.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IN LPWSTR lpValueName
|
|||
|
pointer to a wide character string passed by registry.
|
|||
|
|
|||
|
IN OUT LPVOID *lppData
|
|||
|
IN: pointer to the address of the buffer to receive the completed
|
|||
|
PerfDataBlock and subordinate structures. This routine will
|
|||
|
append its data to the buffer starting at the point referenced
|
|||
|
by *lppData.
|
|||
|
OUT: points to the first byte after the data structure added by this
|
|||
|
routine. This routine updated the value at lppdata after appending
|
|||
|
its data.
|
|||
|
|
|||
|
IN OUT LPDWORD lpcbTotalBytes
|
|||
|
IN: the address of the DWORD that tells the size in bytes of the
|
|||
|
buffer referenced by the lppData argument
|
|||
|
OUT: the number of bytes added by this routine is writted to the
|
|||
|
DWORD pointed to by this argument
|
|||
|
|
|||
|
IN OUT LPDWORD NumObjectTypes
|
|||
|
IN: the address of the DWORD to receive the number of objects added
|
|||
|
by this routine
|
|||
|
OUT: the number of objects added by this routine is writted to the
|
|||
|
DWORD pointed to by this argument
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_MORE_DATA if buffer passed is too small to hold data
|
|||
|
any error conditions encountered are reported to the event log if
|
|||
|
event logging is enabled.
|
|||
|
|
|||
|
ERROR_SUCCESS if success or any other error. Errors, however are
|
|||
|
also reported to the event log.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
return CollectTDIPerformanceData(lpValueName,
|
|||
|
lppData,
|
|||
|
lpcbTotalBytes,
|
|||
|
lpNumObjectTypes,
|
|||
|
SPX_PROTOCOL);
|
|||
|
}
|
|||
|
|
|||
|
DWORD
|
|||
|
CollectNWNBPerformanceData(
|
|||
|
IN LPWSTR lpValueName,
|
|||
|
IN OUT LPVOID *lppData,
|
|||
|
IN OUT LPDWORD lpcbTotalBytes,
|
|||
|
IN OUT LPDWORD lpNumObjectTypes
|
|||
|
)
|
|||
|
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine will return the data for the NWNB counters.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IN LPWSTR lpValueName
|
|||
|
pointer to a wide character string passed by registry.
|
|||
|
|
|||
|
IN OUT LPVOID *lppData
|
|||
|
IN: pointer to the address of the buffer to receive the completed
|
|||
|
PerfDataBlock and subordinate structures. This routine will
|
|||
|
append its data to the buffer starting at the point referenced
|
|||
|
by *lppData.
|
|||
|
OUT: points to the first byte after the data structure added by this
|
|||
|
routine. This routine updated the value at lppdata after appending
|
|||
|
its data.
|
|||
|
|
|||
|
IN OUT LPDWORD lpcbTotalBytes
|
|||
|
IN: the address of the DWORD that tells the size in bytes of the
|
|||
|
buffer referenced by the lppData argument
|
|||
|
OUT: the number of bytes added by this routine is writted to the
|
|||
|
DWORD pointed to by this argument
|
|||
|
|
|||
|
IN OUT LPDWORD NumObjectTypes
|
|||
|
IN: the address of the DWORD to receive the number of objects added
|
|||
|
by this routine
|
|||
|
OUT: the number of objects added by this routine is writted to the
|
|||
|
DWORD pointed to by this argument
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_MORE_DATA if buffer passed is too small to hold data
|
|||
|
any error conditions encountered are reported to the event log if
|
|||
|
event logging is enabled.
|
|||
|
|
|||
|
ERROR_SUCCESS if success or any other error. Errors, however are
|
|||
|
also reported to the event log.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
return CollectTDIPerformanceData(lpValueName,
|
|||
|
lppData,
|
|||
|
lpcbTotalBytes,
|
|||
|
lpNumObjectTypes,
|
|||
|
NWNB_PROTOCOL);
|
|||
|
}
|
|||
|
|
|||
|
DWORD
|
|||
|
CollectTDIPerformanceData(
|
|||
|
IN LPWSTR lpValueName,
|
|||
|
IN OUT LPVOID *lppData,
|
|||
|
IN OUT LPDWORD lpcbTotalBytes,
|
|||
|
IN OUT LPDWORD lpNumObjectTypes,
|
|||
|
IN DWORD CurrentProtocol
|
|||
|
)
|
|||
|
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine will return the data for the TDI counters.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IN LPWSTR lpValueName
|
|||
|
pointer to a wide character string passed by registry.
|
|||
|
|
|||
|
IN OUT LPVOID *lppData
|
|||
|
IN: pointer to the address of the buffer to receive the completed
|
|||
|
PerfDataBlock and subordinate structures. This routine will
|
|||
|
append its data to the buffer starting at the point referenced
|
|||
|
by *lppData.
|
|||
|
OUT: points to the first byte after the data structure added by this
|
|||
|
routine. This routine updated the value at lppdata after appending
|
|||
|
its data.
|
|||
|
|
|||
|
IN OUT LPDWORD lpcbTotalBytes
|
|||
|
IN: the address of the DWORD that tells the size in bytes of the
|
|||
|
buffer referenced by the lppData argument
|
|||
|
OUT: the number of bytes added by this routine is writted to the
|
|||
|
DWORD pointed to by this argument
|
|||
|
|
|||
|
IN OUT LPDWORD NumObjectTypes
|
|||
|
IN: the address of the DWORD to receive the number of objects added
|
|||
|
by this routine
|
|||
|
OUT: the number of objects added by this routine is writted to the
|
|||
|
DWORD pointed to by this argument
|
|||
|
|
|||
|
IN DWORD CurrentProtocol
|
|||
|
this is the index of the protocol for which we are currently
|
|||
|
gathering statistics
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_MORE_DATA if buffer passed is too small to hold data
|
|||
|
any error conditions encountered are reported to the event log if
|
|||
|
event logging is enabled.
|
|||
|
|
|||
|
ERROR_SUCCESS if success or any other error. Errors, however are
|
|||
|
also reported to the event log.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
// Variables for reformating the data
|
|||
|
|
|||
|
ULONG SpaceNeeded;
|
|||
|
PDWORD pdwCounter = NULL;
|
|||
|
LARGE_INTEGER UNALIGNED *pliCounter;
|
|||
|
LARGE_INTEGER UNALIGNED *pliFrameBytes;
|
|||
|
LARGE_INTEGER UNALIGNED *pliDatagramBytes;
|
|||
|
PERF_COUNTER_BLOCK *pPerfCounterBlock;
|
|||
|
NBF_DATA_DEFINITION *pNbfDataDefinition;
|
|||
|
NBF_RESOURCE_DATA_DEFINITION *pNbfResourceDataDefinition;
|
|||
|
|
|||
|
// Variables for collecting the data from Nbf
|
|||
|
|
|||
|
NTSTATUS Status;
|
|||
|
IO_STATUS_BLOCK IoStatusBlock;
|
|||
|
PERF_INSTANCE_DEFINITION *pPerfInstanceDefinition;
|
|||
|
TDI_REQUEST_USER_QUERY_INFO QueryInfo;
|
|||
|
|
|||
|
// Variables for collecting data about Nbf Resouces
|
|||
|
|
|||
|
int NumResource;
|
|||
|
ULONG ResourceSpace;
|
|||
|
UNICODE_STRING ResourceName;
|
|||
|
WCHAR ResourceNameBuffer[MAX_NBF_RESOURCE_NAME_LENGTH + 1];
|
|||
|
|
|||
|
INT NumOfDevices;
|
|||
|
PTDI_DATA_DEFINITION pTDIData;
|
|||
|
INT i;
|
|||
|
INT TotalNumberOfResources;
|
|||
|
|
|||
|
// variables used for error logging
|
|||
|
|
|||
|
DWORD dwDataReturn[2];
|
|||
|
DWORD dwQueryType;
|
|||
|
|
|||
|
if (lpValueName == NULL) {
|
|||
|
REPORT_INFORMATION (TDI_COLLECT_ENTERED, LOG_VERBOSE);
|
|||
|
} else {
|
|||
|
REPORT_INFORMATION_DATA (TDI_COLLECT_ENTERED,
|
|||
|
LOG_VERBOSE,
|
|||
|
lpValueName,
|
|||
|
(DWORD)(lstrlenW(lpValueName)*sizeof(WCHAR)));
|
|||
|
}
|
|||
|
//
|
|||
|
// before doing anything else,
|
|||
|
// see if this is a foreign (i.e. non-NT) computer data request
|
|||
|
//
|
|||
|
dwQueryType = GetQueryType (lpValueName);
|
|||
|
|
|||
|
if ((dwQueryType == QUERY_COSTLY) || (dwQueryType == QUERY_FOREIGN)) {
|
|||
|
// NBF foriegn data requests are not supported so bail out
|
|||
|
REPORT_INFORMATION (TDI_FOREIGN_DATA_REQUEST, LOG_VERBOSE);
|
|||
|
*lpcbTotalBytes = (DWORD) 0;
|
|||
|
*lpNumObjectTypes = (DWORD) 0;
|
|||
|
return ERROR_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
if (dwQueryType == QUERY_ITEMS){
|
|||
|
if (CurrentProtocol == NBF_PROTOCOL) {
|
|||
|
if ( !(IsNumberInUnicodeList (ObjectNameTitleIndices[CurrentProtocol],
|
|||
|
lpValueName)) &&
|
|||
|
!(IsNumberInUnicodeList (NBF_RESOURCE_OBJECT_TITLE_INDEX,
|
|||
|
lpValueName))) {
|
|||
|
|
|||
|
// request received for objects not provided by NBF
|
|||
|
|
|||
|
REPORT_INFORMATION (TDI_UNSUPPORTED_ITEM_REQUEST, LOG_VERBOSE);
|
|||
|
|
|||
|
*lpcbTotalBytes = (DWORD) 0;
|
|||
|
*lpNumObjectTypes = (DWORD) 0;
|
|||
|
return ERROR_SUCCESS;
|
|||
|
}
|
|||
|
} // NBF_PROTOCOL
|
|||
|
else if ( !(IsNumberInUnicodeList (ObjectNameTitleIndices[CurrentProtocol],
|
|||
|
lpValueName))) {
|
|||
|
// request received for objects not provided by this protocol
|
|||
|
REPORT_INFORMATION (TDI_UNSUPPORTED_ITEM_REQUEST, LOG_VERBOSE);
|
|||
|
*lpcbTotalBytes = (DWORD) 0;
|
|||
|
*lpNumObjectTypes = (DWORD) 0;
|
|||
|
return ERROR_SUCCESS;
|
|||
|
} // other protocol
|
|||
|
} // dwQueryType == QUERY_ITEMS
|
|||
|
|
|||
|
// if no NBF devices were opened, in the OPEN routine, then
|
|||
|
// leave now.
|
|||
|
|
|||
|
if (TDITbl[CurrentProtocol].pTDIData == NULL) {
|
|||
|
REPORT_WARNING (TDI_NULL_HANDLE, LOG_DEBUG);
|
|||
|
*lpcbTotalBytes = (DWORD) 0;
|
|||
|
*lpNumObjectTypes = (DWORD) 0;
|
|||
|
return ERROR_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
pNbfDataDefinition = (NBF_DATA_DEFINITION *) *lppData;
|
|||
|
|
|||
|
pTDIData = TDITbl[CurrentProtocol].pTDIData;
|
|||
|
NumOfDevices = TDITbl[CurrentProtocol].NumOfDevices;
|
|||
|
|
|||
|
// Compute space needed to hold Nbf Resource Data
|
|||
|
|
|||
|
if (CurrentProtocol != NBF_PROTOCOL) {
|
|||
|
ResourceSpace = 0;
|
|||
|
} else {
|
|||
|
ResourceSpace = sizeof(NBF_RESOURCE_DATA_DEFINITION) +
|
|||
|
(TDITbl[CurrentProtocol].MaxNumOfResources *
|
|||
|
(sizeof(PERF_INSTANCE_DEFINITION) +
|
|||
|
QWORD_MULTIPLE(
|
|||
|
(MAX_NBF_RESOURCE_NAME_LENGTH * sizeof(WCHAR)) +
|
|||
|
sizeof(UNICODE_NULL)) +
|
|||
|
SIZE_OF_NBF_RESOURCE_DATA));
|
|||
|
ResourceSpace *= NumOfDevices;
|
|||
|
}
|
|||
|
|
|||
|
SpaceNeeded = sizeof(NBF_DATA_DEFINITION) +
|
|||
|
SIZE_OF_NBF_DATA +
|
|||
|
ResourceSpace;
|
|||
|
|
|||
|
// now add in the per instance NBF data
|
|||
|
SpaceNeeded += NumOfDevices *
|
|||
|
(SIZE_OF_NBF_DATA +
|
|||
|
sizeof(PERF_INSTANCE_DEFINITION) +
|
|||
|
QWORD_MULTIPLE(
|
|||
|
(TDITbl[CurrentProtocol].MaxDeviceName * sizeof(WCHAR))
|
|||
|
+ sizeof(UNICODE_NULL)));
|
|||
|
|
|||
|
if ( *lpcbTotalBytes < SpaceNeeded ) {
|
|||
|
dwDataReturn[0] = *lpcbTotalBytes;
|
|||
|
dwDataReturn[1] = SpaceNeeded;
|
|||
|
REPORT_WARNING_DATA (TDI_DATA_BUFFER_SIZE_ERROR,
|
|||
|
LOG_DEBUG,
|
|||
|
&dwDataReturn,
|
|||
|
sizeof(dwDataReturn));
|
|||
|
*lpcbTotalBytes = (DWORD) 0;
|
|||
|
*lpNumObjectTypes = (DWORD) 0;
|
|||
|
return ERROR_MORE_DATA;
|
|||
|
}
|
|||
|
|
|||
|
REPORT_INFORMATION (TDI_DATA_BUFFER_SIZE_SUCCESS, LOG_VERBOSE);
|
|||
|
|
|||
|
//
|
|||
|
// Copy the (constant, initialized) Object Type and counter definitions
|
|||
|
//
|
|||
|
|
|||
|
RtlMoveMemory(pNbfDataDefinition,
|
|||
|
&NbfDataDefinition,
|
|||
|
sizeof(NBF_DATA_DEFINITION));
|
|||
|
|
|||
|
pNbfDataDefinition->NbfObjectType.ObjectNameTitleIndex =
|
|||
|
ObjectNameTitleIndices[CurrentProtocol];
|
|||
|
|
|||
|
pNbfDataDefinition->NbfObjectType.ObjectHelpTitleIndex =
|
|||
|
ObjectNameTitleIndices[CurrentProtocol] + 1;
|
|||
|
|
|||
|
pPerfInstanceDefinition = (PERF_INSTANCE_DEFINITION *)
|
|||
|
&pNbfDataDefinition[1];
|
|||
|
|
|||
|
if (NumOfDevices > 0) {
|
|||
|
for (i=0; i < NumOfDevices; i++, pTDIData++) {
|
|||
|
//
|
|||
|
// Format and collect Nbf data
|
|||
|
//
|
|||
|
|
|||
|
QueryInfo.QueryType = TDI_QUERY_PROVIDER_STATISTICS;
|
|||
|
|
|||
|
Status = NtDeviceIoControlFile(
|
|||
|
pTDIData->fileHandle,
|
|||
|
NULL,
|
|||
|
NULL,
|
|||
|
NULL,
|
|||
|
&IoStatusBlock,
|
|||
|
IOCTL_TDI_QUERY_INFORMATION,
|
|||
|
(PVOID)&QueryInfo,
|
|||
|
sizeof(TDI_REQUEST_USER_QUERY_INFO),
|
|||
|
(PVOID)ProviderStats,
|
|||
|
ProviderStatsLength);
|
|||
|
|
|||
|
if (Status != STATUS_SUCCESS) {
|
|||
|
REPORT_ERROR (TDI_UNABLE_READ_DEVICE, LOG_DEBUG);
|
|||
|
REPORT_ERROR_DATA (TDI_QUERY_INFO_ERROR,
|
|||
|
LOG_DEBUG,
|
|||
|
&IoStatusBlock,
|
|||
|
sizeof (IoStatusBlock));
|
|||
|
*lpcbTotalBytes = (DWORD) 0;
|
|||
|
*lpNumObjectTypes = (DWORD) 0;
|
|||
|
return ERROR_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
REPORT_INFORMATION (TDI_QUERY_INFO_SUCCESS, LOG_DEBUG);
|
|||
|
|
|||
|
|
|||
|
MonBuildInstanceDefinition(
|
|||
|
pPerfInstanceDefinition,
|
|||
|
(PVOID *)&pPerfCounterBlock,
|
|||
|
0,
|
|||
|
0,
|
|||
|
(DWORD)PERF_NO_UNIQUE_ID,
|
|||
|
&(pTDIData->DeviceName));
|
|||
|
|
|||
|
|
|||
|
pPerfCounterBlock->ByteLength = SIZE_OF_NBF_DATA;
|
|||
|
|
|||
|
pdwCounter = (PDWORD) (&pPerfCounterBlock[1]);
|
|||
|
|
|||
|
*pdwCounter = ProviderStats->DatagramsSent +
|
|||
|
ProviderStats->DatagramsReceived;
|
|||
|
|
|||
|
pliCounter = (LARGE_INTEGER UNALIGNED *) ++pdwCounter;
|
|||
|
pliDatagramBytes = pliCounter;
|
|||
|
pliCounter->QuadPart = ProviderStats->DatagramBytesSent.QuadPart +
|
|||
|
ProviderStats->DatagramBytesReceived.QuadPart;
|
|||
|
pdwCounter = (PDWORD) ++pliCounter;
|
|||
|
*pdwCounter = ProviderStats->PacketsSent + ProviderStats->PacketsReceived;
|
|||
|
*++pdwCounter = ProviderStats->DataFramesSent +
|
|||
|
ProviderStats->DataFramesReceived;
|
|||
|
|
|||
|
pliCounter = (LARGE_INTEGER UNALIGNED *) ++pdwCounter;
|
|||
|
pliFrameBytes = pliCounter;
|
|||
|
pliCounter->QuadPart = ProviderStats->DataFrameBytesSent.QuadPart +
|
|||
|
ProviderStats->DataFrameBytesReceived.QuadPart;
|
|||
|
|
|||
|
// Get the Bytes Total/sec which is the sum of Frame Byte /sec
|
|||
|
// and Datagram byte/sec
|
|||
|
++pliCounter;
|
|||
|
pliCounter->QuadPart = pliDatagramBytes->QuadPart +
|
|||
|
pliFrameBytes->QuadPart;
|
|||
|
//
|
|||
|
// Get the TDI raw data.
|
|||
|
//
|
|||
|
pdwCounter = (PDWORD) ++pliCounter;
|
|||
|
*pdwCounter = ProviderStats->OpenConnections;
|
|||
|
*++pdwCounter = ProviderStats->ConnectionsAfterNoRetry;
|
|||
|
*++pdwCounter = ProviderStats->ConnectionsAfterRetry;
|
|||
|
*++pdwCounter = ProviderStats->LocalDisconnects;
|
|||
|
*++pdwCounter = ProviderStats->RemoteDisconnects;
|
|||
|
*++pdwCounter = ProviderStats->LinkFailures;
|
|||
|
*++pdwCounter = ProviderStats->AdapterFailures;
|
|||
|
*++pdwCounter = ProviderStats->SessionTimeouts;
|
|||
|
*++pdwCounter = ProviderStats->CancelledConnections;
|
|||
|
*++pdwCounter = ProviderStats->RemoteResourceFailures;
|
|||
|
*++pdwCounter = ProviderStats->LocalResourceFailures;
|
|||
|
*++pdwCounter = ProviderStats->NotFoundFailures;
|
|||
|
*++pdwCounter = ProviderStats->NoListenFailures;
|
|||
|
*++pdwCounter = ProviderStats->DatagramsSent;
|
|||
|
|
|||
|
pliCounter = (LARGE_INTEGER UNALIGNED *) ++pdwCounter;
|
|||
|
*pliCounter = ProviderStats->DatagramBytesSent;
|
|||
|
|
|||
|
pdwCounter = (PDWORD) ++pliCounter;
|
|||
|
*pdwCounter = ProviderStats->DatagramsReceived;
|
|||
|
|
|||
|
pliCounter = (LARGE_INTEGER UNALIGNED *) ++pdwCounter;
|
|||
|
*pliCounter = ProviderStats->DatagramBytesReceived;
|
|||
|
|
|||
|
pdwCounter = (PDWORD) ++pliCounter;
|
|||
|
*pdwCounter = ProviderStats->PacketsSent;
|
|||
|
*++pdwCounter = ProviderStats->PacketsReceived;
|
|||
|
*++pdwCounter = ProviderStats->DataFramesSent;
|
|||
|
|
|||
|
pliCounter = (LARGE_INTEGER UNALIGNED *) ++pdwCounter;
|
|||
|
*pliCounter = ProviderStats->DataFrameBytesSent;
|
|||
|
|
|||
|
pdwCounter = (PDWORD) ++pliCounter;
|
|||
|
*pdwCounter = ProviderStats->DataFramesReceived;
|
|||
|
|
|||
|
pliCounter = (LARGE_INTEGER UNALIGNED *) ++pdwCounter;
|
|||
|
*pliCounter = ProviderStats->DataFrameBytesReceived;
|
|||
|
|
|||
|
pdwCounter = (PDWORD) ++pliCounter;
|
|||
|
*pdwCounter = ProviderStats->DataFramesResent;
|
|||
|
|
|||
|
pliCounter = (LARGE_INTEGER UNALIGNED *) ++pdwCounter;
|
|||
|
*pliCounter = ProviderStats->DataFrameBytesResent;
|
|||
|
|
|||
|
pdwCounter = (PDWORD) ++pliCounter;
|
|||
|
*pdwCounter = ProviderStats->DataFramesRejected;
|
|||
|
|
|||
|
pliCounter = (LARGE_INTEGER UNALIGNED *) ++pdwCounter;
|
|||
|
*pliCounter = ProviderStats->DataFrameBytesRejected;
|
|||
|
|
|||
|
pdwCounter = (PDWORD) ++pliCounter;
|
|||
|
*pdwCounter = ProviderStats->ResponseTimerExpirations;
|
|||
|
*++pdwCounter = ProviderStats->AckTimerExpirations;
|
|||
|
*++pdwCounter = ProviderStats->MaximumSendWindow;
|
|||
|
*++pdwCounter = ProviderStats->AverageSendWindow;
|
|||
|
*++pdwCounter = ProviderStats->PiggybackAckQueued;
|
|||
|
*++pdwCounter = ProviderStats->PiggybackAckTimeouts;
|
|||
|
*++pdwCounter = 0; //reserved
|
|||
|
|
|||
|
pPerfInstanceDefinition = (PERF_INSTANCE_DEFINITION *)
|
|||
|
((PBYTE) pPerfCounterBlock +
|
|||
|
SIZE_OF_NBF_DATA);
|
|||
|
}
|
|||
|
|
|||
|
pNbfResourceDataDefinition = (NBF_RESOURCE_DATA_DEFINITION *)
|
|||
|
++pdwCounter;
|
|||
|
} else {
|
|||
|
pNbfResourceDataDefinition = (NBF_RESOURCE_DATA_DEFINITION *)
|
|||
|
pPerfInstanceDefinition;
|
|||
|
}
|
|||
|
|
|||
|
TotalNumberOfResources = 0;
|
|||
|
|
|||
|
pNbfDataDefinition->NbfObjectType.NumInstances = NumOfDevices;
|
|||
|
pNbfDataDefinition->NbfObjectType.TotalByteLength =
|
|||
|
(DWORD)((PBYTE) pdwCounter - (PBYTE) pNbfDataDefinition);
|
|||
|
|
|||
|
if (CurrentProtocol == NBF_PROTOCOL) {
|
|||
|
|
|||
|
RtlMoveMemory(pNbfResourceDataDefinition,
|
|||
|
&NbfResourceDataDefinition,
|
|||
|
sizeof(NBF_RESOURCE_DATA_DEFINITION));
|
|||
|
|
|||
|
pPerfInstanceDefinition = (PERF_INSTANCE_DEFINITION *)
|
|||
|
&pNbfResourceDataDefinition[1];
|
|||
|
|
|||
|
pTDIData = TDITbl[CurrentProtocol].pTDIData;
|
|||
|
|
|||
|
for (i = 0; i < NumOfDevices; i++, pTDIData++) {
|
|||
|
// for most cases, we will have only one deivce,
|
|||
|
// then we could just use the ProviderStats read
|
|||
|
// for NBF data.
|
|||
|
if (NumOfDevices > 1) {
|
|||
|
// need to read ProviderStat again for multiple devices
|
|||
|
QueryInfo.QueryType = TDI_QUERY_PROVIDER_STATISTICS;
|
|||
|
|
|||
|
Status = NtDeviceIoControlFile(
|
|||
|
pTDIData->fileHandle,
|
|||
|
NULL,
|
|||
|
NULL,
|
|||
|
NULL,
|
|||
|
&IoStatusBlock,
|
|||
|
IOCTL_TDI_QUERY_INFORMATION,
|
|||
|
(PVOID)&QueryInfo,
|
|||
|
sizeof(TDI_REQUEST_USER_QUERY_INFO),
|
|||
|
(PVOID)ProviderStats,
|
|||
|
ProviderStatsLength);
|
|||
|
|
|||
|
if (Status != STATUS_SUCCESS) {
|
|||
|
REPORT_ERROR (TDI_UNABLE_READ_DEVICE, LOG_DEBUG);
|
|||
|
REPORT_ERROR_DATA (TDI_QUERY_INFO_ERROR,
|
|||
|
LOG_DEBUG,
|
|||
|
&IoStatusBlock,
|
|||
|
sizeof (IoStatusBlock));
|
|||
|
*lpcbTotalBytes = (DWORD) 0;
|
|||
|
*lpNumObjectTypes = (DWORD) 0;
|
|||
|
return ERROR_SUCCESS;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
TotalNumberOfResources += pTDIData->NumberOfResources;
|
|||
|
|
|||
|
for ( NumResource = 0;
|
|||
|
NumResource < pTDIData->NumberOfResources;
|
|||
|
NumResource++ ) {
|
|||
|
|
|||
|
//
|
|||
|
// Format and collect Nbf Resource data
|
|||
|
//
|
|||
|
|
|||
|
if (NumResource < NUMBER_OF_NAMES) {
|
|||
|
RtlInitUnicodeString(&ResourceName,
|
|||
|
NetResourceName[NumResource]);
|
|||
|
} else {
|
|||
|
ResourceName.Length = 0;
|
|||
|
ResourceName.MaximumLength = MAX_NBF_RESOURCE_NAME_LENGTH +
|
|||
|
sizeof(UNICODE_NULL);
|
|||
|
ResourceName.Buffer = ResourceNameBuffer;
|
|||
|
RtlIntegerToUnicodeString(NumResource,
|
|||
|
10,
|
|||
|
&ResourceName);
|
|||
|
}
|
|||
|
|
|||
|
MonBuildInstanceDefinition(
|
|||
|
pPerfInstanceDefinition,
|
|||
|
(PVOID *)&pPerfCounterBlock,
|
|||
|
ObjectNameTitleIndices[CurrentProtocol],
|
|||
|
i,
|
|||
|
(DWORD)PERF_NO_UNIQUE_ID,
|
|||
|
&ResourceName);
|
|||
|
|
|||
|
pPerfCounterBlock->ByteLength = SIZE_OF_NBF_RESOURCE_DATA;
|
|||
|
|
|||
|
pdwCounter = (PDWORD)&pPerfCounterBlock[1]; // define pointer to first
|
|||
|
// counter in block
|
|||
|
*pdwCounter++ =
|
|||
|
ProviderStats->ResourceStats[NumResource].MaximumResourceUsed;
|
|||
|
*pdwCounter++ =
|
|||
|
ProviderStats->ResourceStats[NumResource].AverageResourceUsed;
|
|||
|
*pdwCounter++ =
|
|||
|
ProviderStats->ResourceStats[NumResource].ResourceExhausted;
|
|||
|
|
|||
|
// set pointer to where next instance buffer should show up
|
|||
|
|
|||
|
pPerfInstanceDefinition = (PERF_INSTANCE_DEFINITION *)
|
|||
|
((PBYTE) pPerfCounterBlock +
|
|||
|
SIZE_OF_NBF_RESOURCE_DATA);
|
|||
|
// set for loop termination
|
|||
|
|
|||
|
pdwCounter = (PDWORD) pPerfInstanceDefinition;
|
|||
|
|
|||
|
} // NumberOfResources
|
|||
|
} // NumOfDevices
|
|||
|
} // NBF_PROTOCOL
|
|||
|
|
|||
|
*lppData = pdwCounter;
|
|||
|
|
|||
|
pNbfResourceDataDefinition->NbfResourceObjectType.TotalByteLength =
|
|||
|
(DWORD)((PBYTE) pdwCounter - (PBYTE) pNbfResourceDataDefinition);
|
|||
|
|
|||
|
if (CurrentProtocol != NBF_PROTOCOL) {
|
|||
|
*lpNumObjectTypes = 1;
|
|||
|
// bytes used are those of the first (i.e. only) object returned
|
|||
|
*lpcbTotalBytes = pNbfDataDefinition->NbfObjectType.TotalByteLength;
|
|||
|
} else {
|
|||
|
// set count of object types returned
|
|||
|
*lpNumObjectTypes = NBF_NUM_PERF_OBJECT_TYPES;
|
|||
|
// set length of this object
|
|||
|
*lpcbTotalBytes;
|
|||
|
// note the bytes used by first object
|
|||
|
*lpcbTotalBytes = pNbfDataDefinition->NbfObjectType.TotalByteLength;
|
|||
|
// add the bytes used by the second object
|
|||
|
*lpcbTotalBytes +=
|
|||
|
pNbfResourceDataDefinition->NbfResourceObjectType.TotalByteLength;
|
|||
|
// set number of instances loaded
|
|||
|
pNbfResourceDataDefinition->NbfResourceObjectType.NumInstances =
|
|||
|
TotalNumberOfResources;
|
|||
|
}
|
|||
|
|
|||
|
REPORT_INFORMATION (TDI_COLLECT_DATA, LOG_DEBUG);
|
|||
|
return ERROR_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
DWORD
|
|||
|
CloseNbfPerformanceData(
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine closes the open handles to Nbf devices.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_SUCCESS
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
return CloseTDIPerformanceData(NBF_PROTOCOL);
|
|||
|
}
|
|||
|
|
|||
|
DWORD
|
|||
|
CloseIPXPerformanceData(
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine closes the open handles to IPX devices.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_SUCCESS
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
return CloseTDIPerformanceData(IPX_PROTOCOL);
|
|||
|
}
|
|||
|
|
|||
|
DWORD
|
|||
|
CloseSPXPerformanceData(
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine closes the open handles to SPX devices.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_SUCCESS
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
return CloseTDIPerformanceData(SPX_PROTOCOL);
|
|||
|
}
|
|||
|
|
|||
|
DWORD
|
|||
|
CloseNWNBPerformanceData(
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine closes the open handles to NWNB devices.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_SUCCESS
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
return CloseTDIPerformanceData(NWNB_PROTOCOL);
|
|||
|
}
|
|||
|
|
|||
|
DWORD
|
|||
|
CloseTDIPerformanceData(
|
|||
|
DWORD CurrentProtocol
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine closes the open handles to TDI devices.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Current protocol index.
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_SUCCESS
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
REPORT_INFORMATION (TDI_CLOSE_ENTERED, LOG_VERBOSE);
|
|||
|
|
|||
|
if (dwTdiProtocolRefCount[CurrentProtocol] > 0) {
|
|||
|
dwTdiProtocolRefCount[CurrentProtocol]--;
|
|||
|
if (dwTdiProtocolRefCount[CurrentProtocol] == 0) {
|
|||
|
CleanUpTDIData (CurrentProtocol);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (dwTdiRefCount > 0) {
|
|||
|
dwTdiRefCount--;
|
|||
|
if (dwTdiRefCount == 0) {
|
|||
|
if ( ProviderStats ) {
|
|||
|
RtlFreeHeap(RtlProcessHeap(), 0, ProviderStats);
|
|||
|
ProviderStats = NULL;
|
|||
|
REPORT_INFORMATION (TDI_PROVIDER_STATS_FREED, LOG_VERBOSE);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
MonCloseEventLog ();
|
|||
|
|
|||
|
return ERROR_SUCCESS;
|
|||
|
|
|||
|
}
|
|||
|
|