|
|
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
perfrdr.c
Abstract:
This file implements a Performance Object that presents Redirector Performance object data
Created:
Bob Watson 22-Oct-1996
Revision History
--*/ //
// Include Files
//
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <ntddnfs.h>
#include <ntioapi.h>
#include <windows.h>
#include <assert.h>
#include <srvfsctl.h>
#include <winperf.h>
#include <ntprfctr.h>
#include <perfutil.h>
#include "perfnet.h"
#include "netsvcmc.h"
#include "datardr.h"
HANDLE hRdr = NULL; BOOL bRdrError = FALSE; // Log only one event per process
DWORD APIENTRY OpenRedirObject ( IN LPWSTR lpValueName ) { UNICODE_STRING DeviceNameU; OBJECT_ATTRIBUTES ObjectAttributes; IO_STATUS_BLOCK IoStatusBlock; NTSTATUS status; HANDLE hLocalRdr = NULL;
UNREFERENCED_PARAMETER (lpValueName);
// open the handle to the server for data collection
//
// Now get access to the Redirector for its data
//
RtlInitUnicodeString(&DeviceNameU, DD_NFS_DEVICE_NAME_U);
InitializeObjectAttributes(&ObjectAttributes, &DeviceNameU, OBJ_CASE_INSENSITIVE, NULL, NULL );
status = NtCreateFile(&hLocalRdr, SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
if (!NT_SUCCESS(status)) { if (!bRdrError) { ReportEvent (hEventLog, EVENTLOG_ERROR_TYPE, 0, PERFNET_UNABLE_OPEN_REDIR, NULL, 0, sizeof(DWORD), NULL, (LPVOID)&status); bRdrError = TRUE; } } else { if (InterlockedCompareExchangePointer( &hRdr, hLocalRdr, NULL) != NULL) { //
// Replace only if the global handle is NULL
//
NtClose(hLocalRdr); // close duplicate handle
} }
return (DWORD)RtlNtStatusToDosError(status);
}
DWORD APIENTRY CollectRedirObjectData( IN OUT LPVOID *lppData, IN OUT LPDWORD lpcbTotalBytes, IN OUT LPDWORD lpNumObjectTypes ) /*++
Routine Description:
This routine will return the data for the Physical Disk object
Arguments:
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
Returns:
0 if successful, else Win 32 error code of failure
--*/ {
DWORD TotalLen; // Length of the total return block
NTSTATUS Status = ERROR_SUCCESS; IO_STATUS_BLOCK IoStatusBlock;
RDR_DATA_DEFINITION *pRdrDataDefinition; RDR_COUNTER_DATA *pRCD;
REDIR_STATISTICS RdrStatistics;
if ( hRdr == NULL ) { // redir didn't get opened and it has already been logged
*lpcbTotalBytes = (DWORD) 0; *lpNumObjectTypes = (DWORD) 0; return ERROR_SUCCESS; } //
// Check for sufficient space for redirector data
//
TotalLen = sizeof(RDR_DATA_DEFINITION) + sizeof(RDR_COUNTER_DATA);
if ( *lpcbTotalBytes < TotalLen ) { *lpcbTotalBytes = (DWORD) 0; *lpNumObjectTypes = (DWORD) 0; return ERROR_MORE_DATA; }
//
// Define objects data block
//
pRdrDataDefinition = (RDR_DATA_DEFINITION *) *lppData;
memcpy (pRdrDataDefinition, &RdrDataDefinition, sizeof(RDR_DATA_DEFINITION));
//
// Format and collect redirector data
//
pRCD = (PRDR_COUNTER_DATA)&pRdrDataDefinition[1];
// test for quadword alignment of the structure
assert (((DWORD)(pRCD) & 0x00000007) == 0);
pRCD->CounterBlock.ByteLength = QWORD_MULTIPLE(sizeof (RDR_COUNTER_DATA));
Status = NtFsControlFile(hRdr, NULL, NULL, NULL, &IoStatusBlock, FSCTL_LMR_GET_STATISTICS, NULL, 0, &RdrStatistics, sizeof(RdrStatistics) ); if (NT_SUCCESS(Status)) { // transfer Redir data
pRCD->Bytes = RdrStatistics.BytesReceived.QuadPart + RdrStatistics.BytesTransmitted.QuadPart; pRCD->IoOperations = RdrStatistics.ReadOperations + RdrStatistics.WriteOperations; pRCD->Smbs = RdrStatistics.SmbsReceived.QuadPart + RdrStatistics.SmbsTransmitted.QuadPart; pRCD->BytesReceived = RdrStatistics.BytesReceived.QuadPart; pRCD->SmbsReceived = RdrStatistics.SmbsReceived.QuadPart; pRCD->PagingReadBytesRequested = RdrStatistics.PagingReadBytesRequested.QuadPart; pRCD->NonPagingReadBytesRequested = RdrStatistics.NonPagingReadBytesRequested.QuadPart; pRCD->CacheReadBytesRequested = RdrStatistics.CacheReadBytesRequested.QuadPart; pRCD->NetworkReadBytesRequested = RdrStatistics.NetworkReadBytesRequested.QuadPart; pRCD->BytesTransmitted = RdrStatistics.BytesTransmitted.QuadPart; pRCD->SmbsTransmitted = RdrStatistics.SmbsTransmitted.QuadPart; pRCD->PagingWriteBytesRequested = RdrStatistics.PagingWriteBytesRequested.QuadPart; pRCD->NonPagingWriteBytesRequested = RdrStatistics.NonPagingWriteBytesRequested.QuadPart; pRCD->CacheWriteBytesRequested = RdrStatistics.CacheWriteBytesRequested.QuadPart; pRCD->NetworkWriteBytesRequested = RdrStatistics.NetworkWriteBytesRequested.QuadPart; pRCD->ReadOperations = RdrStatistics.ReadOperations; pRCD->RandomReadOperations = RdrStatistics.RandomReadOperations; pRCD->ReadSmbs = RdrStatistics.ReadSmbs; pRCD->LargeReadSmbs = RdrStatistics.LargeReadSmbs; pRCD->SmallReadSmbs = RdrStatistics.SmallReadSmbs; pRCD->WriteOperations = RdrStatistics.WriteOperations; pRCD->RandomWriteOperations = RdrStatistics.RandomWriteOperations; pRCD->WriteSmbs = RdrStatistics.WriteSmbs; pRCD->LargeWriteSmbs = RdrStatistics.LargeWriteSmbs; pRCD->SmallWriteSmbs = RdrStatistics.SmallWriteSmbs; pRCD->RawReadsDenied = RdrStatistics.RawReadsDenied; pRCD->RawWritesDenied = RdrStatistics.RawWritesDenied; pRCD->NetworkErrors = RdrStatistics.NetworkErrors; pRCD->Sessions = RdrStatistics.Sessions; pRCD->Reconnects = RdrStatistics.Reconnects; pRCD->CoreConnects = RdrStatistics.CoreConnects; pRCD->Lanman20Connects = RdrStatistics.Lanman20Connects; pRCD->Lanman21Connects = RdrStatistics.Lanman21Connects; pRCD->LanmanNtConnects = RdrStatistics.LanmanNtConnects; pRCD->ServerDisconnects = RdrStatistics.ServerDisconnects; pRCD->HungSessions = RdrStatistics.HungSessions; pRCD->CurrentCommands = RdrStatistics.CurrentCommands;
} else {
//
// Failure to access Redirector: clear counters to 0
//
if (!bRdrError) { ReportEvent (hEventLog, EVENTLOG_ERROR_TYPE, 0, PERFNET_UNABLE_READ_REDIR, NULL, 0, sizeof(DWORD), NULL, (LPVOID)&Status); bRdrError = TRUE; }
memset(pRCD, 0, sizeof(RDR_COUNTER_DATA)); pRCD->CounterBlock.ByteLength = QWORD_MULTIPLE(sizeof (RDR_COUNTER_DATA));
} *lpcbTotalBytes = pRdrDataDefinition->RdrObjectType.TotalByteLength = (DWORD) QWORD_MULTIPLE((LPBYTE) &pRCD[1] - (LPBYTE) pRdrDataDefinition); * lppData = (LPVOID) (((LPBYTE) pRdrDataDefinition) + *lpcbTotalBytes); *lpNumObjectTypes = 1;
return ERROR_SUCCESS; }
DWORD APIENTRY CloseRedirObject () { HANDLE hLocalRdr = hRdr;
if (hLocalRdr != NULL) { if (InterlockedCompareExchangePointer( &hRdr, NULL, hLocalRdr) == hLocalRdr) { NtClose(hLocalRdr); } }
return ERROR_SUCCESS; }
|