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.
305 lines
9.9 KiB
305 lines
9.9 KiB
/*++
|
|
|
|
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;
|
|
}
|