From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- private/nw/perf/makefile | 6 + private/nw/perf/nwdata.c | 296 +++++++++++++++++++++++++++++++++ private/nw/perf/nwperf.c | 398 +++++++++++++++++++++++++++++++++++++++++++++ private/nw/perf/nwperf.h | 144 ++++++++++++++++ private/nw/perf/nwperf.rc | 11 ++ private/nw/perf/perfnw.def | 8 + private/nw/perf/prfutil.c | 203 +++++++++++++++++++++++ private/nw/perf/prfutil.h | 42 +++++ private/nw/perf/sources | 46 ++++++ 9 files changed, 1154 insertions(+) create mode 100644 private/nw/perf/makefile create mode 100644 private/nw/perf/nwdata.c create mode 100644 private/nw/perf/nwperf.c create mode 100644 private/nw/perf/nwperf.h create mode 100644 private/nw/perf/nwperf.rc create mode 100644 private/nw/perf/perfnw.def create mode 100644 private/nw/perf/prfutil.c create mode 100644 private/nw/perf/prfutil.h create mode 100644 private/nw/perf/sources (limited to 'private/nw/perf') diff --git a/private/nw/perf/makefile b/private/nw/perf/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/nw/perf/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/nw/perf/nwdata.c b/private/nw/perf/nwdata.c new file mode 100644 index 000000000..af2b1b8a3 --- /dev/null +++ b/private/nw/perf/nwdata.c @@ -0,0 +1,296 @@ +// +// NWData.c +// +// This file contains the initalized Object and counter definition for NetWare +// redirector performance extensible DLL. +// This would be the place to add more counters and the change the definitions +// of the current ones. +// +#include "windows.h" +#include +#include "NWPerf.h" + +NW_DATA_DEFINITION NWDataDefinition = { + { sizeof(NW_DATA_DEFINITION)+ + SIZE_OF_COUNTER_BLOCK, // Total Bytes ( Size of this header, the counter definitions + // and the size of the actual counter data ) + sizeof(NW_DATA_DEFINITION), // Definition length ( This header and the counter definitions ) + sizeof(PERF_OBJECT_TYPE), // Header Length ( This header ) + NWOBJ, // Object Name Title Index + 0, // Object Name Title + NWOBJ, // Object Help Title Index + 0, // Object Help Title + PERF_DETAIL_NOVICE, // Detail Level + (sizeof(NW_DATA_DEFINITION)-sizeof(PERF_OBJECT_TYPE))/ + sizeof(PERF_COUNTER_DEFINITION), // Number of Counters + 0, // Default Counters + 0, // Num Instances + 0, // Code Page + {0,0}, // Perf Time + {0,0} // Perf Freq + }, + { sizeof(PERF_COUNTER_DEFINITION), + 388, + 0, + 389, + 0, + -4, + PERF_DETAIL_NOVICE, + PERF_COUNTER_BULK_COUNT, + sizeof(LARGE_INTEGER), + BYTES_OFFSET + }, + { sizeof(PERF_COUNTER_DEFINITION), + 406, + 0, + 391, + 0, + 0, + PERF_DETAIL_NOVICE, + PERF_COUNTER_COUNTER, + sizeof(DWORD), + IO_OPERATIONS_OFFSET + }, + { sizeof(PERF_COUNTER_DEFINITION), + 400, + 0, + 401, + 0, + -1, + PERF_DETAIL_NOVICE, + PERF_COUNTER_BULK_COUNT, + sizeof(LARGE_INTEGER), + PACKETS_OFFSET + }, + { sizeof(PERF_COUNTER_DEFINITION), + 264, + 0, + 265, + 0, + -4, + PERF_DETAIL_ADVANCED, + PERF_COUNTER_BULK_COUNT, + sizeof(LARGE_INTEGER), + BYTES_RECEIVED_OFFSET + }, + { sizeof(PERF_COUNTER_DEFINITION), + 266, + 0, + 267, + 0, + -1, + PERF_DETAIL_ADVANCED, + PERF_COUNTER_BULK_COUNT, + sizeof(LARGE_INTEGER), + NCPS_RECEIVED_OFFSET + }, + { sizeof(PERF_COUNTER_DEFINITION), + 276, + 0, + 277, + 0, + -4, + PERF_DETAIL_ADVANCED, + PERF_COUNTER_BULK_COUNT, + sizeof(LARGE_INTEGER), + BYTES_TRANSMITTED_OFFSET + }, + { sizeof(PERF_COUNTER_DEFINITION), + 278, + 0, + 279, + 0, + -1, + PERF_DETAIL_ADVANCED, + PERF_COUNTER_BULK_COUNT, + sizeof(LARGE_INTEGER), + NCPS_TRANSMITTED_OFFSET + }, + { sizeof(PERF_COUNTER_DEFINITION), + 10, + 0, + 289, + 0, + 0, + PERF_DETAIL_NOVICE, + PERF_COUNTER_COUNTER, + sizeof(DWORD), + RDR_READ_OPERATIONS_OFFSET + }, + { sizeof(PERF_COUNTER_DEFINITION), + 290, + 0, + 291, + 0, + -1, + PERF_DETAIL_ADVANCED, + PERF_COUNTER_COUNTER, + sizeof(DWORD), + RANDOM_READ_OPERATIONS_OFFSET + }, + { sizeof(PERF_COUNTER_DEFINITION), + 292, + 0, + 293, + 0, + -1, + PERF_DETAIL_ADVANCED, + PERF_COUNTER_COUNTER, + sizeof(DWORD), + READ_NCPS_OFFSET + }, + { sizeof(PERF_COUNTER_DEFINITION), + 12, + 0, + 299, + 0, + 0, + PERF_DETAIL_NOVICE, + PERF_COUNTER_COUNTER, + sizeof(DWORD), + RDR_WRITE_OPERATIONS_OFFSET + }, + { sizeof(PERF_COUNTER_DEFINITION), + 300, + 0, + 301, + 0, + -1, + PERF_DETAIL_ADVANCED, + PERF_COUNTER_COUNTER, + sizeof(DWORD), + RANDOM_WRITE_OPERATIONS_OFFSET + }, + { sizeof(PERF_COUNTER_DEFINITION), + 302, + 0, + 303, + 0, + -1, + PERF_DETAIL_ADVANCED, + PERF_COUNTER_COUNTER, + sizeof(DWORD), + WRITE_NCPS_OFFSET + }, + { sizeof(PERF_COUNTER_DEFINITION), + 314, + 0, + 315, + 0, + 0, + PERF_DETAIL_NOVICE, + PERF_COUNTER_RAWCOUNT, + sizeof(DWORD), + SESSIONS_OFFSET + }, + { sizeof(PERF_COUNTER_DEFINITION), + 316, + 0, + 317, + 0, + 0, + PERF_DETAIL_ADVANCED, + PERF_COUNTER_RAWCOUNT, + sizeof(DWORD), + RECONNECTS_OFFSET + }, + { sizeof(PERF_COUNTER_DEFINITION), + CONNECT_2X_ID, + 0, + CONNECT_2X_ID, + 0, + 0, + PERF_DETAIL_ADVANCED, + PERF_COUNTER_RAWCOUNT, + sizeof(DWORD), + NETWARE_2X_CONNECTS_OFFSET + }, + { sizeof(PERF_COUNTER_DEFINITION), + CONNECT_3X_ID, + 0, + CONNECT_3X_ID, + 0, + 0, + PERF_DETAIL_ADVANCED, + PERF_COUNTER_RAWCOUNT, + sizeof(DWORD), + NETWARE_3X_CONNECTS_OFFSET + }, + { sizeof(PERF_COUNTER_DEFINITION), + CONNECT_4X_ID, + 0, + CONNECT_4X_ID, + 0, + 0, + PERF_DETAIL_ADVANCED, + PERF_COUNTER_RAWCOUNT, + sizeof(DWORD), + NETWARE_4X_CONNECTS_OFFSET + }, + { sizeof(PERF_COUNTER_DEFINITION), + 326, + 0, + 327, + 0, + 0, + PERF_DETAIL_ADVANCED, + PERF_COUNTER_RAWCOUNT, + sizeof(DWORD), + SERVER_DISCONNECTS_OFFSET + }, + { sizeof(PERF_COUNTER_DEFINITION), + PACKET_BURST_READ_ID, + 0, + PACKET_BURST_READ_ID, + 0, + 0, + PERF_DETAIL_ADVANCED, + PERF_COUNTER_COUNTER, + sizeof(DWORD), + PACKET_BURST_READ_OFFSET + }, + { sizeof(PERF_COUNTER_DEFINITION), + PACKET_BURST_READ_TO_ID, + 0, + PACKET_BURST_READ_TO_ID, + 0, + 0, + PERF_DETAIL_ADVANCED, + PERF_COUNTER_COUNTER, + sizeof(DWORD), + PACKET_BURST_READ_TO_OFFSET + }, + { sizeof(PERF_COUNTER_DEFINITION), + PACKET_BURST_WRITE_ID, + 0, + PACKET_BURST_WRITE_ID, + 0, + 0, + PERF_DETAIL_ADVANCED, + PERF_COUNTER_COUNTER, + sizeof(DWORD), + PACKET_BURST_WRITE_OFFSET + }, + { sizeof(PERF_COUNTER_DEFINITION), + PACKET_BURST_WRITE_TO_ID, + 0, + PACKET_BURST_WRITE_TO_ID, + 0, + 0, + PERF_DETAIL_ADVANCED, + PERF_COUNTER_COUNTER, + sizeof(DWORD), + PACKET_BURST_WRITE_TO_OFFSET + }, + { sizeof(PERF_COUNTER_DEFINITION), + PACKET_BURST_IO_ID, + 0, + PACKET_BURST_IO_ID, + 0, + 0, + PERF_DETAIL_ADVANCED, + PERF_COUNTER_COUNTER, + sizeof(DWORD), + PACKET_BURST_IO_OFFSET + } +}; diff --git a/private/nw/perf/nwperf.c b/private/nw/perf/nwperf.c new file mode 100644 index 000000000..28d711e54 --- /dev/null +++ b/private/nw/perf/nwperf.c @@ -0,0 +1,398 @@ +/**************************************************************************** + + PROGRAM: NWPerf.c + + PURPOSE: Contains library routines for providing perfmon with data + + FUNCTIONS: +*******************************************************************************/ +#include +#include +#include +#include +#include +#include +#include "NWPerf.h" +#include "prfutil.h" + +#ifndef QFE_BUILD +#include "ntprfctr.h" +#endif + + + +BOOL gbInitOK = FALSE; + +HANDLE hNetWareRdr ; +extern NW_DATA_DEFINITION NWDataDefinition; + +#ifdef QFE_BUILD +TCHAR PerformanceKeyName [] = + TEXT("SYSTEM\\CurrentControlSet\\Services\\NWrdr\\Performance"); +TCHAR FirstCounterKeyName [] = TEXT("First Counter"); +TCHAR FirstHelpKeyName [] = TEXT("First Help"); +#endif + +/**************************************************************************** + FUNCTION: OpenNetWarePerformanceData + + Purpose: This routine also initializes the data structures used to pass + data back to the registry + + Return: None. +r****************************************************************************/ +DWORD APIENTRY +OpenNetWarePerformanceData( + LPWSTR pInstances ) +{ + + LONG status; +#ifdef QFE_BUILD + HKEY hKeyPerf = 0; + DWORD size; + DWORD type; + DWORD dwFirstCounter; + DWORD dwFirstHelp; +#else + NT_PRODUCT_TYPE ProductType; + DWORD dwFirstCounter = NWCS_CLIENT_COUNTER_INDEX ; + DWORD dwFirstHelp = NWCS_CLIENT_HELP_INDEX ; +#endif + + IO_STATUS_BLOCK IoStatusBlock; + RTL_RELATIVE_NAME RelativeName; + UNICODE_STRING DeviceNameU; + OBJECT_ATTRIBUTES ObjectAttributes; + +#ifdef QFE_BUILD + status = RegOpenKeyEx ( HKEY_LOCAL_MACHINE, + PerformanceKeyName, + 0L, KEY_ALL_ACCESS, &hKeyPerf ); + + if (status != ERROR_SUCCESS) { + goto OpenExitPoint; + } + + size = sizeof (DWORD); + status = RegQueryValueEx( hKeyPerf, FirstCounterKeyName, 0L, &type, + (LPBYTE)&dwFirstCounter, &size); + + if (status != ERROR_SUCCESS) { + goto OpenExitPoint; + } + + size = sizeof (DWORD); + status = RegQueryValueEx( hKeyPerf, FirstHelpKeyName, + 0L, &type, (LPBYTE)&dwFirstHelp, &size ); + + if (status != ERROR_SUCCESS) { + goto OpenExitPoint; + } +#endif + + // + // NOTE: the initialization program could also retrieve + // LastCounter and LastHelp if they wanted to do + // bounds checking on the new number. e.g. + // + // counter->CounterNameTitleIndex += dwFirstCounter; + // if (counter->CounterNameTitleIndex > dwLastCounter) { + // LogErrorToEventLog (INDEX_OUT_OF_BOUNDS); + // } + + NWDataDefinition.NWObjectType.ObjectNameTitleIndex += dwFirstCounter; + NWDataDefinition.NWObjectType.ObjectHelpTitleIndex += dwFirstHelp; + + // Counters not defined in Redirector, setup the correct IDs + NWDataDefinition.PacketBurstRead.CounterNameTitleIndex += dwFirstCounter; + NWDataDefinition.PacketBurstRead.CounterHelpTitleIndex += dwFirstHelp; + NWDataDefinition.PacketBurstReadTimeouts.CounterNameTitleIndex += dwFirstCounter; + NWDataDefinition.PacketBurstReadTimeouts.CounterHelpTitleIndex += dwFirstHelp; + NWDataDefinition.PacketBurstWrite.CounterNameTitleIndex += dwFirstCounter; + NWDataDefinition.PacketBurstWrite.CounterHelpTitleIndex += dwFirstHelp; + NWDataDefinition.PacketBurstWriteTimeouts.CounterNameTitleIndex += dwFirstCounter; + NWDataDefinition.PacketBurstWriteTimeouts.CounterHelpTitleIndex += dwFirstHelp; + NWDataDefinition.PacketBurstIO.CounterNameTitleIndex += dwFirstCounter; + NWDataDefinition.PacketBurstIO.CounterHelpTitleIndex += dwFirstHelp; + NWDataDefinition.NetWare2XConnects.CounterNameTitleIndex += dwFirstCounter; + NWDataDefinition.NetWare2XConnects.CounterHelpTitleIndex += dwFirstHelp; + NWDataDefinition.NetWare3XConnects.CounterNameTitleIndex += dwFirstCounter; + NWDataDefinition.NetWare3XConnects.CounterHelpTitleIndex += dwFirstHelp; + NWDataDefinition.NetWare4XConnects.CounterNameTitleIndex += dwFirstCounter; + NWDataDefinition.NetWare4XConnects.CounterHelpTitleIndex += dwFirstHelp; + + +#ifndef QFE_BUILD + // Check for WorkStation or Server and use the gateway indexes if + // currently running on Server. + // If RtlGetNtProductType is not successful or ProductType is + // WinNt machine, ObjectNameTitleIndex and ObjectHelpTitleIndex are set + // to the correct values already. + if ( RtlGetNtProductType( &ProductType)) + { + if ( ProductType != NtProductWinNt ) + { + NWDataDefinition.NWObjectType.ObjectNameTitleIndex = NWCS_GATEWAY_COUNTER_INDEX; + NWDataDefinition.NWObjectType.ObjectHelpTitleIndex = NWCS_GATEWAY_HELP_INDEX; + } + } +#endif + + hNetWareRdr = NULL; + + RtlInitUnicodeString(&DeviceNameU, DD_NWFS_DEVICE_NAME_U); + RelativeName.ContainingDirectory = NULL; + + InitializeObjectAttributes(&ObjectAttributes, + &DeviceNameU, + OBJ_CASE_INSENSITIVE, + RelativeName.ContainingDirectory, + NULL + ); + + status = NtCreateFile(&hNetWareRdr, + SYNCHRONIZE, + &ObjectAttributes, + &IoStatusBlock, + NULL, + FILE_ATTRIBUTE_NORMAL, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_OPEN_IF, + FILE_SYNCHRONOUS_IO_NONALERT, + NULL, + 0 + ); + + gbInitOK = TRUE; // ok to use this function + + status = ERROR_SUCCESS; // for successful exit + +#ifdef QFE_BUILD +OpenExitPoint: + if (hKeyPerf) + RegCloseKey (hKeyPerf); // close key to registry +#endif + + return ((DWORD) status); +} + + +/**************************************************************************** + FUNCTION: CollectNetWarePerformanceData + + Purpose: This routine will return the data for the NetWare 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 written + 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 written + to the DWORD pointed to by this argument + + Return: 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. + +****************************************************************************/ +DWORD APIENTRY +CollectNetWarePerformanceData( + IN LPWSTR lpValueName, + IN OUT LPVOID *lppData, + IN OUT LPDWORD lpcbTotalBytes, + IN OUT LPDWORD lpNumObjectTypes) +{ + ULONG SpaceNeeded; + PDWORD pdwCounter; + DWORD dwQueryType; + PERF_COUNTER_BLOCK *pPerfCounterBlock; + NW_DATA_DEFINITION *pNWDataDefinition; + LONG status; + NW_REDIR_STATISTICS NWRdrStatistics; + LARGE_INTEGER UNALIGNED *pliCounter; + IO_STATUS_BLOCK IoStatusBlock; + + // + // before doing anything else, see if Open went OK + // + if (!gbInitOK) { + *lpcbTotalBytes = (DWORD) 0; + *lpNumObjectTypes = (DWORD) 0; + return ERROR_SUCCESS; // yes, this is a successful exit + } + + // see if this is a foreign (i.e. non-NT) computer data request + // + dwQueryType = GetQueryType (lpValueName); + + if (dwQueryType == QUERY_FOREIGN) { + // this routine does not service requests for data from + // Non-NT computers + *lpcbTotalBytes = (DWORD) 0; + *lpNumObjectTypes = (DWORD) 0; + return ERROR_SUCCESS; + } + + // If the caller only wanted some counter, check if we have 'em + if (dwQueryType == QUERY_ITEMS){ + if ( !(IsNumberInUnicodeList ( + NWDataDefinition.NWObjectType.ObjectNameTitleIndex, + lpValueName))) { + // request received for data object not provided by this routine + *lpcbTotalBytes = (DWORD) 0; + *lpNumObjectTypes = (DWORD) 0; + return ERROR_SUCCESS; + } + } + + pNWDataDefinition = (NW_DATA_DEFINITION *) *lppData; + + SpaceNeeded = sizeof(NW_DATA_DEFINITION) + SIZE_OF_COUNTER_BLOCK; + + if ( *lpcbTotalBytes < SpaceNeeded ) { + *lpcbTotalBytes = (DWORD) 0; + *lpNumObjectTypes = (DWORD) 0; + return ((DWORD) ERROR_MORE_DATA); + } + + // + // Copy the (constant, initialized) Object Type and counter definitions + // to the caller's data buffer + // + memmove( pNWDataDefinition, &NWDataDefinition, + sizeof(NW_DATA_DEFINITION) ); + + // Point at the byte right after all the definitions + pPerfCounterBlock = (PERF_COUNTER_BLOCK *) &pNWDataDefinition[1]; + + // The first DWORD should specify the size of actual data block + pPerfCounterBlock->ByteLength = SIZE_OF_COUNTER_BLOCK; + + // Move the pointer up + pdwCounter = (PDWORD) (&pPerfCounterBlock[1]); + + + // Open the NetWare data + if ( hNetWareRdr != NULL) { + status = NtFsControlFile(hNetWareRdr, + NULL, + NULL, + NULL, + &IoStatusBlock, + FSCTL_NWR_GET_STATISTICS, + NULL, + 0, + &NWRdrStatistics, + sizeof(NWRdrStatistics) + ); + } + if ( hNetWareRdr != NULL && NT_SUCCESS(status) ) { + + pliCounter = (LARGE_INTEGER UNALIGNED * ) (&pPerfCounterBlock[1]); + + pliCounter->QuadPart = NWRdrStatistics.BytesReceived.QuadPart + + NWRdrStatistics.BytesTransmitted.QuadPart; + + pdwCounter = (PDWORD) ++pliCounter; + *pdwCounter = NWRdrStatistics.ReadOperations + + NWRdrStatistics.WriteOperations; + pliCounter = (LARGE_INTEGER UNALIGNED * ) ++pdwCounter; + pliCounter->QuadPart = NWRdrStatistics.NcpsReceived.QuadPart + + NWRdrStatistics.NcpsTransmitted.QuadPart; + *++pliCounter = NWRdrStatistics.BytesReceived; + *++pliCounter = NWRdrStatistics.NcpsReceived; + *++pliCounter = NWRdrStatistics.BytesTransmitted; + *++pliCounter = NWRdrStatistics.NcpsTransmitted; + pdwCounter = (PDWORD) ++pliCounter; + *pdwCounter = NWRdrStatistics.ReadOperations; + *++pdwCounter = NWRdrStatistics.RandomReadOperations; + *++pdwCounter = NWRdrStatistics.ReadNcps; + *++pdwCounter = NWRdrStatistics.WriteOperations; + *++pdwCounter = NWRdrStatistics.RandomWriteOperations; + *++pdwCounter = NWRdrStatistics.WriteNcps; + *++pdwCounter = NWRdrStatistics.Sessions; + *++pdwCounter = NWRdrStatistics.Reconnects; + *++pdwCounter = NWRdrStatistics.NW2xConnects; + *++pdwCounter = NWRdrStatistics.NW3xConnects; + *++pdwCounter = NWRdrStatistics.NW4xConnects; + *++pdwCounter = NWRdrStatistics.ServerDisconnects; + + *++pdwCounter = NWRdrStatistics.PacketBurstReadNcps; + *++pdwCounter = NWRdrStatistics.PacketBurstReadTimeouts; + *++pdwCounter = NWRdrStatistics.PacketBurstWriteNcps; + *++pdwCounter = NWRdrStatistics.PacketBurstWriteTimeouts; + *++pdwCounter = NWRdrStatistics.PacketBurstReadNcps + + NWRdrStatistics.PacketBurstWriteNcps; + + *lppData = (LPVOID) ++pdwCounter; + + } else { + + // + // Failure to access Redirector: clear counters to 0 + // + + memset(&pPerfCounterBlock[1], + 0, + SIZE_OF_COUNTER_BLOCK - sizeof(pPerfCounterBlock)); + + pdwCounter = (PDWORD) ((PBYTE) pPerfCounterBlock + SIZE_OF_COUNTER_BLOCK); + *lppData = (LPVOID) pdwCounter; + + } + + + // We sent data for only one Object. (Remember not to confuse this + // with counters. Even if more counters are added, the number of object + // is still only one. However, this does not mean more objects cannot + // be added + *lpNumObjectTypes = 1; + + // Fill in the number of bytes we copied - incl. the definitions and the + // counter data. + *lpcbTotalBytes = ((PBYTE) pdwCounter - (PBYTE) pNWDataDefinition); + + return ERROR_SUCCESS; +} + +/**************************************************************************** + FUNCTION: CloseNetWarePerformanceData + + Purpose: This routine closes the open handles to NetWare performance counters + + + Return: ERROR_SUCCESS + +****************************************************************************/ +DWORD APIENTRY +CloseNetWarePerformanceData( +) +{ + NtClose( hNetWareRdr ); + + return ERROR_SUCCESS; + +} + diff --git a/private/nw/perf/nwperf.h b/private/nw/perf/nwperf.h new file mode 100644 index 000000000..f6af9af41 --- /dev/null +++ b/private/nw/perf/nwperf.h @@ -0,0 +1,144 @@ + +// +// MODULE: NWPerf.H +// +// This file contains all the defines and prototypes for the performnce +// monitoring DLL for NetWare redirector +// +// Date: Sept, 28 1993 + + +// +// The routines that load these structures assume that all fields +// are packed and aligned on DWORD boundries. Alpha support may +// change this assumption so the pack pragma is used here to insure +// the DWORD packing assumption remains valid. +// +#pragma pack (4) + +// +// All these definitions will have to be updated when new counters are added. +// if a new counter called COUNTX is added then the Help and Title indicies +// defines should include a new entry - "#define COUNTXOBJ 4". This increases +// in increments of 2 because each counter has a title and help index. +// +// The Offset of the counters should have another entry - with the size of +// the data for COUNT - +// "#define COUNTER_OFFSET_COUNTX COUNTER_OFFSET_USERS+sizeof(COUNTX_TYPE)" +// +// The SIZE_OF_COUNTER_BLOCK will be updated to: +// "#define SIZE_OF_COUNTER_BLOCK COUNTER_OFFSET_COUNTX + sizeof(DWORD)" +// +// Finally the NW_DATA_DEFINITION will have a new PERF_COUNTER_DEFINTIION +// entry + +// Title and Help index defines. These are used for looking up the Registry +// to get at the counter indicies for the title and help strings. + +#define NW_NUM_OBJECTS 1 +#define NWOBJ 0 +#define PACKET_BURST_READ_ID 2 +#define PACKET_BURST_READ_TO_ID 4 +#define PACKET_BURST_WRITE_ID 6 +#define PACKET_BURST_WRITE_TO_ID 8 +#define PACKET_BURST_IO_ID 10 +#define CONNECT_2X_ID 12 +#define CONNECT_3X_ID 14 +#define CONNECT_4X_ID 16 + +// +// NetWare Redirector data object definitions. +// The offsets of the counters. The first DWORD is the size of the counter +// data block. In WinPerf, you will see this as PERF_COUNTER_BLOCK.ByteLength +// +#define BYTES_OFFSET sizeof(DWORD) +#define IO_OPERATIONS_OFFSET BYTES_OFFSET + sizeof(LARGE_INTEGER) +#define PACKETS_OFFSET IO_OPERATIONS_OFFSET + sizeof(DWORD) +#define BYTES_RECEIVED_OFFSET PACKETS_OFFSET + \ + sizeof(LARGE_INTEGER) +#define NCPS_RECEIVED_OFFSET BYTES_RECEIVED_OFFSET + \ + sizeof(LARGE_INTEGER) +#define BYTES_TRANSMITTED_OFFSET \ + NCPS_RECEIVED_OFFSET + \ + sizeof(LARGE_INTEGER) +#define NCPS_TRANSMITTED_OFFSET \ + BYTES_TRANSMITTED_OFFSET + \ + sizeof(LARGE_INTEGER) +#define RDR_READ_OPERATIONS_OFFSET \ + NCPS_TRANSMITTED_OFFSET + \ + sizeof(LARGE_INTEGER) +#define RANDOM_READ_OPERATIONS_OFFSET RDR_READ_OPERATIONS_OFFSET + \ + sizeof(DWORD) +#define READ_NCPS_OFFSET RANDOM_READ_OPERATIONS_OFFSET + \ + sizeof(DWORD) +#define RDR_WRITE_OPERATIONS_OFFSET READ_NCPS_OFFSET + \ + sizeof(DWORD) +#define RANDOM_WRITE_OPERATIONS_OFFSET RDR_WRITE_OPERATIONS_OFFSET + \ + sizeof(DWORD) +#define WRITE_NCPS_OFFSET RANDOM_WRITE_OPERATIONS_OFFSET + \ + sizeof(DWORD) +#define SESSIONS_OFFSET WRITE_NCPS_OFFSET + \ + sizeof(DWORD) +#define RECONNECTS_OFFSET SESSIONS_OFFSET + \ + sizeof(DWORD) +#define NETWARE_2X_CONNECTS_OFFSET RECONNECTS_OFFSET + \ + sizeof(DWORD) +#define NETWARE_3X_CONNECTS_OFFSET NETWARE_2X_CONNECTS_OFFSET + \ + sizeof(DWORD) +#define NETWARE_4X_CONNECTS_OFFSET NETWARE_3X_CONNECTS_OFFSET + \ + sizeof(DWORD) +#define SERVER_DISCONNECTS_OFFSET NETWARE_4X_CONNECTS_OFFSET + \ + sizeof(DWORD) +#define PACKET_BURST_READ_OFFSET SERVER_DISCONNECTS_OFFSET + \ + sizeof(DWORD) +#define PACKET_BURST_READ_TO_OFFSET PACKET_BURST_READ_OFFSET + \ + sizeof(DWORD) +#define PACKET_BURST_WRITE_OFFSET PACKET_BURST_READ_TO_OFFSET + \ + sizeof(DWORD) +#define PACKET_BURST_WRITE_TO_OFFSET PACKET_BURST_WRITE_OFFSET + \ + sizeof(DWORD) +#define PACKET_BURST_IO_OFFSET PACKET_BURST_WRITE_TO_OFFSET + \ + sizeof(DWORD) +#define SIZE_OF_COUNTER_BLOCK PACKET_BURST_IO_OFFSET + \ + sizeof(DWORD) + + + + +// The definition of the NetWare Data definition. This structure holds the +// definition for actual NetWare object and the definition for each of the +// counters. +typedef struct _NW_DATA_DEFINITION { + PERF_OBJECT_TYPE NWObjectType; + PERF_COUNTER_DEFINITION Bytes; + PERF_COUNTER_DEFINITION IoOperations; + PERF_COUNTER_DEFINITION Ncps; + PERF_COUNTER_DEFINITION BytesReceived; + PERF_COUNTER_DEFINITION NcpsReceived; + PERF_COUNTER_DEFINITION BytesTransmitted; + PERF_COUNTER_DEFINITION NcpsTransmitted; + PERF_COUNTER_DEFINITION ReadOperations; + PERF_COUNTER_DEFINITION RandomReadOperations; + PERF_COUNTER_DEFINITION ReadNcps; + PERF_COUNTER_DEFINITION WriteOperations; + PERF_COUNTER_DEFINITION RandomWriteOperations; + PERF_COUNTER_DEFINITION WriteNcps; + PERF_COUNTER_DEFINITION Sessions; + PERF_COUNTER_DEFINITION Reconnects; + PERF_COUNTER_DEFINITION NetWare2XConnects; + PERF_COUNTER_DEFINITION NetWare3XConnects; + PERF_COUNTER_DEFINITION NetWare4XConnects; + PERF_COUNTER_DEFINITION ServerDisconnects; + PERF_COUNTER_DEFINITION PacketBurstRead; + PERF_COUNTER_DEFINITION PacketBurstReadTimeouts; + PERF_COUNTER_DEFINITION PacketBurstWrite; + PERF_COUNTER_DEFINITION PacketBurstWriteTimeouts; + PERF_COUNTER_DEFINITION PacketBurstIO; +} NW_DATA_DEFINITION; + +#pragma pack () + +PM_OPEN_PROC OpenNetWarePerformanceData; +PM_COLLECT_PROC CollectNetWarePerformanceData; +PM_CLOSE_PROC CloseNetWarePerformanceData; + diff --git a/private/nw/perf/nwperf.rc b/private/nw/perf/nwperf.rc new file mode 100644 index 000000000..d9d1eee7e --- /dev/null +++ b/private/nw/perf/nwperf.rc @@ -0,0 +1,11 @@ +#include + +#include + +#define VER_FILETYPE VFT_DLL +#define VER_FILESUBTYPE VFT2_DRV_NETWORK +#define VER_FILEDESCRIPTION_STR "Client/Gateway Service for Netware Counters" +#define VER_INTERNALNAME_STR "PERFNW.DLL" +#define VER_ORIGINALFILENAME_STR "PERFNW.DLL" + +#include "common.ver" diff --git a/private/nw/perf/perfnw.def b/private/nw/perf/perfnw.def new file mode 100644 index 000000000..b9884595d --- /dev/null +++ b/private/nw/perf/perfnw.def @@ -0,0 +1,8 @@ +LIBRARY PerfNW + +DESCRIPTION 'NetWare(R) Workstation Compatible Service Performance Monitor Support' + +EXPORTS + OpenNetWarePerformanceData @2 + CollectNetWarePerformanceData @3 + CloseNetWarePerformanceData @4 diff --git a/private/nw/perf/prfutil.c b/private/nw/perf/prfutil.c new file mode 100644 index 000000000..f13286d93 --- /dev/null +++ b/private/nw/perf/prfutil.c @@ -0,0 +1,203 @@ +// +// Prfutil.h +// +// Utility procedures from the VGACTRS code in the DDK +// +#include "windows.h" +#include + +#define DEFINE_STRING +#include "prfutil.h" + +DWORD +GetQueryType ( + IN LPWSTR lpValue +) +/*++ + +GetQueryType + + returns the type of query described in the lpValue string so that + the appropriate processing method may be used + +Arguments + + IN lpValue + string passed to PerfRegQuery Value for processing + +Return Value + + QUERY_GLOBAL + if lpValue == 0 (null pointer) + lpValue == pointer to Null string + lpValue == pointer to "Global" string + + QUERY_FOREIGN + if lpValue == pointer to "Foriegn" string + + QUERY_COSTLY + if lpValue == pointer to "Costly" string + + otherwise: + + QUERY_ITEMS + +--*/ +{ + TCHAR *pwcArgChar, *pwcTypeChar; + BOOL bFound; + + if (lpValue == 0) { + return QUERY_GLOBAL; + } else if (*lpValue == 0) { + return QUERY_GLOBAL; + } + + // check for "Global" request + + pwcArgChar = lpValue; + pwcTypeChar = GLOBAL_STRING; + bFound = TRUE; // assume found until contradicted + + // check to the length of the shortest string + + while ((*pwcArgChar != 0) && (*pwcTypeChar != 0)) { + if (*pwcArgChar++ != *pwcTypeChar++) { + bFound = FALSE; // no match + break; // bail out now + } + } + + if (bFound) return QUERY_GLOBAL; + + // check for "Foreign" request + + pwcArgChar = lpValue; + pwcTypeChar = FOREIGN_STRING; + bFound = TRUE; // assume found until contradicted + + // check to the length of the shortest string + + while ((*pwcArgChar != 0) && (*pwcTypeChar != 0)) { + if (*pwcArgChar++ != *pwcTypeChar++) { + bFound = FALSE; // no match + break; // bail out now + } + } + + if (bFound) return QUERY_FOREIGN; + + // check for "Costly" request + + pwcArgChar = lpValue; + pwcTypeChar = COSTLY_STRING; + bFound = TRUE; // assume found until contradicted + + // check to the length of the shortest string + + while ((*pwcArgChar != 0) && (*pwcTypeChar != 0)) { + if (*pwcArgChar++ != *pwcTypeChar++) { + bFound = FALSE; // no match + break; // bail out now + } + } + + if (bFound) return QUERY_COSTLY; + + // if not Global and not Foreign and not Costly, + // then it must be an item list + + return QUERY_ITEMS; + +} + +BOOL +IsNumberInUnicodeList ( + IN DWORD dwNumber, + IN LPWSTR lpwszUnicodeList +) +/*++ + +IsNumberInUnicodeList + +Arguments: + + IN dwNumber + DWORD number to find in list + + IN lpwszUnicodeList + Null terminated, Space delimited list of decimal numbers + +Return Value: + + TRUE: + dwNumber was found in the list of unicode number strings + + FALSE: + dwNumber was not found in the list. + +--*/ +{ + DWORD dwThisNumber; + TCHAR *pwcThisChar; + BOOL bValidNumber; + BOOL bNewItem; + TCHAR wcDelimiter; // could be an argument to be more flexible + + if (lpwszUnicodeList == 0) return FALSE; // null pointer, # not founde + + pwcThisChar = lpwszUnicodeList; + dwThisNumber = 0; + wcDelimiter = TEXT(' '); + bValidNumber = FALSE; + bNewItem = TRUE; + + while (TRUE) { + switch (EvalThisChar (*pwcThisChar, wcDelimiter)) { + case DIGIT: + // if this is the first digit after a delimiter, then + // set flags to start computing the new number + if (bNewItem) { + bNewItem = FALSE; + bValidNumber = TRUE; + } + if (bValidNumber) { + dwThisNumber *= 10; + dwThisNumber += (*pwcThisChar - TEXT('0')); + } + break; + + case DELIMITER: + // a delimter is either the delimiter character or the + // end of the string ('\0') if when the delimiter has been + // reached a valid number was found, then compare it to the + // number from the argument list. if this is the end of the + // string and no match was found, then return. + // + if (bValidNumber) { + if (dwThisNumber == dwNumber) return TRUE; + bValidNumber = FALSE; + } + if (*pwcThisChar == 0) { + return FALSE; + } else { + bNewItem = TRUE; + dwThisNumber = 0; + } + break; + + case INVALID: + // if an invalid character was encountered, ignore all + // characters up to the next delimiter and then start fresh. + // the invalid number is not compared. + bValidNumber = FALSE; + break; + + default: + break; + + } + pwcThisChar++; + } + +} // IsNumberInUnicodeList diff --git a/private/nw/perf/prfutil.h b/private/nw/perf/prfutil.h new file mode 100644 index 000000000..58eb21abd --- /dev/null +++ b/private/nw/perf/prfutil.h @@ -0,0 +1,42 @@ +// +// Prfutil.h +// +// Utility procedures from the VGACTRS code in the DDK +// +#ifndef _PRFUTIL_ +#define _PRF_UTIL_ + +#define QUERY_GLOBAL 1 +#define QUERY_ITEMS 2 +#define QUERY_FOREIGN 3 +#define QUERY_COSTLY 4 + +#define DIGIT 1 +#define DELIMITER 2 +#define INVALID 3 + +#define EvalThisChar(c,d) ( \ + (c == d) ? DELIMITER : \ + (c == 0) ? DELIMITER : \ + (c < (WCHAR)'0') ? INVALID : \ + (c > (WCHAR)'9') ? INVALID : \ + DIGIT) + +BOOL IsNumberInUnicodeList ( IN DWORD dwNumber, IN LPWSTR lpwszUnicodeList ); +DWORD GetQueryType ( IN LPWSTR lpValue ); + +// only prfutil.c will define GLOBAL_STRING +#ifdef DEFINE_STRING +TCHAR GLOBAL_STRING[] = TEXT("Global"); +TCHAR FOREIGN_STRING[] = TEXT("Foreign"); +TCHAR COSTLY_STRING[] = TEXT("Costly"); +TCHAR NULL_STRING[] = TEXT("\0"); // pointer to null string +#else +extern TCHAR GLOBAL_STRING[]; +extern TCHAR FOREIGN_STRING[]; +extern TCHAR COSTLY_STRING[]; +extern TCHAR NULL_STRING[]; +#endif + + +#endif // _PRFUTIL_ diff --git a/private/nw/perf/sources b/private/nw/perf/sources new file mode 100644 index 000000000..4f18ffc64 --- /dev/null +++ b/private/nw/perf/sources @@ -0,0 +1,46 @@ +!IF 0 +************************************************************** +Sources file for building an Win32 dll. + +Module Name : Sources for perfnw.dll + +Authors: HonWah Chan + +Revisions: 09/28/93 + +INCLUDES= ..\..\..\inc;..\inc +************************************************************** +!ENDIF + +DLLBASE=0x7500000 + +MAJORCOMP=sdktools +MINORCOMP=perfnw + +USE_CRTDLL=1 + +TARGETNAME=perfnw +TARGETPATH=\nt\public\sdk\lib +TARGETTYPE=DYNLINK +TARGETLIBS= \ + $(BASEDIR)\public\sdk\lib\*\advapi32.lib + + +INCLUDES= ..\inc + +SOURCES= \ + nwperf.c \ + prfutil.c \ + nwperf.rc \ + nwdata.c + +UMLIBS= \ + $(BASEDIR)\public\sdk\lib\*\advapi32.lib + + + +!IF "$(QFE_BUILD)" != "1" +NET_C_DEFINES= -DSECURITY -DWIN32 -DSTRICT -DUNICODE -D_UNICODE +!ELSE +NET_C_DEFINES= -DSECURITY -DWIN32 -DSTRICT -DUNICODE -D_UNICODE -DQFE_BUILD=1 +!ENDIF -- cgit v1.2.3