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.
 
 
 
 
 
 

1102 lines
33 KiB

/**********************************************************************/
/** Microsoft Windows NT **/
/** Copyright(c) Microsoft Corp., 1993 **/
/**********************************************************************/
/*
entrypts.cxx
This file implements the Extensible Performance Objects for
the iis counters.
FILE HISTORY:
EmilyK 24-Aug-2000 Created, based on w3ctrs code.
*/
#include "precomp.h"
//
// common defines & globals
//
#define MAX_STRINGIZED_ULONG_CHAR_COUNT 11 // "4294967295", including the terminating null
DWORD g_IIS_SecondsToNotLogFor = 60 * 60 * 12; // 60 seconds = 1 minute * 60 = 1 hour * 12 = 12 hours
//
// Public prototypes.
//
PM_OPEN_PROC OpenW3PerformanceData;
PM_COLLECT_PROC CollectW3PerformanceData;
PM_CLOSE_PROC CloseW3PerformanceData;
//
// Global object contecting to the site counters memory.
//
CRITICAL_SECTION g_IISMemManagerCriticalSection;
PERF_SM_MANAGER* g_pIISMemManager;
LONG g_IISNumberInitialized;
HANDLE g_hWASProcessWait;
// Pointer to the event log class so we can log problems with perf counters.
EVENT_LOG* g_pEventLog = NULL;
//
// Private Supporting Functions
//
/***************************************************************************++
Routine Description:
Looks up in the registry all the specific counter values
that we need to be able to play nice with the other counters
on the machine.
Arguments:
None
Return Value:
DWORD - Win32 Error Code
--***************************************************************************/
DWORD EstablishIndexes()
{
DWORD err = NO_ERROR;
HKEY hkey = NULL;
DWORD size;
DWORD type;
DWORD dwFirstCounter;
DWORD dwFirstHelp;
PERF_COUNTER_DEFINITION* pDefinition = NULL;
//
// Open the HTTP Server service's Performance key.
//
err = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
REGISTRY_KEY_W3SVC_PERFORMANCE_KEY_A,
0,
KEY_QUERY_VALUE,
&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 && type == REG_DWORD )
{
//
// Read the first help DWORD.
//
size = sizeof(DWORD);
err = RegQueryValueEx( hkey,
"First Help",
NULL,
&type,
(LPBYTE)&dwFirstHelp,
&size );
if ( err == NO_ERROR && type == REG_DWORD )
{
//
// First establish all of the W3 Service Counters
// ==============================================
//
// Update the object & counter name & help indicies.
//
W3DataDefinition.W3ObjectType.ObjectNameTitleIndex
+= dwFirstCounter;
W3DataDefinition.W3ObjectType.ObjectHelpTitleIndex
+= dwFirstHelp;
//
// Figure out the first counter definition. It starts
// after the PERF_OBJECT_TYPE structure, which is the
// first iten in the W3DataDefinition.
//
pDefinition = (PERF_COUNTER_DEFINITION*) ((LPBYTE) (&W3DataDefinition)
+ sizeof(PERF_OBJECT_TYPE));
//
// Now simply walk through the counters incrementing
// the pDefinition by on PERF_COUNTER_DEFINITION as you go.
//
for (int i = 0; i < NUMBER_OF_W3_COUNTERS; i++, pDefinition++)
{
pDefinition->CounterNameTitleIndex += dwFirstCounter;
pDefinition->CounterHelpTitleIndex += dwFirstHelp;
}
//
// Now do all of the W3 Global Service Counters
// ============================================
//
// Update the object & counter name & help indicies.
//
W3GlobalDataDefinition.W3GlobalObjectType.ObjectNameTitleIndex
+= dwFirstCounter;
W3GlobalDataDefinition.W3GlobalObjectType.ObjectHelpTitleIndex
+= dwFirstHelp;
//
// Figure out the first counter definition. It starts
// after the PERF_OBJECT_TYPE structure, which is the
// first iten in the W3DataDefinition.
//
pDefinition = (PERF_COUNTER_DEFINITION*)
((LPBYTE) (&W3GlobalDataDefinition)
+ sizeof(PERF_OBJECT_TYPE));
//
// Now simply walk through the counters incrementing
// the pDefinition by on PERF_COUNTER_DEFINITION as you go.
//
for ( int i = 0;
i < NUMBER_OF_W3_GLOBAL_COUNTERS;
i++, pDefinition++ )
{
pDefinition->CounterNameTitleIndex += dwFirstCounter;
pDefinition->CounterHelpTitleIndex += dwFirstHelp;
}
}
}
if( hkey != NULL )
{
RegCloseKey( hkey );
hkey = NULL;
}
}
return err;
}
/***************************************************************************++
Routine Description:
Routine deletes the shared memory if it is in existence.
Arguments:
None
Return Value:
None
Note: It should always be called from inside a critical section.
--***************************************************************************/
VOID FreeSharedManager(BOOL HandleCallbackAsWell
)
{
//
// Only clean up the callback handle if we are told
// to, this is so we don't clean it up if we are
// in the middle of a callback call.
//
if ( HandleCallbackAsWell && g_hWASProcessWait )
{
if ( !UnregisterWait( g_hWASProcessWait ) )
{
DPERROR((
DBG_CONTEXT,
HRESULT_FROM_WIN32(GetLastError()),
"Could not unregister the old process wait handle \n"
));
}
g_hWASProcessWait = NULL;
}
//
// Now clean up the shared memory object.
//
if ( g_pIISMemManager )
{
delete g_pIISMemManager;
g_pIISMemManager = NULL;
}
}
/***************************************************************************++
Routine Description:
Routine drops the shared memory if the managing process of the memory
goes away.
Arguments:
LPVOID lpParameter - Unused
BOOL bUnused - Unused
Return Value:
None
--***************************************************************************/
VOID CALLBACK ShutdownMemory(
PVOID,
BOOLEAN
)
{
EnterCriticalSection ( &g_IISMemManagerCriticalSection );
FreeSharedManager(FALSE);
LeaveCriticalSection ( &g_IISMemManagerCriticalSection );
}
/***************************************************************************++
Routine Description:
Helper function to hook up to shared memory when we are ready to
provide counters.
Arguments:
None.
Return Value:
DWORD - Win32 Error Code
--***************************************************************************/
DWORD
HookUpSharedMemory()
{
DWORD dwErr = ERROR_SUCCESS;
DWORD size = 0;
DWORD type = 0;
DWORD dwRegSettingValue = 0;
HKEY hkey = NULL;
//
// If we are not hooked up to the manager than hook up.
//
if ( !g_pIISMemManager )
{
//
// Hook up to the manager of the shared memory.
//
g_pIISMemManager = new PERF_SM_MANAGER();
if ( ! g_pIISMemManager )
{
dwErr = ERROR_OUTOFMEMORY;
goto exit;
}
//
// Initialize the memory manager for readonly access
//
dwErr = g_pIISMemManager->Initialize(FALSE);
if ( dwErr != ERROR_SUCCESS )
{
goto exit;
}
// This ( in the Initialize call above ) is when we read
// the wait times for the perf counters
// from the registry so this is when we should set the logging
// wait time as well.
//
dwErr = RegOpenKeyExW( HKEY_LOCAL_MACHINE,
REGISTRY_KEY_W3SVC_PERFORMANCE_KEY_W,
0,
KEY_QUERY_VALUE,
&hkey );
if( dwErr == ERROR_SUCCESS)
{
size = sizeof(DWORD);
dwErr = RegQueryValueExW( hkey,
REGISTRY_VALUE_W3SVC_PERF_EVENT_LOG_DELAY_OVERRIDE_W,
NULL,
&type,
(LPBYTE)&dwRegSettingValue,
&size );
if( dwErr == ERROR_SUCCESS && type == REG_DWORD )
{
if ( dwRegSettingValue != 0 )
{
g_IIS_SecondsToNotLogFor = dwRegSettingValue;
}
}
if( hkey != NULL )
{
RegCloseKey( hkey );
hkey = NULL;
}
}
// Press on in the face of errors.
dwErr = ERROR_SUCCESS;
//
//
// if we re-initialized then we need to setup the
// wait on the process again. it is possible that
// the previous wait has not been cleaned up (since
// we can't clean it up in the callback function) so
// if this is the case we need to clean it up first.
//
if ( g_hWASProcessWait != NULL )
{
if ( !UnregisterWait( g_hWASProcessWait ) )
{
DPERROR((
DBG_CONTEXT,
HRESULT_FROM_WIN32(GetLastError()),
"Could not unregister the old process wait handle \n"
));
}
g_hWASProcessWait = NULL;
}
//
// Register to wait on the managing process,
// so we release any shared memory if the managing
// process shutsdown or crashes.
//
if ( !RegisterWaitForSingleObject( &g_hWASProcessWait,
g_pIISMemManager->GetWASProcessHandle(),
&ShutdownMemory,
NULL,
INFINITE,
WT_EXECUTEONLYONCE |
WT_EXECUTEINIOTHREAD ) )
{
dwErr = GetLastError();
DPERROR((
DBG_CONTEXT,
HRESULT_FROM_WIN32(dwErr),
"Could not register to wait on the process handle \n"
));
goto exit;
}
//
// Initialize a reader to point to the appropriate
// counter set.
//
dwErr = g_pIISMemManager->CreateNewCounterSet( SITE_COUNTER_SET );
if ( dwErr != ERROR_SUCCESS )
{
goto exit;
}
//
// Initialize a reader to point to the appropriate
// counter set.
//
dwErr = g_pIISMemManager->CreateNewCounterSet( GLOBAL_COUNTER_SET );
if ( dwErr != ERROR_SUCCESS )
{
goto exit;
}
}
//
// Whether we just hooked up to the memory or not, we still want
// to do one final check to make sure the memory is still valid.
// It might have been invalidated in since the last gathering, or
// it might have been invalidated while we were hooking up the
// wait on the process id. Either way, if it is now not valid,
// drop it.
//
if ( g_pIISMemManager->ReleaseIsNeeded() )
{
//
// The exit will take care of deleteing
// the memory manager which will release
// the files.
//
dwErr = ERROR_NOT_READY;
goto exit;
}
exit:
if ( dwErr != ERROR_SUCCESS )
{
FreeSharedManager(TRUE);
}
return dwErr;
}
//
// Public Exported functions.
//
/***************************************************************************++
Routine Description:
Is called to initialize any memory data structures needed for
supporting the performance counter publishing.
Arguments:
Return Value:
DWORD - Win32 Error Code
--***************************************************************************/
DWORD OpenW3PerformanceData( LPWSTR )
{
DWORD dwErr = ERROR_SUCCESS;
static BOOL fInit = FALSE;
IF_DEBUG( WEB_ADMIN_SERVICE_PERFCOUNT )
{
DBGPRINTF((
DBG_CONTEXT,
"Entering W3CTRS - OpenW3PerformanceData routine \n"
));
}
//
// If we are the first one here then we can setup the
// objects the correct way.
//
// Note: this is not neccessarily completely safe, but
// it really isn't that big of a problem if these
// objects get setup twice.
//
if ( !fInit )
{
//
// Setup the event log so we can log errors.
//
// If this fails then the g_pEventLog will still
// be null. We would not fail in this case, and
// since we do not have the event viewer we really
// don't have any place to log a message. We will
// validate that this has been set before using it
// throughout the code.
//
g_pEventLog = new EVENT_LOG(L"W3CTRS");
//
// Establish all machine static information about
// the counters.
//
dwErr = EstablishIndexes();
if ( dwErr != ERROR_SUCCESS )
{
if ( g_pEventLog )
{
g_pEventLog->
LogEvent(
W3_W3SVC_REGISTRATION_MAY_BE_BAD, // message id
0, // count of strings
NULL, // array of strings
HRESULT_FROM_WIN32(dwErr) // error code
);
}
goto exit;
}
fInit = TRUE;
}
exit:
IF_DEBUG( WEB_ADMIN_SERVICE_PERFCOUNT )
{
DBGPRINTF((
DBG_CONTEXT,
"Exiting W3CTRS - OpenW3PerformanceData routine \n"
));
}
return dwErr;
} // OpenW3PerformanceData
/***************************************************************************++
Routine Description:
Is called to retrieve counters from our library.
Arguments:
LPWSTR lpValueName - Name fo the set of counters to retrieve.
LPVOID * 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.
LPDWORD 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.
LPDWORD lpNumObjectTypes - Receives the number of objects added
by this routine.
Return Value:
DWORD - Win32 Error Code (MUST be either NO_ERROR or ERROR_MORE_DATA)
--***************************************************************************/
DWORD CollectW3PerformanceData(
LPWSTR lpValueName,
LPVOID * lppData,
LPDWORD lpcbTotalBytes,
LPDWORD lpNumObjectTypes
)
{
DBG_ASSERT ( lppData );
DBG_ASSERT ( lpcbTotalBytes );
DBG_ASSERT ( lpNumObjectTypes );
static DWORD s_FirstFailureAt = 0;
static DWORD s_NumberOfTimesTookToLong = 0;
LPVOID pData = *lppData;
COUNTER_GLOBAL_STRUCT* pSiteObject = NULL;
LPVOID pSiteInstance = NULL;
COUNTER_GLOBAL_STRUCT* pGlobalObject = NULL;
LPVOID pGlobalInstance = NULL;
DWORD dwErr = ERROR_SUCCESS;
DWORD dwSiteSize = 0;
DWORD dwGlobalSize = 0;
DWORD dwTotalSize = 0;
DWORD dwQueryType = GetQueryType( lpValueName );
BOOL fGetSites = TRUE;
BOOL fGetGlobal = TRUE;
DWORD NumObjects = 2;
//
// Figure out if it is a query type we do not support.
//
if (( dwQueryType == QUERY_FOREIGN ) || (dwQueryType == QUERY_COSTLY))
{
// We don't do foreign queries
*lpcbTotalBytes = 0;
*lpNumObjectTypes = 0;
return ERROR_SUCCESS;
}
//
// If it is a query by item, then figure out if we own any of the
// items it is referring to.
//
if( dwQueryType == QUERY_ITEMS )
{
//
// The registry is asking for a specific object. Let's
// see if we're one of the chosen.
//
if( !IsNumberInUnicodeList(
W3DataDefinition.W3ObjectType.ObjectNameTitleIndex,
lpValueName ) )
{
fGetSites = FALSE;
NumObjects--;
}
if( !IsNumberInUnicodeList(
W3GlobalDataDefinition.W3GlobalObjectType.ObjectNameTitleIndex,
lpValueName ) )
{
fGetGlobal = FALSE;
NumObjects--;
}
if ( NumObjects == 0 )
{
*lpcbTotalBytes = 0;
*lpNumObjectTypes = 0;
return ERROR_SUCCESS;
}
}
IF_DEBUG( WEB_ADMIN_SERVICE_PERFCOUNT )
{
DBGPRINTF((
DBG_CONTEXT,
"Entering W3CTRS - CollectW3PerformanceData routine \n"
));
}
//
// if we got this far then we know that we want to get something.
//
EnterCriticalSection ( &g_IISMemManagerCriticalSection );
dwErr = HookUpSharedMemory();
if ( dwErr != ERROR_SUCCESS )
{
DWORD dwSizeNeeded = 0;
DBG_ASSERT ( fGetSites || fGetGlobal );
if ( fGetSites )
{
dwSizeNeeded += sizeof(W3DataDefinition) +
sizeof(PERF_INSTANCE_DEFINITION) +
(sizeof(WCHAR) * MAX_INSTANCE_NAME ) +
sizeof(W3_COUNTER_BLOCK);
}
if ( fGetGlobal )
{
dwSizeNeeded += sizeof( W3GlobalDataDefinition )
+ sizeof( W3_GLOBAL_COUNTER_BLOCK );
}
if ( dwSizeNeeded > *lpcbTotalBytes )
{
*lpcbTotalBytes = 0;
*lpNumObjectTypes = 0;
dwErr = ERROR_MORE_DATA;
}
else
{
if ( fGetSites )
{
memcpy (pData, &W3DataDefinition, sizeof(W3DataDefinition));
((PERF_OBJECT_TYPE*) pData)->NumInstances = 1;
((PERF_OBJECT_TYPE*) pData)->TotalByteLength = sizeof(W3DataDefinition) +
sizeof(PERF_INSTANCE_DEFINITION) +
(sizeof(WCHAR) * MAX_INSTANCE_NAME) +
sizeof(W3_COUNTER_BLOCK);
pData = (LPBYTE) pData + sizeof(W3DataDefinition);
// Copy in a _Total instance
// First Setup the Instance Definition
((PERF_INSTANCE_DEFINITION*) pData)->ByteLength = sizeof(PERF_INSTANCE_DEFINITION) +
MAX_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 = (DWORD) ((wcslen(L"_Total") + 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, L"_Total", wcslen(L"_Total") + 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_INSTANCE_NAME * sizeof(WCHAR));
// Lastly copy in a block of zero's for the _Total site data.
memset ( pData, 0, sizeof(W3_COUNTER_BLOCK) );
// This is setting the size in the structure, it is the first
// DWORD in the W3_CONTER_BLOCK.
*((DWORD*) (pData)) = sizeof(W3_COUNTER_BLOCK);
pData = (LPBYTE) pData + sizeof(W3_COUNTER_BLOCK);
}
if ( fGetGlobal )
{
memcpy (pData, &W3GlobalDataDefinition, sizeof(W3GlobalDataDefinition));
((PERF_OBJECT_TYPE*) pData)->NumInstances = PERF_NO_INSTANCES;
((PERF_OBJECT_TYPE*) pData)->TotalByteLength = sizeof(W3GlobalDataDefinition) +
sizeof(W3_GLOBAL_COUNTER_BLOCK);
pData = (LPBYTE) pData + sizeof(W3GlobalDataDefinition);
// Copy in the actual data for global
memset ( pData, 0, sizeof(W3_GLOBAL_COUNTER_BLOCK) );
// This is setting the size in the structure, it is the first
// DWORD in the W3_GLOBAL_CONTER_BLOCK.
*((DWORD*) (pData)) = sizeof(W3_GLOBAL_COUNTER_BLOCK);
pData = (LPBYTE) pData + sizeof(W3_GLOBAL_COUNTER_BLOCK);
}
// Make sure we didn't lie about the size.
DBG_ASSERT ( dwSizeNeeded == DIFF((PCHAR) pData - (PCHAR) (*lppData)) );
*lpcbTotalBytes = dwSizeNeeded;
*lpNumObjectTypes = NumObjects;
*lppData = pData;
dwErr = ERROR_SUCCESS;
}
goto exit;
}
DBG_ASSERT ( g_pIISMemManager );
//
// Now check that the memory has been updated recently. If it has
// not been then we need to ping WAS and let them know that we need
// new data, and wait on that new data.
//
if ( ! g_pIISMemManager->EvaluateIfCountersAreFresh() )
{
if ( g_pEventLog )
{
IF_DEBUG( WEB_ADMIN_SERVICE_PERFCOUNT )
{
DBGPRINTF((
DBG_CONTEXT,
"Perf Counters did not refresh in a timely manner: \n"
" CurrentSecondsCount = %d \n"
" FirstFailure was %d \n"
" Time to wait to restart is %d \n"
" NumberFailures = %d \n",
GetCurrentTimeInSeconds(),
s_FirstFailureAt,
g_IIS_SecondsToNotLogFor,
s_NumberOfTimesTookToLong
));
}
if ( ( s_FirstFailureAt == 0 ) ||
( ( s_FirstFailureAt + g_IIS_SecondsToNotLogFor ) < GetCurrentTimeInSeconds() ) )
{
s_FirstFailureAt = GetCurrentTimeInSeconds();
s_NumberOfTimesTookToLong = 0;
}
s_NumberOfTimesTookToLong++;
if ( s_NumberOfTimesTookToLong == 1 )
{
g_pEventLog->
LogEvent(
W3_W3SVC_REFRESH_TAKING_TOO_LONG, // message id
0, // count of strings
NULL, // array of strings
0 // error code
);
}
if ( s_NumberOfTimesTookToLong == 2 )
{
DWORD Hours = g_IIS_SecondsToNotLogFor / 60 / 60;
DWORD Minutes = ( g_IIS_SecondsToNotLogFor - ( Hours * 60 * 60 ) ) / 60;
DWORD Seconds = g_IIS_SecondsToNotLogFor - ( Hours * 60 * 60 ) - ( Minutes * 60 );
const WCHAR * EventLogStrings[1];
// Format is "DWORD:DWORD:DWORD" So 3 max dwords plus two colons and a null
WCHAR StringizedTimeLimit[ (MAX_STRINGIZED_ULONG_CHAR_COUNT * 3) + 3 ];
_snwprintf( StringizedTimeLimit,
sizeof( StringizedTimeLimit ) / sizeof ( WCHAR ),
L"%lu:%02lu:%02lu",
Hours,
Minutes,
Seconds);
EventLogStrings[0] = StringizedTimeLimit;
g_pEventLog->
LogEvent(
W3_W3SVC_REFRESH_TAKING_TOO_LONG_STOPPING_LOGGING, // message id
sizeof( EventLogStrings ) / sizeof( const WCHAR * ), // count of strings
EventLogStrings, // array of strings
0 // error code
);
// if s_NumberOfTimesTookToLong is anything else
// then we don't bother printing anything.
}
}
}
if ( fGetSites)
{
//
// Get the counter information from shared memory.
//
dwErr = g_pIISMemManager->GetCounterInfo(SITE_COUNTER_SET,
&pSiteObject,
&pSiteInstance);
if ( dwErr != ERROR_SUCCESS )
{
if ( g_pEventLog )
{
g_pEventLog->
LogEvent(
W3_UNABLE_QUERY_W3SVC_DATA, // message id
0, // count of strings
NULL, // array of strings
HRESULT_FROM_WIN32(dwErr) // error code
);
}
//
// According to the perf by laws you can only
// return Success or More Data from here so
// we will need to log the error and then return
// Success, since this does not mean we have more data.
//
*lpcbTotalBytes = 0;
*lpNumObjectTypes = 0;
dwErr = ERROR_SUCCESS;
goto exit;
}
dwSiteSize = sizeof(W3DataDefinition) + pSiteObject->SizeData;
}
if ( fGetGlobal )
{
//
// Get the counter information from shared memory.
//
dwErr = g_pIISMemManager->GetCounterInfo(GLOBAL_COUNTER_SET,
&pGlobalObject,
&pGlobalInstance);
if ( dwErr != ERROR_SUCCESS )
{
if ( g_pEventLog )
{
g_pEventLog->
LogEvent(
W3_UNABLE_QUERY_W3SVC_DATA, // message id
0, // count of strings
NULL, // array of strings
HRESULT_FROM_WIN32(dwErr) // error code
);
}
//
// According to the perf by laws you can only
// return Success or More Data from here so
// we will need to log the error and then return
// Success, since this does not mean we have more data.
//
*lpcbTotalBytes = 0;
*lpNumObjectTypes = 0;
dwErr = ERROR_SUCCESS;
goto exit;
}
dwGlobalSize = sizeof(W3GlobalDataDefinition) +
pGlobalObject->SizeData;
}
//
// Figure out the total size of the memory
//
dwTotalSize = dwSiteSize + dwGlobalSize;
//
// If we don't have room tell the counter library.
//
if ( dwTotalSize > *lpcbTotalBytes )
{
*lpcbTotalBytes = 0;
*lpNumObjectTypes = 0;
dwErr = ERROR_MORE_DATA;
goto exit;
}
if ( fGetSites )
{
//
// Copy in the definition of the data for sites.
//
memcpy (pData, &W3DataDefinition, sizeof(W3DataDefinition));
((PERF_OBJECT_TYPE*) pData)->NumInstances = pSiteObject->NumInstances;
((PERF_OBJECT_TYPE*) pData)->TotalByteLength = dwSiteSize;
pData = (LPBYTE) pData + sizeof(W3DataDefinition);
// Copy in the actual data for sites
memcpy ( pData, pSiteInstance, pSiteObject->SizeData );
pData = (LPBYTE) pData + pSiteObject->SizeData;
}
if ( fGetGlobal )
{
//
// Copy in the definition of the data for global
//
memcpy (pData, &W3GlobalDataDefinition, sizeof(W3GlobalDataDefinition));
((PERF_OBJECT_TYPE*) pData)->NumInstances = pGlobalObject->NumInstances;
((PERF_OBJECT_TYPE*) pData)->TotalByteLength = dwGlobalSize;
pData = (LPBYTE) pData + sizeof(W3GlobalDataDefinition);
// Copy in the actual data for global
memcpy ( pData, pGlobalInstance, pGlobalObject->SizeData );
pData = (LPBYTE) pData + pGlobalObject->SizeData;
}
// Make sure we didn't lie about the size.
DBG_ASSERT ( dwTotalSize == DIFF((PCHAR) pData - (PCHAR) (*lppData)) );
*lpcbTotalBytes = dwTotalSize;
*lpNumObjectTypes = NumObjects;
*lppData = pData;
//
// Let WAS know that we need new counters.
//
g_pIISMemManager->PingWASToRefreshCounters();
exit:
LeaveCriticalSection ( &g_IISMemManagerCriticalSection );
IF_DEBUG( WEB_ADMIN_SERVICE_PERFCOUNT )
{
DBGPRINTF((
DBG_CONTEXT,
"Exiting W3CTRS - CollectW3PerformanceData routine \n"
));
}
return dwErr;
} // CollectW3PerformanceData
/***************************************************************************++
Routine Description:
Terminates the performance counters.
Arguments:
None.
Return Value:
DWORD - Win32 Error Code
--***************************************************************************/
DWORD CloseW3PerformanceData( VOID )
{
//
// On tclose tell the timer queue to stop launching
// the checking code.
//
// Note if someone calls close and then collect again
// we will have stopped listening to notifications from
// w3svc and will not know when to drop the memory.
//
IF_DEBUG( WEB_ADMIN_SERVICE_PERFCOUNT )
{
DBGPRINTF((
DBG_CONTEXT,
"Entering W3CTRS - CloseW3PerformanceData routine \n"
));
}
EnterCriticalSection ( &g_IISMemManagerCriticalSection );
FreeSharedManager(TRUE);
LeaveCriticalSection( &g_IISMemManagerCriticalSection );
if ( g_pEventLog )
{
delete g_pEventLog;
g_pEventLog = NULL;
}
IF_DEBUG( WEB_ADMIN_SERVICE_PERFCOUNT )
{
DBGPRINTF((
DBG_CONTEXT,
"Exiting W3CTRS - CloseW3PerformanceData routine \n"
));
}
return ERROR_SUCCESS;
} // CloseW3PerformanceData