|
|
/**********************************************************************/ /** 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
|