283 lines
8.8 KiB
C
283 lines
8.8 KiB
C
/*++
|
||
|
||
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"
|
||
|
||
static HANDLE hRdr = NULL;
|
||
|
||
DWORD APIENTRY
|
||
OpenRedirObject (
|
||
IN LPWSTR lpValueName
|
||
)
|
||
{
|
||
UNICODE_STRING DeviceNameU;
|
||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||
IO_STATUS_BLOCK IoStatusBlock;
|
||
NTSTATUS status;
|
||
RTL_RELATIVE_NAME RelativeName;
|
||
|
||
UNREFERENCED_PARAMETER (lpValueName);
|
||
|
||
// open the handle to the server for data collection
|
||
//
|
||
// Now get access to the Redirector for its data
|
||
//
|
||
|
||
RtlInitUnicodeString(&DeviceNameU, (LPCWSTR)DD_NFS_DEVICE_NAME_U);
|
||
RelativeName.ContainingDirectory = NULL;
|
||
|
||
InitializeObjectAttributes(&ObjectAttributes,
|
||
&DeviceNameU,
|
||
OBJ_CASE_INSENSITIVE,
|
||
RelativeName.ContainingDirectory,
|
||
NULL
|
||
);
|
||
|
||
status = NtCreateFile(&hRdr,
|
||
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)) {
|
||
ReportEvent (hEventLog,
|
||
EVENTLOG_ERROR_TYPE,
|
||
0,
|
||
PERFNET_UNABLE_OPEN_REDIR,
|
||
NULL,
|
||
0,
|
||
sizeof(DWORD),
|
||
NULL,
|
||
(LPVOID)&status);
|
||
}
|
||
|
||
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 = 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
|
||
//
|
||
|
||
ReportEvent (hEventLog,
|
||
EVENTLOG_ERROR_TYPE,
|
||
0,
|
||
PERFNET_UNABLE_READ_REDIR,
|
||
NULL,
|
||
0,
|
||
sizeof(DWORD),
|
||
NULL,
|
||
(LPVOID)&Status);
|
||
|
||
memset(pRCD, 0, sizeof(RDR_COUNTER_DATA));
|
||
pRCD->CounterBlock.ByteLength = sizeof (RDR_COUNTER_DATA);
|
||
|
||
}
|
||
|
||
*lppData = (LPVOID)&pRCD[1];
|
||
|
||
*lpcbTotalBytes = (DWORD)((LPBYTE)&pRCD[1] - (LPBYTE)pRdrDataDefinition);
|
||
*lpNumObjectTypes = 1;
|
||
|
||
return ERROR_SUCCESS;
|
||
}
|
||
|
||
DWORD APIENTRY
|
||
CloseRedirObject ()
|
||
{
|
||
if (hRdr != NULL) {
|
||
NtClose(hRdr);
|
||
hRdr = NULL;
|
||
}
|
||
|
||
return ERROR_SUCCESS;
|
||
}
|