/*++ 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 #include #include #include #include #include #include #include #include #include #include #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; }