Leaked source code of windows server 2003
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.
 
 
 
 
 
 

933 lines
33 KiB

/**********************************************************************/
/** Microsoft Windows NT **/
/** Copyright(c) Microsoft Corp., 1993 **/
/**********************************************************************/
/*
perfftp.cxx
This file implements the Extensible Performance Objects for
the FTP Server service.
FILE HISTORY:
KeithMo 07-Jun-1993 Created, based on RussBl's sample code.
MuraliK 16-Nov-1995 Modified dependencies and removed NetApi
SophiaC 06-Nov-1996 Supported mutlitiple instances
*/
#define INITGUID
#include <windows.h>
#include <winperf.h>
#include <lm.h>
#include <string.h>
#include <stdlib.h>
#include <ole2.h>
#include "iis64.h"
#include "dbgutil.h"
#include "iisinfo.h"
#include "ftpd.h"
#include "ftpctrs.h"
#include "ftpmsg.h"
#include "iadm.h"
extern "C" {
#include "perfutil.h"
#include "apiutil.h"
#include "ftpdata.h"
} // extern "C"
#define APP_NAME (TEXT("FTPCtrs"))
#define MAX_SIZEOF_INSTANCE_NAME METADATA_MAX_NAME_LEN
#define TOTAL_INSTANCE_NAME L"_Total"
//
// Private globals.
//
DWORD cOpens = 0; // Active "opens" reference count.
BOOL fInitOK = FALSE; // TRUE if DLL initialized OK.
HANDLE hEventLog = NULL; // event log handle
//
// Public prototypes.
//
PM_OPEN_PROC OpenFtpPerformanceData;
PM_COLLECT_PROC CollectFtpPerformanceData;
PM_CLOSE_PROC CloseFtpPerformanceData;
//
// Private prototypes.
//
VOID
CopyStatisticsData(
IN FTP_STATISTICS_0 * pFTPStats,
OUT FTPD_COUNTER_BLOCK * pCounterBlock
);
VOID
Update_TotalStatisticsData(
IN FTPD_COUNTER_BLOCK * pCounterBlock,
OUT FTPD_COUNTER_BLOCK * pTotal
);
//
// Public functions.
//
/*******************************************************************
NAME: OpenFtpPerformanceData
SYNOPSIS: Initializes the data structures used to communicate
performance counters with the registry.
ENTRY: lpDeviceNames - Poitner to object ID of each device
to be opened.
RETURNS: DWORD - Win32 status code.
HISTORY:
KeithMo 07-Jun-1993 Created.
********************************************************************/
DWORD OpenFtpPerformanceData( LPWSTR lpDeviceNames )
{
DWORD err = NO_ERROR;
HKEY hkey = NULL;
DWORD size;
DWORD type;
DWORD dwFirstCounter;
DWORD dwFirstHelp;
PERF_COUNTER_DEFINITION * pctr;
FTPD_COUNTER_BLOCK ftpc;
DWORD i;
//
// Since WINLOGON 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( !fInitOK )
{
//
// This is the *first* open.
//
// open event log interface
if (hEventLog == NULL){
hEventLog = RegisterEventSource ((LPTSTR)NULL, // Use Local Machine
APP_NAME); // event log app name to find in registry
if (hEventLog == NULL)
{
return GetLastError();
}
}
//
// Open the FTP Server service's Performance key.
//
err = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
FTPD_PERFORMANCE_KEY,
0,
KEY_READ,
&hkey );
if( err == NO_ERROR )
{
//
// Read the first counter DWORD.
//
size = sizeof(DWORD);
err = RegQueryValueEx( hkey,
"First Counter",
NULL,
&type,
(LPBYTE)&dwFirstCounter,
&size );
if( err == NO_ERROR )
{
//
// Read the first help DWORD.
//
size = sizeof(DWORD);
err = RegQueryValueEx( hkey,
"First Help",
NULL,
&type,
(LPBYTE)&dwFirstHelp,
&size );
if ( err == NO_ERROR )
{
//
// Update the object & counter name & help indicies.
//
FtpdDataDefinition.FtpdObjectType.ObjectNameTitleIndex
+= dwFirstCounter;
FtpdDataDefinition.FtpdObjectType.ObjectHelpTitleIndex
+= dwFirstHelp;
FtpdDataDefinition.FtpdBytesSent.CounterNameTitleIndex
+= dwFirstCounter;
FtpdDataDefinition.FtpdBytesSent.CounterHelpTitleIndex
+= dwFirstHelp;
FtpdDataDefinition.FtpdBytesSent.CounterOffset =
(DWORD)((LPBYTE)&ftpc.BytesSent - (LPBYTE)&ftpc);
FtpdDataDefinition.FtpdBytesReceived.CounterNameTitleIndex
+= dwFirstCounter;
FtpdDataDefinition.FtpdBytesReceived.CounterHelpTitleIndex
+= dwFirstHelp;
FtpdDataDefinition.FtpdBytesReceived.CounterOffset =
(DWORD)((LPBYTE)&ftpc.BytesReceived - (LPBYTE)&ftpc);
FtpdDataDefinition.FtpdBytesTotal.CounterNameTitleIndex
+= dwFirstCounter;
FtpdDataDefinition.FtpdBytesTotal.CounterHelpTitleIndex
+= dwFirstHelp;
FtpdDataDefinition.FtpdBytesTotal.CounterOffset =
(DWORD)((LPBYTE)&ftpc.BytesTotal - (LPBYTE)&ftpc);
FtpdDataDefinition.FtpdFilesSent.CounterNameTitleIndex
+= dwFirstCounter;
FtpdDataDefinition.FtpdFilesSent.CounterHelpTitleIndex
+= dwFirstHelp;
FtpdDataDefinition.FtpdFilesSent.CounterOffset =
(DWORD)((LPBYTE)&ftpc.FilesSent - (LPBYTE)&ftpc);
FtpdDataDefinition.FtpdFilesReceived.CounterNameTitleIndex
+= dwFirstCounter;
FtpdDataDefinition.FtpdFilesReceived.CounterHelpTitleIndex
+= dwFirstHelp;
FtpdDataDefinition.FtpdFilesReceived.CounterOffset =
(DWORD)((LPBYTE)&ftpc.FilesReceived - (LPBYTE)&ftpc);
FtpdDataDefinition.FtpdFilesTotal.CounterNameTitleIndex
+= dwFirstCounter;
FtpdDataDefinition.FtpdFilesTotal.CounterHelpTitleIndex
+= dwFirstHelp;
FtpdDataDefinition.FtpdFilesTotal.CounterOffset =
(DWORD)((LPBYTE)&ftpc.FilesTotal - (LPBYTE)&ftpc);
FtpdDataDefinition.FtpdCurrentAnonymous.CounterNameTitleIndex
+= dwFirstCounter;
FtpdDataDefinition.FtpdCurrentAnonymous.CounterHelpTitleIndex
+= dwFirstHelp;
FtpdDataDefinition.FtpdCurrentAnonymous.CounterOffset =
(DWORD)((LPBYTE)&ftpc.CurrentAnonymous - (LPBYTE)&ftpc);
FtpdDataDefinition.FtpdCurrentNonAnonymous.CounterNameTitleIndex
+= dwFirstCounter;
FtpdDataDefinition.FtpdCurrentNonAnonymous.CounterHelpTitleIndex
+= dwFirstHelp;
FtpdDataDefinition.FtpdCurrentNonAnonymous.CounterOffset =
(DWORD)((LPBYTE)&ftpc.CurrentNonAnonymous - (LPBYTE)&ftpc);
FtpdDataDefinition.FtpdTotalAnonymous.CounterNameTitleIndex
+= dwFirstCounter;
FtpdDataDefinition.FtpdTotalAnonymous.CounterHelpTitleIndex
+= dwFirstHelp;
FtpdDataDefinition.FtpdTotalAnonymous.CounterOffset =
(DWORD)((LPBYTE)&ftpc.TotalAnonymous - (LPBYTE)&ftpc);
FtpdDataDefinition.FtpdTotalNonAnonymous.CounterNameTitleIndex
+= dwFirstCounter;
FtpdDataDefinition.FtpdTotalNonAnonymous.CounterHelpTitleIndex
+= dwFirstHelp;
FtpdDataDefinition.FtpdTotalNonAnonymous.CounterOffset =
(DWORD)((LPBYTE)&ftpc.TotalNonAnonymous - (LPBYTE)&ftpc);
FtpdDataDefinition.FtpdMaxAnonymous.CounterNameTitleIndex
+= dwFirstCounter;
FtpdDataDefinition.FtpdMaxAnonymous.CounterHelpTitleIndex
+= dwFirstHelp;
FtpdDataDefinition.FtpdMaxAnonymous.CounterOffset =
(DWORD)((LPBYTE)&ftpc.MaxAnonymous - (LPBYTE)&ftpc);
FtpdDataDefinition.FtpdMaxNonAnonymous.CounterNameTitleIndex
+= dwFirstCounter;
FtpdDataDefinition.FtpdMaxNonAnonymous.CounterHelpTitleIndex
+= dwFirstHelp;
FtpdDataDefinition.FtpdMaxNonAnonymous.CounterOffset =
(DWORD)((LPBYTE)&ftpc.MaxNonAnonymous - (LPBYTE)&ftpc);
FtpdDataDefinition.FtpdCurrentConnections.CounterNameTitleIndex
+= dwFirstCounter;
FtpdDataDefinition.FtpdCurrentConnections.CounterHelpTitleIndex
+= dwFirstHelp;
FtpdDataDefinition.FtpdCurrentConnections.CounterOffset =
(DWORD)((LPBYTE)&ftpc.CurrentConnections - (LPBYTE)&ftpc);
FtpdDataDefinition.FtpdMaxConnections.CounterNameTitleIndex
+= dwFirstCounter;
FtpdDataDefinition.FtpdMaxConnections.CounterHelpTitleIndex
+= dwFirstHelp;
FtpdDataDefinition.FtpdMaxConnections.CounterOffset =
(DWORD)((LPBYTE)&ftpc.MaxConnections - (LPBYTE)&ftpc);
FtpdDataDefinition.FtpdConnectionAttempts.CounterNameTitleIndex
+= dwFirstCounter;
FtpdDataDefinition.FtpdConnectionAttempts.CounterHelpTitleIndex
+= dwFirstHelp;
FtpdDataDefinition.FtpdConnectionAttempts.CounterOffset =
(DWORD)((LPBYTE)&ftpc.ConnectionAttempts - (LPBYTE)&ftpc);
FtpdDataDefinition.FtpdLogonAttempts.CounterNameTitleIndex
+= dwFirstCounter;
FtpdDataDefinition.FtpdLogonAttempts.CounterHelpTitleIndex
+= dwFirstHelp;
FtpdDataDefinition.FtpdLogonAttempts.CounterOffset =
(DWORD)((LPBYTE)&ftpc.LogonAttempts - (LPBYTE)&ftpc);
FtpdDataDefinition.FtpdServiceUptime.CounterNameTitleIndex
+= dwFirstCounter;
FtpdDataDefinition.FtpdServiceUptime.CounterHelpTitleIndex
+= dwFirstHelp;
FtpdDataDefinition.FtpdServiceUptime.CounterOffset =
(DWORD)((LPBYTE)&ftpc.ServiceUptime - (LPBYTE)&ftpc);
// These counters are currently meaningless, but should be restored if we
// ever enable per-FTP-instance bandwidth throttling.
/*
FtpdDataDefinition.FtpdBlockedRequests.CounterNameTitleIndex
+= dwFirstCounter;
FtpdDataDefinition.FtpdBlockedRequests.CounterHelpTitleIndex
+= dwFirstHelp;
FtpdDataDefinition.FtpdBlockedRequests.CounterOffset =
(DWORD)((LPBYTE)&ftpc.BlockedRequests - (LPBYTE)&ftpc);
FtpdDataDefinition.FtpdAllowedRequests.CounterNameTitleIndex
+= dwFirstCounter;
FtpdDataDefinition.FtpdAllowedRequests.CounterHelpTitleIndex
+= dwFirstHelp;
FtpdDataDefinition.FtpdAllowedRequests.CounterOffset =
(DWORD)((LPBYTE)&ftpc.AllowedRequests - (LPBYTE)&ftpc);
FtpdDataDefinition.FtpdRejectedRequests.CounterNameTitleIndex
+= dwFirstCounter;
FtpdDataDefinition.FtpdRejectedRequests.CounterHelpTitleIndex
+= dwFirstHelp;
FtpdDataDefinition.FtpdRejectedRequests.CounterOffset =
(DWORD)((LPBYTE)&ftpc.RejectedRequests - (LPBYTE)&ftpc);
FtpdDataDefinition.FtpdCurrentBlockedRequests.CounterNameTitleIndex
+= dwFirstCounter;
FtpdDataDefinition.FtpdCurrentBlockedRequests.CounterHelpTitleIndex
+= dwFirstHelp;
FtpdDataDefinition.FtpdCurrentBlockedRequests.CounterOffset =
(DWORD)((LPBYTE)&ftpc.CurrentBlockedRequests - (LPBYTE)&ftpc);
FtpdDataDefinition.FtpdMeasuredBandwidth.CounterNameTitleIndex
+= dwFirstCounter;
FtpdDataDefinition.FtpdMeasuredBandwidth.CounterHelpTitleIndex
+= dwFirstHelp;
FtpdDataDefinition.FtpdMeasuredBandwidth.CounterOffset =
(DWORD)((LPBYTE)&ftpc.MeasuredBandwidth - (LPBYTE)&ftpc);
*/
//
// Remember that we initialized OK.
//
fInitOK = TRUE;
} else {
ReportEvent (hEventLog, EVENTLOG_ERROR_TYPE,
0, FTP_UNABLE_QUERY_DATA,
(PSID)NULL, 0,
sizeof(err), NULL,
(PVOID)(&err));
}
} else {
ReportEvent (hEventLog, EVENTLOG_ERROR_TYPE,
0, FTP_UNABLE_QUERY_DATA,
(PSID)NULL, 0,
sizeof(err), NULL,
(PVOID)(&err));
}
//
// Close the registry if we managed to actually open it.
//
if( hkey != NULL )
{
RegCloseKey( hkey );
hkey = NULL;
}
} else {
ReportEvent (hEventLog, EVENTLOG_ERROR_TYPE,
0, FTP_UNABLE_QUERY_DATA,
(PSID)NULL, 0,
sizeof(err), NULL,
(PVOID)(&err));
}
}
//
// Bump open counter.
//
InterlockedIncrement((LPLONG )&cOpens);
return err;
} // OpenFTPPerformanceData
/*******************************************************************
NAME: CollectFtpPerformanceData
SYNOPSIS: Initializes the data structures used to communicate
ENTRY: lpValueName - The name of the value to retrieve.
lppData - On entry contains a pointer to the buffer to
receive the completed PerfDataBlock & subordinate
structures. On exit, points to the first bytes
*after* the data structures added by this routine.
lpcbTotalBytes - On entry contains a pointer to the
size (in BYTEs) of the buffer referenced by lppData.
On exit, contains the number of BYTEs added by this
routine.
lpNumObjectTypes - Receives the number of objects added
by this routine.
RETURNS: DWORD - Win32 status code. MUST be either NO_ERROR
or ERROR_MORE_DATA.
HISTORY:
KeithMo 07-Jun-1993 Created.
********************************************************************/
DWORD CollectFtpPerformanceData( LPWSTR lpValueName,
LPVOID * lppData,
LPDWORD lpcbTotalBytes,
LPDWORD lpNumObjectTypes )
{
PERF_INSTANCE_DEFINITION * pPerfInstanceDefinition;
DWORD dwInstanceIndex = 0;
DWORD dwInstanceCount = 0;
DWORD i = 0;
DWORD dwQueryType;
ULONG cbRequired;
DWORD * pdwCounter;
LARGE_INTEGER * pliCounter;
FTPD_COUNTER_BLOCK * pCounterBlock;
FTPD_COUNTER_BLOCK * pTotal;
FTPD_DATA_DEFINITION * pFtpdDataDefinition;
FTP_STATISTICS_0 * pFTPStats;
NET_API_STATUS neterr;
HRESULT hresErr;
DWORD dwBufferSize = 0;
LPINET_INFO_SITE_LIST pSites;
//
// No need to even try if we failed to open...
//
if( !fInitOK )
{
*lpcbTotalBytes = 0;
*lpNumObjectTypes = 0;
//
// According to the Performance Counter design, this
// is a successful exit. Go figure.
//
return NO_ERROR;
}
//
// Determine the query type.
//
dwQueryType = GetQueryType( lpValueName );
if (( dwQueryType == QUERY_FOREIGN ) || (dwQueryType == QUERY_COSTLY))
{
//
// We don't do foreign queries.
//
*lpcbTotalBytes = 0;
*lpNumObjectTypes = 0;
return NO_ERROR;
}
if( dwQueryType == QUERY_ITEMS )
{
//
// The registry is asking for a specific object. Let's
// see if we're one of the chosen.
//
if( !IsNumberInUnicodeList(
FtpdDataDefinition.FtpdObjectType.ObjectNameTitleIndex,
lpValueName ) )
{
*lpcbTotalBytes = 0;
*lpNumObjectTypes = 0;
return NO_ERROR;
}
}
//
// Enumerate and get total number of instances count.
//
pFtpdDataDefinition = (FTPD_DATA_DEFINITION *)*lppData;
neterr = InetInfoGetSites(
NULL,
INET_FTP_SVC_ID,
&pSites
);
if( neterr != NERR_Success )
{
//
// Only event log once for each server down
//
// if the server is down, we don't log an error.
if ( !( neterr == RPC_S_SERVER_UNAVAILABLE ||
neterr == RPC_S_UNKNOWN_IF ||
neterr == ERROR_SERVICE_NOT_ACTIVE ||
neterr == RPC_S_CALL_FAILED_DNE ))
{
//
// Error retrieving statistics.
//
ReportEvent(hEventLog, EVENTLOG_ERROR_TYPE,
0, FTP_UNABLE_QUERY_DATA,
(PSID)NULL, 0,
sizeof(neterr), NULL,
(PVOID)(&neterr));
}
cbRequired = sizeof(FTPD_DATA_DEFINITION) +
sizeof(PERF_INSTANCE_DEFINITION) +
(sizeof(WCHAR) * MAX_SIZEOF_INSTANCE_NAME ) +
sizeof(FTPD_COUNTER_BLOCK);
if( *lpcbTotalBytes < cbRequired )
{
//
// Nope.
//
*lpcbTotalBytes = 0;
*lpNumObjectTypes = 0;
return ERROR_MORE_DATA;
}
// We always return the _Total instance even if the counters
// are not accessible. This is so we stay in sync with how the
// other IIS counters work. For the PERF_NO_INSTANCE counters we need
// to do this so that WMI get's it's definition data even if the service
// is not running, and logging doesn't get confused by a PERF_NO_INSTANCE
// counter returning zero instances.
// First we move in the definition.
memmove( pFtpdDataDefinition,
&FtpdDataDefinition,
sizeof(FTPD_DATA_DEFINITION) );
((PERF_OBJECT_TYPE*) pFtpdDataDefinition)->NumInstances = 1;
((PERF_OBJECT_TYPE*) pFtpdDataDefinition)->TotalByteLength = cbRequired;
LPVOID pData = (LPVOID) ( pFtpdDataDefinition + 1 );
// Now we setup the PERF_INSTANCE_DEFINITION
((PERF_INSTANCE_DEFINITION*) pData)->ByteLength = sizeof(PERF_INSTANCE_DEFINITION) +
MAX_SIZEOF_INSTANCE_NAME * sizeof(WCHAR);
((PERF_INSTANCE_DEFINITION*) pData)->ParentObjectTitleIndex = 0;
((PERF_INSTANCE_DEFINITION*) pData)->ParentObjectInstance = 0;
((PERF_INSTANCE_DEFINITION*) pData)->UniqueID = PERF_NO_UNIQUE_ID;
((PERF_INSTANCE_DEFINITION*) pData)->NameOffset = sizeof(PERF_INSTANCE_DEFINITION);
((PERF_INSTANCE_DEFINITION*) pData)->NameLength = (wcslen(TOTAL_INSTANCE_NAME) + 1) * sizeof(WCHAR);
pData = (LPBYTE) pData + sizeof(PERF_INSTANCE_DEFINITION);
// Next copy in the Instance Name including the
// NULL, we know we have enough room because of
// the check above for size.
wcsncpy ( (LPWSTR) pData, TOTAL_INSTANCE_NAME, wcslen(TOTAL_INSTANCE_NAME) + 1 );
// To avoid suttle differences we use the same MAX_INSTANCE_NAME
// amount of space even for this faked up _Total Site.
pData = (LPBYTE) pData + ( MAX_SIZEOF_INSTANCE_NAME * sizeof(WCHAR));
// Lastly copy in a block of zero's for the _Total site data.
memset ( pData, 0, sizeof(FTPD_COUNTER_BLOCK) );
// This is setting the size in the structure, it is the first
// DWORD in the W3_CONTER_BLOCK.
*((DWORD*) (pData)) = sizeof(FTPD_COUNTER_BLOCK);
*lpcbTotalBytes = cbRequired;
*lpNumObjectTypes = 1;
*lppData = (LPBYTE) pFtpdDataDefinition + cbRequired;
return NO_ERROR;
}
//
// add 1 to dwInstanceCount for _Total instance
//
dwInstanceCount = pSites->cEntries + 1;
//
// always return an "instance sized" buffer after the definition
// blocks to prevent perfmon from reading bogus data. This is strictly
// a hack to accomodate how PERFMON handles the "0" instance case.
// By doing this, perfmon won't choke when there are no instances
// and the counter object & counters will be displayed in the list
// boxes, even though no instances will be listed.
//
cbRequired = sizeof(FTPD_DATA_DEFINITION) +
(dwInstanceCount * (sizeof(PERF_INSTANCE_DEFINITION) +
MAX_SIZEOF_INSTANCE_NAME +
sizeof (FTPD_COUNTER_BLOCK)));
//
// See if there's enough space.
//
if( *lpcbTotalBytes < cbRequired )
{
//
// Nope.
//
*lpcbTotalBytes = 0;
*lpNumObjectTypes = 0;
MIDL_user_free(pSites);
return ERROR_MORE_DATA;
}
//
// Copy the (constant, initialized) Object Type and counter definitions
// to the caller's data buffer
//
memmove( pFtpdDataDefinition,
&FtpdDataDefinition,
sizeof(FTPD_DATA_DEFINITION) );
//
// Create data for return for each instance
//
pPerfInstanceDefinition = (PERF_INSTANCE_DEFINITION *)
&pFtpdDataDefinition[1];
//
// Set first block of Buffer for _Total
//
MonBuildInstanceDefinition(
pPerfInstanceDefinition,
(PVOID *)&pCounterBlock,
0,
0,
(DWORD)-1, // use name
TOTAL_INSTANCE_NAME ); // pass in instance name
pTotal = pCounterBlock;
memset( pTotal, 0, sizeof(FTPD_COUNTER_BLOCK ));
pTotal->PerfCounterBlock.ByteLength = sizeof (FTPD_COUNTER_BLOCK);
pPerfInstanceDefinition =
(PERF_INSTANCE_DEFINITION *)((LPBYTE)pCounterBlock +
sizeof(FTPD_COUNTER_BLOCK));
neterr = FtpQueryStatistics2(
NULL,
0,
0, // instance id, 0 for global stats
0,
(LPBYTE *)&pFTPStats );
if( neterr == NERR_Success )
{
pTotal->ServiceUptime = pFTPStats->ServiceUptime;
}
MIDL_user_free( pFTPStats );
for ( i = 0; i < pSites->cEntries; i++)
{
MonBuildInstanceDefinition(
pPerfInstanceDefinition,
(PVOID *)&pCounterBlock,
0,
0,
(DWORD)-1, // use name
pSites->aSiteEntry[i].pszComment // pass in instance name
);
//
// query for statistics info
//
neterr = FtpQueryStatistics2(
NULL,
0,
pSites->aSiteEntry[i].dwInstance, // instance id
0,
(LPBYTE *)&pFTPStats );
if( neterr != NERR_Success )
{
//
// Only event log once for each server down
//
// if the server is down, we don't log an error.
if ( !( neterr == RPC_S_SERVER_UNAVAILABLE ||
neterr == RPC_S_UNKNOWN_IF ||
neterr == ERROR_SERVICE_NOT_ACTIVE ||
neterr == RPC_S_CALL_FAILED_DNE ))
{
//
// Error retrieving statistics.
//
ReportEvent (hEventLog, EVENTLOG_ERROR_TYPE,
0, FTP_UNABLE_QUERY_DATA,
(PSID)NULL, 0,
sizeof(neterr), NULL,
(PVOID)(&neterr));
}
*lpcbTotalBytes = 0;
*lpNumObjectTypes = 0;
MIDL_user_free(pSites);
return NO_ERROR;
}
//
// Format the FTP Server data.
//
CopyStatisticsData( pFTPStats,
pCounterBlock );
//
// update _total instance counters
//
Update_TotalStatisticsData( pCounterBlock,
pTotal );
pPerfInstanceDefinition =
(PERF_INSTANCE_DEFINITION *)((LPBYTE)pCounterBlock +
sizeof(FTPD_COUNTER_BLOCK));
//
// Free the API buffer.
//
MIDL_user_free( pFTPStats );
}
if (dwInstanceCount == 1) {
DWORD cbSize = sizeof(PERF_INSTANCE_DEFINITION) +
MAX_SIZEOF_INSTANCE_NAME +
sizeof(FTPD_COUNTER_BLOCK);
//
// zero fill one instance sized block of data if there's no data
// instances
//
memset (pPerfInstanceDefinition, 0, cbSize);
// adjust pointer to point to end of zeroed block
pPerfInstanceDefinition += cbSize;
}
//
// Update arguments for return.
//
*lppData = (PVOID)(pPerfInstanceDefinition);
*lpNumObjectTypes = 1;
pFtpdDataDefinition->FtpdObjectType.NumInstances = dwInstanceCount;
pFtpdDataDefinition->FtpdObjectType.TotalByteLength =
*lpcbTotalBytes = DIFF((PBYTE)pPerfInstanceDefinition -
(PBYTE)pFtpdDataDefinition);
//
// Success! Honest!!
//
MIDL_user_free(pSites);
return NO_ERROR;
} // CollectFTPPerformanceData
/*******************************************************************
NAME: CloseFtpPerformanceData
SYNOPSIS: Terminates the performance counters.
RETURNS: DWORD - Win32 status code.
HISTORY:
KeithMo 07-Jun-1993 Created.
********************************************************************/
DWORD CloseFtpPerformanceData( VOID )
{
DWORD dwCount = InterlockedDecrement((LPLONG )&cOpens);
if ((dwCount) == 0) {
if (hEventLog != NULL)
{
DeregisterEventSource (hEventLog);
hEventLog = NULL;
};
}
return NO_ERROR;
} // CloseFTPPerformanceData
VOID
CopyStatisticsData(
IN FTP_STATISTICS_0 * pFTPStats,
OUT FTPD_COUNTER_BLOCK * pCounterBlock
)
{
//
// Format the FTP Server data.
//
pCounterBlock->PerfCounterBlock.ByteLength = sizeof (FTPD_COUNTER_BLOCK);
pCounterBlock->BytesSent = pFTPStats->TotalBytesSent.QuadPart;
pCounterBlock->BytesReceived = pFTPStats->TotalBytesReceived.QuadPart;
pCounterBlock->BytesTotal = pFTPStats->TotalBytesSent.QuadPart +
pFTPStats->TotalBytesReceived.QuadPart;
pCounterBlock->FilesSent = pFTPStats->TotalFilesSent;
pCounterBlock->FilesReceived = pFTPStats->TotalFilesReceived;
pCounterBlock->FilesTotal = pFTPStats->TotalFilesSent +
pFTPStats->TotalFilesReceived;
pCounterBlock->CurrentAnonymous = pFTPStats->CurrentAnonymousUsers;
pCounterBlock->CurrentNonAnonymous = pFTPStats->CurrentNonAnonymousUsers;
pCounterBlock->TotalAnonymous = pFTPStats->TotalAnonymousUsers;
pCounterBlock->TotalNonAnonymous = pFTPStats->TotalNonAnonymousUsers;
pCounterBlock->MaxAnonymous = pFTPStats->MaxAnonymousUsers;
pCounterBlock->MaxNonAnonymous = pFTPStats->MaxNonAnonymousUsers;
pCounterBlock->CurrentConnections = pFTPStats->CurrentConnections;
pCounterBlock->MaxConnections = pFTPStats->MaxConnections;
pCounterBlock->ConnectionAttempts = pFTPStats->ConnectionAttempts;
pCounterBlock->LogonAttempts = pFTPStats->LogonAttempts;
pCounterBlock->ServiceUptime = pFTPStats->ServiceUptime;
// These counters are currently meaningless, but should be restored if we
// ever enable per-FTP-instance bandwidth throttling.
/*
pCounterBlock->BlockedRequests = pFTPStats->TotalBlockedRequests;
pCounterBlock->AllowedRequests = pFTPStats->TotalAllowedRequests;
pCounterBlock->RejectedRequests = pFTPStats->TotalRejectedRequests;
pCounterBlock->MeasuredBandwidth= pFTPStats->MeasuredBandwidth;
pCounterBlock->CurrentBlockedRequests = pFTPStats->CurrentBlockedRequests;
*/
} // CopyStatisticsData
VOID
Update_TotalStatisticsData(
IN FTPD_COUNTER_BLOCK * pCounterBlock,
OUT FTPD_COUNTER_BLOCK * pTotal
)
{
//
// update _total instance counters
//
pTotal->BytesSent += pCounterBlock->BytesSent;
pTotal->BytesReceived += pCounterBlock->BytesReceived;
pTotal->BytesTotal += pCounterBlock->BytesTotal;
pTotal->FilesSent += pCounterBlock->FilesSent;
pTotal->FilesReceived += pCounterBlock->FilesReceived;
pTotal->FilesTotal += pCounterBlock->FilesTotal;
pTotal->CurrentAnonymous += pCounterBlock->CurrentAnonymous;
pTotal->CurrentNonAnonymous += pCounterBlock->CurrentNonAnonymous;
pTotal->TotalAnonymous += pCounterBlock->TotalAnonymous;
pTotal->TotalNonAnonymous += pCounterBlock->TotalNonAnonymous;
pTotal->MaxAnonymous += pCounterBlock->MaxAnonymous;
pTotal->MaxNonAnonymous += pCounterBlock->MaxNonAnonymous;
pTotal->CurrentConnections += pCounterBlock->CurrentConnections;
pTotal->MaxConnections += pCounterBlock->MaxConnections;
pTotal->ConnectionAttempts = pCounterBlock->ConnectionAttempts;
pTotal->LogonAttempts += pCounterBlock->LogonAttempts;
// These counters are currently meaningless, but should be restored if we
// ever enable per-FTP-instance bandwidth throttling.
/*
pTotal->BlockedRequests += pCounterBlock->BlockedRequests;
pTotal->RejectedRequests += pCounterBlock->RejectedRequests;
pTotal->AllowedRequests += pCounterBlock->AllowedRequests;
pTotal->MeasuredBandwidth += pCounterBlock->MeasuredBandwidth;
pTotal->CurrentBlockedRequests += pCounterBlock->CurrentBlockedRequests;
*/
} // Update_TotalStatisticsData