Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

372 lines
9.0 KiB

/*++ BUILD Version: 0001 // Increment this if a change has global effects
Copyright (c) 1992 Microsoft Corporation
Module Name:
perfsfm.c
Abstract:
This file implements the Extensible Objects for the Sfm object type
Created:
Russ Blake 24 Feb 93
Sue Adams 07 Jun 93
Revision History
Sue Adams 23 Feb 94 - no longer need to open \MacSrv\... registry
key to query for FirstCounter and FirstHelp. These
are now hardcoded values in the base NT system.
SFMOBJ = 1000, SFMOBJ_HELP = 1001
Jameel Hyder Use SFM Apis instead of Nt apis to get the counters.
--*/
//
// Include Files
//
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <string.h>
#include <wcstr.h>
#include <winperf.h>
#include "sfmctrs.h" // error message definition
#include "perfmsg.h"
#include "perfutil.h"
#include "datasfm.h"
#include <macfile.h>
#include <admin.h>
//
// References to constants which initialize the Object type definitions
// (see datasfm.h & .c)
//
extern SFM_DATA_DEFINITION SfmDataDefinition;
DWORD dwOpenCount = 0; // count of "Open" threads
BOOL bInitOK = FALSE; // true = DLL initialized OK
//
// Sfm data structures
//
PPERF_COUNTER_BLOCK pCounterBlock;
AFP_SERVER_HANDLE SfmRpcHandle;
//
// Function Prototypes
//
// these are used to insure that the data collection functions
// accessed by Perflib will have the correct calling format.
//
PM_OPEN_PROC OpenAfpPerformanceData;
PM_COLLECT_PROC CollectAfpPerformanceData;
PM_CLOSE_PROC CloseAfpPerformanceData;
DWORD
OpenAfpPerformanceData(
LPWSTR lpDeviceNames
)
/*++
Routine Description:
This routine will open the Sfmsrv FSD/FSP driver to
pass performance data back. This routine also initializes the data
structures used to pass data back to the registry
Arguments:
Pointer to object ID of each device to be opened. (Will be null for
MacFile).
Return Value:
None.
--*/
{
LONG status;
OBJECT_ATTRIBUTES SfmObjectAttributes;
//
// Since SCREG is multi-threaded and will call this routine in
// order to service remote performance queries, this library
// must keep track of how many times it has been opened (i.e.
// how many threads have accessed it). the registry routines will
// limit access to the initialization routine to only one thread
// at a time so synchronization (i.e. reentrancy) should not be
// a problem
//
#if DBG
OutputDebugString("sfmctr.dll: Open routine entered...\n");
#endif
if (!dwOpenCount) {
// open Eventlog interface
hEventLog = MonOpenEventLog();
pCounterBlock = NULL; // initialize pointer to memory
status = AfpAdminConnect(L"", &SfmRpcHandle);
if (!NT_SUCCESS(status)) {
REPORT_ERROR (SFMPERF_OPEN_FILE_DRIVER_ERROR, LOG_USER);
// this is fatal, if we can't open the driver then there's no
// point in continuing.
goto OpenExitPoint;
}
bInitOK = TRUE; // ok to use this function
}
dwOpenCount++; // increment OPEN counter
status = ERROR_SUCCESS; // for successful exit
OpenExitPoint:
return status;
}
DWORD
CollectAfpPerformanceData(
IN LPWSTR lpValueName,
IN OUT LPVOID *lppData,
IN OUT LPDWORD lpcbTotalBytes,
IN OUT LPDWORD lpNumObjectTypes
)
/*++
Routine Description:
This routine will return the data for the SFM 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 Value:
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.
--*/
{
// Variables for reformating the data
PAFP_STATISTICS_INFO_EX pAfpStats;
NTSTATUS Status;
ULONG SpaceNeeded;
PDWORD pdwCounter;
LARGE_INTEGER UNALIGNED * pliCounter;
PERF_COUNTER_BLOCK * pPerfCounterBlock;
SFM_DATA_DEFINITION * pSfmDataDefinition;
// variables used for error logging
DWORD dwQueryType;
//
// before doing anything else, see if Open went OK
//
if (!bInitOK) {
// unable to continue because open failed.
*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 (dwQueryType == QUERY_ITEMS){
if ( !(IsNumberInUnicodeList (SfmDataDefinition.SfmObjectType.ObjectNameTitleIndex, lpValueName))) {
// request received for data object not provided by this routine
*lpcbTotalBytes = (DWORD) 0;
*lpNumObjectTypes = (DWORD) 0;
return ERROR_SUCCESS;
}
}
pSfmDataDefinition = (SFM_DATA_DEFINITION *) *lppData;
SpaceNeeded = sizeof(SFM_DATA_DEFINITION) +
SIZE_OF_SFM_PERFORMANCE_DATA;
if ( *lpcbTotalBytes < SpaceNeeded ) {
*lpcbTotalBytes = (DWORD) 0;
*lpNumObjectTypes = (DWORD) 0;
return ERROR_MORE_DATA;
}
//
// Copy the (constant, initialized) Object Type and counter definitions
// to the caller's data buffer
//
memmove(pSfmDataDefinition,
&SfmDataDefinition,
sizeof(SFM_DATA_DEFINITION));
//
// Format and collect SFM data from IOCTL
//
Status = AfpAdminStatisticsGetEx( SfmRpcHandle, (LPBYTE *)&pAfpStats);
if (Status != NO_ERROR)
{
AfpAdminDisconnect(SfmRpcHandle);
SfmRpcHandle = 0;
bInitOK = FALSE;
*lpcbTotalBytes = (DWORD) 0;
*lpNumObjectTypes = (DWORD) 0;
return ERROR_SUCCESS;
}
//
// Go to end of SfmDataDefinitionStructure to get to PerfCounterBlock
//
pPerfCounterBlock = (PERF_COUNTER_BLOCK *) &pSfmDataDefinition[1];
pPerfCounterBlock->ByteLength = SIZE_OF_SFM_PERFORMANCE_DATA;
// Go to end of PerfCounterBlock to get to array of counters
pdwCounter = (PDWORD) (&pPerfCounterBlock[1]);
*pdwCounter++ = pAfpStats->stat_MaxPagedUsage;
*pdwCounter++ = pAfpStats->stat_CurrPagedUsage;
*pdwCounter++ = pAfpStats->stat_MaxNonPagedUsage;
*pdwCounter++ = pAfpStats->stat_CurrNonPagedUsage;
*pdwCounter++ = pAfpStats->stat_CurrentSessions;
*pdwCounter++ = pAfpStats->stat_MaxSessions;
*pdwCounter++ = pAfpStats->stat_CurrentInternalOpens;
*pdwCounter++ = pAfpStats->stat_MaxInternalOpens;
*pdwCounter++ = pAfpStats->stat_NumFailedLogins;
pliCounter = (LARGE_INTEGER UNALIGNED *) pdwCounter;
pliCounter->QuadPart = pAfpStats->stat_DataRead.QuadPart +
pAfpStats->stat_DataReadInternal.QuadPart;
pliCounter++;
pliCounter->QuadPart = pAfpStats->stat_DataWritten.QuadPart +
pAfpStats->stat_DataWrittenInternal.QuadPart;
pliCounter++;
*pliCounter++ = pAfpStats->stat_DataIn;
*pliCounter++ = pAfpStats->stat_DataOut;
pdwCounter = (PDWORD) pliCounter;
*pdwCounter++ = pAfpStats->stat_CurrQueueLength;
*pdwCounter++ = pAfpStats->stat_MaxQueueLength;
*pdwCounter++ = pAfpStats->stat_CurrThreadCount;
*pdwCounter++ = pAfpStats->stat_MaxThreadCount;
*lppData = (PVOID) pdwCounter;
// update arguments for return
*lpNumObjectTypes = 1;
*lpcbTotalBytes = (DWORD)((PBYTE) pdwCounter - (PBYTE) pSfmDataDefinition);
AfpAdminBufferFree(pAfpStats);
return ERROR_SUCCESS;
}
DWORD
CloseAfpPerformanceData(
)
/*++
Routine Description:
This routine closes the open handles to MacFile device performance counters
Arguments:
None.
Return Value:
ERROR_SUCCESS
--*/
{
if (!(--dwOpenCount))
{
// when this is the last thread...
if (SfmRpcHandle != 0)
AfpAdminDisconnect(SfmRpcHandle);
pCounterBlock = NULL;
MonCloseEventLog();
}
return ERROR_SUCCESS;
}