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.
2010 lines
69 KiB
2010 lines
69 KiB
/*++
|
|
|
|
Copyright (C) 1999-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ADAPPERF.CPP
|
|
|
|
Abstract:
|
|
|
|
History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#include <stdio.h>
|
|
#include <wbemcli.h>
|
|
#include <cominit.h>
|
|
#include <WinMgmtR.h>
|
|
#include "ntreg.h"
|
|
#include "adapperf.h"
|
|
#include "adaputil.h"
|
|
|
|
|
|
#define PL_TIMEOUT 100000 // The timeout value for waiting on a function mutex
|
|
#define GUARD_BLOCK "WMIADAP_WMIADAP_WMIADAP_WMIADAP_WMIADAP_WMIADAP_WMIADAP_WMIADAP"
|
|
|
|
BYTE CAdapSafeBuffer::s_pGuardBytes[] = GUARD_BLOCK;
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CAdapSafeDataBlock
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
CAdapSafeBuffer::CAdapSafeBuffer( WString wstrServiceName )
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Constructor
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
: m_dwGuardSize ( 0 ),
|
|
m_hPerfLibHeap ( NULL ),
|
|
m_pRawBuffer ( NULL ),
|
|
m_pSafeBuffer ( NULL ),
|
|
m_dwSafeBufferSize ( 0 ),
|
|
m_pCurrentPtr ( NULL ),
|
|
m_dwNumObjects ( 0 ),
|
|
m_wstrServiceName ( wstrServiceName )
|
|
{
|
|
// Initialize the guard byte pattern
|
|
// =================================
|
|
|
|
m_dwGuardSize = sizeof( GUARD_BLOCK );
|
|
|
|
// Create the private heap
|
|
// =======================
|
|
|
|
m_hPerfLibHeap = HeapCreate( 0, 0x100000, 0 );
|
|
|
|
// If the private heap could not be created, then use the process heap
|
|
// ===================================================================
|
|
|
|
if ( NULL == m_hPerfLibHeap )
|
|
{
|
|
m_hPerfLibHeap = GetProcessHeap();
|
|
}
|
|
}
|
|
|
|
CAdapSafeBuffer::~CAdapSafeBuffer()
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Destructor
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
{
|
|
// Deallocate the raw buffer
|
|
// =========================
|
|
|
|
if ( NULL != m_pRawBuffer )
|
|
{
|
|
HeapFree( m_hPerfLibHeap, 0, m_pRawBuffer );
|
|
}
|
|
|
|
// Destroy the private heap
|
|
// ========================
|
|
|
|
if ( ( NULL != m_hPerfLibHeap ) && ( GetProcessHeap() != m_hPerfLibHeap ) )
|
|
{
|
|
HeapDestroy( m_hPerfLibHeap );
|
|
}
|
|
}
|
|
|
|
HRESULT CAdapSafeBuffer::SetSize( DWORD dwNumBytes )
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Sets the size of the safe buffer. Memory is actually allocated for the raw buffer, and
|
|
// the safe buffer just sits in the raw buffer between the set of guard bytes
|
|
//
|
|
// Parameters:
|
|
// dwNumBytes - the number of bytes requested for the safe buffer
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
{
|
|
HRESULT hr = WBEM_NO_ERROR;
|
|
|
|
DWORD dwRawBufferSize = 0;
|
|
|
|
// Check for roll-over
|
|
// ===================
|
|
|
|
if ( dwNumBytes > ( 0xFFFFFFFF - ( 2 * m_dwGuardSize ) ) )
|
|
{
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
|
|
if ( SUCCEEDED ( hr ) )
|
|
{
|
|
// Set the total size of the buffer
|
|
// ================================
|
|
|
|
m_dwSafeBufferSize = dwNumBytes;
|
|
dwRawBufferSize = dwNumBytes + ( 2 * m_dwGuardSize );
|
|
|
|
// Allocate the memory
|
|
// ===================
|
|
if ( NULL == m_pRawBuffer )
|
|
{
|
|
// First time allocation
|
|
// =====================
|
|
m_pRawBuffer = (BYTE*) HeapAlloc( m_hPerfLibHeap,
|
|
HEAP_ZERO_MEMORY,
|
|
dwRawBufferSize );
|
|
}
|
|
else
|
|
{
|
|
BYTE * pTmp = (BYTE *)HeapReAlloc( m_hPerfLibHeap,
|
|
HEAP_ZERO_MEMORY,
|
|
m_pRawBuffer,
|
|
dwRawBufferSize );
|
|
if (pTmp)
|
|
{
|
|
m_pRawBuffer = pTmp;
|
|
}
|
|
else
|
|
{
|
|
HeapFree(m_hPerfLibHeap,0,m_pRawBuffer);
|
|
m_pRawBuffer = NULL;
|
|
}
|
|
}
|
|
|
|
if ( NULL != m_pRawBuffer )
|
|
{
|
|
// Set the safe buffer pointer
|
|
// ===========================
|
|
|
|
m_pSafeBuffer = m_pRawBuffer + m_dwGuardSize;
|
|
|
|
// Set the prefix guard bytes
|
|
// =========================
|
|
|
|
memcpy( m_pRawBuffer, s_pGuardBytes, m_dwGuardSize );
|
|
|
|
// Set the suffix guard bytes
|
|
// ==========================
|
|
|
|
memcpy( m_pSafeBuffer + m_dwSafeBufferSize, s_pGuardBytes, m_dwGuardSize );
|
|
}
|
|
else
|
|
{
|
|
m_pSafeBuffer = NULL;
|
|
m_pCurrentPtr = NULL;
|
|
m_dwSafeBufferSize = 0;
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CAdapSafeBuffer::Validate(BOOL * pSentToEventLog)
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Validate will compare the size of the pointer displacement matches the byte size
|
|
// returned from the collection, validates the guard bytes and walks the blob, verifying
|
|
// that all of the pointers are within the boundary of the blob
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
{
|
|
HRESULT hr = WBEM_NO_ERROR;
|
|
|
|
try
|
|
{
|
|
PERF_OBJECT_TYPE* pObject = (PERF_OBJECT_TYPE*) m_pSafeBuffer;
|
|
|
|
// Validate that if we have objects, then we have mass
|
|
// ===================================================
|
|
|
|
if ( ( 0 < m_dwNumObjects ) && ( 0 == m_dwDataBlobSize ) )
|
|
{
|
|
hr = WBEM_E_FAILED;
|
|
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
|
|
WBEM_MC_ADAP_BLOB_HAS_NO_SIZE,
|
|
(LPCWSTR)m_wstrServiceName );
|
|
if (pSentToEventLog) {
|
|
*pSentToEventLog = TRUE;
|
|
}
|
|
}
|
|
|
|
// Validate that that number of bytes returned is the same as the pointer displacement
|
|
// ===================================================================================
|
|
|
|
if ( SUCCEEDED( hr ) && ( ( m_pCurrentPtr - m_pSafeBuffer ) != m_dwDataBlobSize ) )
|
|
{
|
|
hr = WBEM_E_FAILED;
|
|
|
|
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
|
|
WBEM_MC_ADAP_BAD_PERFLIB_INVALID_DATA,
|
|
(LPCWSTR)m_wstrServiceName, CHex( hr ) );
|
|
if (pSentToEventLog) {
|
|
*pSentToEventLog = TRUE;
|
|
}
|
|
}
|
|
|
|
if ( SUCCEEDED ( hr ) )
|
|
{
|
|
// Validate the guard bytes
|
|
// ========================
|
|
|
|
if ( 0 != memcmp( m_pRawBuffer, s_pGuardBytes, m_dwGuardSize) )
|
|
{
|
|
hr = WBEM_E_FAILED;
|
|
|
|
CAdapUtility::NTLogEvent( EVENTLOG_ERROR_TYPE,
|
|
WBEM_MC_ADAP_BAD_PERFLIB_MEMORY,
|
|
(LPCWSTR)m_wstrServiceName, CHex( hr ) );
|
|
if (pSentToEventLog) {
|
|
*pSentToEventLog = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( 0 != memcmp( m_pSafeBuffer + m_dwSafeBufferSize, s_pGuardBytes, m_dwGuardSize) )
|
|
{
|
|
hr = WBEM_E_FAILED;
|
|
CAdapUtility::NTLogEvent( EVENTLOG_ERROR_TYPE,
|
|
WBEM_MC_ADAP_BAD_PERFLIB_MEMORY,
|
|
(LPCWSTR)m_wstrServiceName, CHex( hr ) );
|
|
if (pSentToEventLog) {
|
|
*pSentToEventLog = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Validate the blob
|
|
// =================
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
for ( int nObject = 0; SUCCEEDED( hr ) && nObject < m_dwNumObjects; nObject++ )
|
|
{
|
|
PERF_COUNTER_DEFINITION* pCtr = NULL;
|
|
DWORD dwCtrBlockSize = 0;
|
|
|
|
// Validate the object pointer
|
|
// ===========================
|
|
|
|
hr = ValidateSafePointer( (BYTE*) pObject );
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
// Validate the counter definitions
|
|
// ================================
|
|
|
|
if ( 0 == pObject->HeaderLength )
|
|
{
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
else
|
|
{
|
|
pCtr = ( PERF_COUNTER_DEFINITION* ) ( ( ( BYTE* ) pObject ) + pObject->HeaderLength );
|
|
}
|
|
}
|
|
|
|
for( int nCtr = 0; SUCCEEDED( hr ) && nCtr < pObject->NumCounters; nCtr++)
|
|
{
|
|
hr = ValidateSafePointer( ( BYTE* ) pCtr );
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
dwCtrBlockSize += pCtr->CounterSize;
|
|
|
|
if ( nCtr < ( pObject->NumCounters - 1 ) )
|
|
{
|
|
if ( 0 == pCtr->ByteLength )
|
|
{
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
else
|
|
{
|
|
pCtr = ( PERF_COUNTER_DEFINITION* ) ( ( ( BYTE* ) pCtr ) + pCtr->ByteLength );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Validate the data
|
|
// =================
|
|
|
|
if ( pObject->NumInstances >= 0 )
|
|
{
|
|
// Blob has instances
|
|
// ==================
|
|
|
|
PERF_INSTANCE_DEFINITION* pInstance = NULL;
|
|
|
|
if ( 0 == pObject->DefinitionLength )
|
|
{
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
else
|
|
{
|
|
pInstance = ( PERF_INSTANCE_DEFINITION* ) ( ( ( BYTE* ) pObject ) + pObject->DefinitionLength );
|
|
}
|
|
|
|
// Validate the instances
|
|
// ======================
|
|
|
|
|
|
for ( int nInst = 0; SUCCEEDED( hr ) && nInst < pObject->NumInstances; nInst++ )
|
|
{
|
|
|
|
hr = ValidateSafePointer( ( BYTE* ) pInstance );
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
PERF_COUNTER_BLOCK* pCounterBlock = NULL;
|
|
|
|
// Validate the counter blocks
|
|
// ===========================
|
|
|
|
if ( 0 == pInstance->ByteLength )
|
|
{
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
else
|
|
{
|
|
pCounterBlock = ( PERF_COUNTER_BLOCK* ) ( ( ( BYTE* ) pInstance ) + pInstance->ByteLength );
|
|
|
|
hr = ValidateSafePointer( ( BYTE* ) pCounterBlock );
|
|
}
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
// Is the counter block the same size as the aggregation of the counter sizes?
|
|
// ===========================================================================
|
|
|
|
if ( ( nInst < pObject->NumInstances - 1 ) && SUCCEEDED( hr ) )
|
|
{
|
|
pInstance = ( PERF_INSTANCE_DEFINITION* ) ( ( ( BYTE* ) pCounterBlock ) + pCounterBlock->ByteLength );
|
|
hr = ValidateSafePointer( (BYTE*) pInstance );
|
|
}
|
|
//
|
|
// validate the size of the last object against
|
|
// the 'aperture' of the buffer
|
|
//
|
|
/*
|
|
if (SUCCEEDED(hr) && (nInst == (pObject->NumInstances - 1)))
|
|
{
|
|
BYTE * pLast = ( ( ( BYTE* ) pCounterBlock ) + pCounterBlock->ByteLength );
|
|
// now pLast is 1 byte over the "end" of the buffer
|
|
if (pLast > m_pCurrentPtr)
|
|
{
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Blob is a singleton. Validate the counter blocks
|
|
// ================================================
|
|
|
|
if ( 0 == pObject->DefinitionLength )
|
|
{
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
else
|
|
{
|
|
PERF_COUNTER_BLOCK* pCounterBlock = ( PERF_COUNTER_BLOCK* ) ( ( ( BYTE* ) pObject ) + pObject->DefinitionLength );
|
|
hr = ValidateSafePointer( ( BYTE* ) pCounterBlock );
|
|
}
|
|
}
|
|
|
|
// Get the next object as long as one exists
|
|
// =========================================
|
|
|
|
if ( nObject < ( m_dwNumObjects - 1 ) )
|
|
{
|
|
pObject = (PERF_OBJECT_TYPE*)((BYTE*)pObject + pObject->TotalByteLength);
|
|
hr = ValidateSafePointer( ( BYTE* ) pObject );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CAdapSafeBuffer::ValidateSafePointer( BYTE* pPtr )
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Verifys that the pointer is within the blob. The blob occupies the memory starting at
|
|
// the beginning of the safe buffer, and termintes at an offset equal to m_dwDataBlobSize
|
|
//
|
|
// Parameters:
|
|
// pPtr - a pointer to be verified
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
{
|
|
HRESULT hr = WBEM_NO_ERROR;
|
|
|
|
// NOTE: The upper limit of the safe buffer is 1 byte less the blob pointer plus the blob size since
|
|
// the first byte of the blob is also the first byte. Imagine he case with a blob of size 1.
|
|
// =================================================================================================
|
|
|
|
if ( ( pPtr < m_pSafeBuffer ) || ( pPtr > ( m_pSafeBuffer + m_dwDataBlobSize - 1 ) ) )
|
|
{
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
|
|
if ( FAILED ( hr ) )
|
|
{
|
|
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
|
|
WBEM_MC_ADAP_BAD_PERFLIB_INVALID_DATA,
|
|
(LPCWSTR)m_wstrServiceName, CHex( hr ) );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CAdapSafeBuffer::CopyData( BYTE** ppData, DWORD* pdwNumBytes, DWORD* pdwNumObjects )
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copies the blob data from the private heap into the process heap. The method will
|
|
// allocate memory in the process heap.
|
|
//
|
|
// Parameters:
|
|
// ppData - a pointer to an unallocated byte array
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
{
|
|
if (NULL == ppData || NULL == pdwNumBytes || NULL == pdwNumObjects) return WBEM_E_INVALID_PARAMETER;
|
|
HRESULT hr = WBEM_NO_ERROR;
|
|
|
|
*ppData = new BYTE[m_dwDataBlobSize];
|
|
|
|
if ( NULL == *ppData )
|
|
{
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
else
|
|
{
|
|
memcpy( *ppData, m_pSafeBuffer, m_dwDataBlobSize );
|
|
}
|
|
|
|
*pdwNumBytes = m_dwDataBlobSize;
|
|
*pdwNumObjects = m_dwNumObjects;
|
|
|
|
return hr;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CAdapPerfLib
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
CAdapPerfLib::CAdapPerfLib( LPCWSTR pwcsServiceName, DWORD * pLoadStatus )
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Constructor
|
|
//
|
|
// Initializes all member variables, sets the library and function names, opens the library,
|
|
// sets the entry point addresses, creates the perflib processing mutex, and opens the
|
|
// processing thread.
|
|
//
|
|
// Parameters:
|
|
// pwcsServiceName - A Unicode string specifying the name of the perflib service.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
: m_wstrServiceName( pwcsServiceName ),
|
|
m_pfnOpenProc( NULL ),
|
|
m_pfnCollectProc( NULL ),
|
|
m_pfnCloseProc( NULL ),
|
|
m_pwcsLibrary( NULL ),
|
|
m_pwcsOpenProc( NULL ),
|
|
m_pwcsCollectProc( NULL ),
|
|
m_pwcsCloseProc( NULL ),
|
|
m_hLib( NULL ),
|
|
m_fOpen( FALSE ),
|
|
m_dwStatus( 0 ),
|
|
m_pPerfThread( NULL ),
|
|
m_hPLMutex( NULL ),
|
|
m_fOK( FALSE ),
|
|
m_EventLogCalled( FALSE ),
|
|
m_CollectOK( TRUE ),
|
|
m_dwFirstCtr(2),
|
|
m_dwLastCtr(CPerfNameDb::GetSystemReservedHigh())
|
|
{
|
|
DEBUGTRACE( ( LOG_WMIADAP, "Constructing the %S performance library wrapper.\n", pwcsServiceName ) );
|
|
|
|
HRESULT hr = WBEM_NO_ERROR;
|
|
|
|
// Verify that the perflib is loaded
|
|
// Initialize the performance library name and entry point names
|
|
// =============================================================
|
|
|
|
hr = VerifyLoaded();
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
ERRORTRACE( ( LOG_WMIADAP, "VerifyLoaded for %S hr = %08x.\n", pwcsServiceName, hr ) );
|
|
}
|
|
|
|
|
|
// Set the processing status information for this attempt
|
|
// ======================================================
|
|
|
|
if ( SUCCEEDED ( hr ) )
|
|
{
|
|
if (pLoadStatus)
|
|
{
|
|
(*pLoadStatus) |= EX_STATUS_LOADABLE;
|
|
}
|
|
|
|
hr = BeginProcessingStatus();
|
|
|
|
if ( hr == WBEM_S_ALREADY_EXISTS )
|
|
{
|
|
SetStatus( ADAP_PERFLIB_PREVIOUSLY_PROCESSED );
|
|
}
|
|
}
|
|
|
|
m_fOK = SUCCEEDED( hr );
|
|
|
|
if ( !m_fOK )
|
|
{
|
|
ERRORTRACE( ( LOG_WMIADAP, "Construction of the %S perflib wrapper failed hr = %08x.\n", pwcsServiceName, hr ) );
|
|
}
|
|
}
|
|
|
|
CAdapPerfLib::~CAdapPerfLib( void )
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Destructor
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
{
|
|
DEBUGTRACE( ( LOG_WMIADAP, "Destructing the %S performance library wrapper.\n", (LPWSTR)m_wstrServiceName) );
|
|
|
|
|
|
delete m_pPerfThread;
|
|
|
|
|
|
// Delete the library and entry point names
|
|
// ========================================
|
|
delete [] m_pwcsLibrary;
|
|
delete [] m_pwcsOpenProc;
|
|
delete [] m_pwcsCollectProc;
|
|
delete [] m_pwcsCloseProc;
|
|
|
|
// Free the library
|
|
// ================
|
|
|
|
if ( NULL != m_hLib )
|
|
{
|
|
try
|
|
{
|
|
FreeLibrary( m_hLib );
|
|
}
|
|
catch (...)
|
|
{
|
|
ERRORTRACE(( LOG_WMIADAP,"FreeLibrary for Service %S threw an exception",(LPWSTR)m_wstrServiceName) );
|
|
}
|
|
DEBUGTRACE( ( LOG_WMIADAP, "Library for Service %S Freed.\n",(LPWSTR)m_wstrServiceName ) );
|
|
}
|
|
}
|
|
|
|
HRESULT CAdapPerfLib::VerifyLoaded()
|
|
{
|
|
HRESULT hr = WBEM_E_FAILED;
|
|
|
|
WString wszRegPath = L"SYSTEM\\CurrentControlSet\\Services\\";
|
|
wszRegPath += m_wstrServiceName;
|
|
wszRegPath += L"\\Performance";
|
|
|
|
CNTRegistry reg;
|
|
int nRet = 0;
|
|
|
|
nRet = reg.Open( HKEY_LOCAL_MACHINE, wszRegPath );
|
|
|
|
switch( nRet )
|
|
{
|
|
case CNTRegistry::no_error:
|
|
{
|
|
DWORD dwFirstCtr = 0;
|
|
DWORD dwLastCtr = 0;
|
|
WCHAR* wszObjList = NULL;
|
|
|
|
if ( ( ( reg.GetDWORD( L"First Counter", &dwFirstCtr ) == CNTRegistry::no_error ) &&
|
|
( reg.GetDWORD( L"Last Counter", &dwLastCtr ) == CNTRegistry::no_error ) ) ||
|
|
( reg.GetStr( L"Object List", &wszObjList ) == CNTRegistry::no_error ))
|
|
{
|
|
|
|
hr = InitializeEntryPoints(reg,wszRegPath);
|
|
|
|
if (wszObjList)
|
|
{
|
|
delete [] wszObjList;
|
|
}
|
|
if (dwFirstCtr && dwLastCtr)
|
|
{
|
|
m_dwFirstCtr = dwFirstCtr;
|
|
m_dwLastCtr = dwLastCtr;
|
|
}
|
|
}
|
|
else // more special cases
|
|
{
|
|
if ( m_wstrServiceName.EqualNoCase( L"TCPIP" ) ||
|
|
m_wstrServiceName.EqualNoCase( L"TAPISRV") ||
|
|
m_wstrServiceName.EqualNoCase( L"PERFOS" ) ||
|
|
m_wstrServiceName.EqualNoCase( L"PERFPROC" ) ||
|
|
m_wstrServiceName.EqualNoCase( L"PERFDISK" ) ||
|
|
m_wstrServiceName.EqualNoCase( L"PERFNET" ) ||
|
|
m_wstrServiceName.EqualNoCase( L"SPOOLER" ) ||
|
|
m_wstrServiceName.EqualNoCase( L"MSFTPSvc" ) ||
|
|
m_wstrServiceName.EqualNoCase( L"RemoteAccess" ) ||
|
|
m_wstrServiceName.EqualNoCase( L"WINS" ) ||
|
|
m_wstrServiceName.EqualNoCase( L"MacSrv" ) ||
|
|
m_wstrServiceName.EqualNoCase( L"AppleTalk" ) ||
|
|
m_wstrServiceName.EqualNoCase( L"NM" ) ||
|
|
m_wstrServiceName.EqualNoCase( L"RSVP" ) )
|
|
{
|
|
hr = InitializeEntryPoints(reg,wszRegPath);
|
|
}
|
|
else
|
|
{
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
}
|
|
}break;
|
|
case CNTRegistry::not_found:
|
|
{
|
|
// This shouldn't happen since this is how a perflib is defined
|
|
hr = WBEM_E_FAILED;
|
|
}break;
|
|
case CNTRegistry::access_denied:
|
|
{
|
|
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
|
|
WBEM_MC_ADAP_PERFLIB_REG_VALUE_FAILURE,
|
|
(LPWSTR)wszRegPath, nRet );
|
|
}break;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CAdapPerfLib::InitializeEntryPoints(CNTRegistry & reg,WString & wszRegPath){
|
|
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
// see if someone disabled this library
|
|
DWORD dwDisable = 0;
|
|
if ( CNTRegistry::no_error == reg.GetDWORD( L"Disable Performance Counters", &dwDisable ) &&
|
|
(dwDisable != 0) )
|
|
{
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
else
|
|
{
|
|
hr = WBEM_S_NO_ERROR;
|
|
}
|
|
// the perflib is OK for the world, see if it os OK for US
|
|
|
|
if (SUCCEEDED(hr)){
|
|
|
|
if (!(( reg.GetStr( L"Library", &m_pwcsLibrary ) == CNTRegistry::no_error ) &&
|
|
( reg.GetStr( L"Open", &m_pwcsOpenProc ) == CNTRegistry::no_error)&&
|
|
( reg.GetStr( L"Collect", &m_pwcsCollectProc ) == CNTRegistry::no_error) &&
|
|
( reg.GetStr( L"Close", &m_pwcsCloseProc ) == CNTRegistry::no_error ) ))
|
|
{
|
|
|
|
WString wstrPath(wszRegPath);
|
|
|
|
if (m_pwcsLibrary == NULL){
|
|
wstrPath += L"\\Library";
|
|
} else if (m_pwcsCollectProc == NULL) {
|
|
wstrPath += L"\\Collect";
|
|
}
|
|
|
|
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
|
|
WBEM_MC_ADAP_PERFLIB_REG_VALUE_FAILURE,
|
|
(LPWSTR)wstrPath, CHex( WBEM_E_NOT_AVAILABLE ) );
|
|
|
|
hr = WBEM_E_FAILED;
|
|
|
|
} else {
|
|
|
|
hr = WBEM_S_NO_ERROR;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
HRESULT CAdapPerfLib::Initialize()
|
|
{
|
|
// Load the perflib and initialize the procedure addresses
|
|
// =======================================================
|
|
HRESULT hr = Load();
|
|
|
|
// Initialize the named function mutex (see WbemPerf for syntax of Mutex name)
|
|
// ===========================================================================
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
size_t cchSizeTmp = m_wstrServiceName.Length() + 256;
|
|
WCHAR* wcsMutexName = new WCHAR[cchSizeTmp];
|
|
if (NULL == wcsMutexName) return WBEM_E_OUT_OF_MEMORY;
|
|
CDeleteMe<WCHAR> dmMutexName( wcsMutexName );
|
|
|
|
StringCchPrintfW( wcsMutexName, cchSizeTmp, L"Global\\%s_Perf_Library_Lock_PID_%x", (WCHAR *)m_wstrServiceName, GetCurrentProcessId() );
|
|
m_hPLMutex = CreateMutexW( 0, FALSE, wcsMutexName);
|
|
|
|
if ( NULL == m_hPLMutex )
|
|
{
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
}
|
|
|
|
// Create the worker thread
|
|
// ========================
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
m_pPerfThread = new CPerfThread( this );
|
|
|
|
if ( ( NULL == m_pPerfThread) || ( !m_pPerfThread->IsOk() ) )
|
|
{
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
else
|
|
{
|
|
hr = m_pPerfThread->Open( this );
|
|
}
|
|
}
|
|
|
|
if ( FAILED( hr ) )
|
|
{
|
|
SetStatus( ADAP_PERFLIB_IS_INACTIVE );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CAdapPerfLib::GetFileSignature( CheckLibStruct * pCheckLib )
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
if (!pCheckLib){
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
// Get the current library's file time
|
|
// ===================================
|
|
|
|
HANDLE hFile = NULL;
|
|
|
|
DWORD dwRet = 0;
|
|
WCHAR wszFullPath[MAX_PATH];
|
|
WCHAR* pwcsTemp = NULL;
|
|
|
|
if ( 0 != SearchPathW( NULL, m_pwcsLibrary, NULL, MAX_PATH, wszFullPath, &pwcsTemp ) )
|
|
{
|
|
// Use GetFileAttributes to validate the path.
|
|
DWORD dwAttributes = GetFileAttributesW(wszFullPath);
|
|
if (dwAttributes == 0xFFFFFFFF) return WBEM_E_FAILED;
|
|
|
|
// create mask of the attributes that would make an existing file invalid for use
|
|
DWORD dwMask = FILE_ATTRIBUTE_DEVICE |
|
|
FILE_ATTRIBUTE_DIRECTORY |
|
|
FILE_ATTRIBUTE_OFFLINE |
|
|
FILE_ATTRIBUTE_READONLY |
|
|
FILE_ATTRIBUTE_REPARSE_POINT |
|
|
FILE_ATTRIBUTE_SPARSE_FILE |
|
|
FILE_ATTRIBUTE_SYSTEM |
|
|
FILE_ATTRIBUTE_TEMPORARY;
|
|
|
|
if (dwAttributes & dwMask) return WBEM_E_FAILED;
|
|
|
|
hFile = CreateFileW( wszFullPath,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ,
|
|
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
|
|
|
|
if ( INVALID_HANDLE_VALUE != hFile )
|
|
{
|
|
OnDelete<HANDLE,BOOL(*)(HANDLE),CloseHandle> CloseMe(hFile);
|
|
|
|
DWORD dwFileSizeLow = 0;
|
|
DWORD dwFileSizeHigh = 0;
|
|
__int32 nFileSize = 0;
|
|
DWORD dwNumRead = 0;
|
|
BYTE* aBuffer = NULL;
|
|
|
|
dwFileSizeLow = GetFileSize( hFile, &dwFileSizeHigh );
|
|
nFileSize = ( dwFileSizeHigh << 32 ) + dwFileSizeLow;
|
|
|
|
FILETIME ft;
|
|
if (GetFileTime(hFile,&ft,NULL,NULL))
|
|
{
|
|
aBuffer = new BYTE[nFileSize];
|
|
CDeleteMe<BYTE> dmBuffer( aBuffer );
|
|
|
|
if ( NULL != aBuffer )
|
|
{
|
|
if ( ReadFile( hFile, aBuffer, nFileSize, &dwNumRead, FALSE ) )
|
|
{
|
|
MD5 md5;
|
|
BYTE aSignature[16];
|
|
md5.Transform( aBuffer, dwNumRead, aSignature );
|
|
|
|
// return our data
|
|
memcpy(pCheckLib->Signature,aSignature,sizeof(aSignature));
|
|
pCheckLib->FileTime = ft;
|
|
pCheckLib->FileSize = nFileSize;
|
|
}
|
|
else
|
|
{
|
|
hr = WBEM_E_TOO_MUCH_DATA;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
ERRORTRACE((LOG_WMIADAP,"GetFileSignature for %S err %d\n",wszFullPath,GetLastError()));
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = WBEM_E_NOT_FOUND;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CAdapPerfLib::SetFileSignature()
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
CNTRegistry reg;
|
|
int nRet = 0;
|
|
CheckLibStruct CheckLib;
|
|
|
|
// Clear the signature buffer
|
|
// ==========================
|
|
|
|
memset( &CheckLib, 0, sizeof(CheckLib) );
|
|
|
|
// Get the current file time stamp
|
|
// ===============================
|
|
|
|
hr = GetFileSignature( &CheckLib );
|
|
|
|
// And write it into the registry key
|
|
// ==================================
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
|
|
WString wstr;
|
|
|
|
try
|
|
{
|
|
wstr = L"SYSTEM\\CurrentControlSet\\Services\\";
|
|
wstr += m_wstrServiceName;
|
|
wstr += L"\\Performance";
|
|
}
|
|
catch(...)
|
|
{
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
nRet = reg.Open( HKEY_LOCAL_MACHINE , wstr );
|
|
|
|
switch ( nRet )
|
|
{
|
|
case CNTRegistry::no_error:
|
|
{
|
|
}break;
|
|
case CNTRegistry::access_denied:
|
|
{
|
|
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
|
|
WBEM_MC_ADAP_PERFLIB_REG_VALUE_FAILURE,
|
|
(LPCWSTR)wstr, nRet );
|
|
}
|
|
default:
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
}
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
int nRet1 = reg.SetBinary( ADAP_PERFLIB_SIGNATURE, (PBYTE)&CheckLib.Signature, sizeof( BYTE[16] ) );
|
|
int nRet2 = reg.SetBinary( ADAP_PERFLIB_TIME, (PBYTE)&CheckLib.FileTime, sizeof( FILETIME ) );
|
|
int nRet3 = reg.SetDWORD( ADAP_PERFLIB_SIZE, CheckLib.FileSize );
|
|
|
|
if ( (CNTRegistry::no_error == nRet1) &&
|
|
(CNTRegistry::no_error == nRet2) &&
|
|
(CNTRegistry::no_error == nRet3))
|
|
{
|
|
// everything OK
|
|
}
|
|
else if ((CNTRegistry::access_denied == nRet1) ||
|
|
(CNTRegistry::access_denied == nRet2) ||
|
|
(CNTRegistry::access_denied == nRet3))
|
|
{
|
|
WString wstrPath = wstr;
|
|
wstrPath += ADAP_PERFLIB_SIGNATURE;
|
|
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
|
|
WBEM_MC_ADAP_PERFLIB_REG_VALUE_FAILURE,
|
|
(LPCWSTR)wstrPath, CNTRegistry::access_denied );
|
|
}
|
|
else
|
|
{
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CAdapPerfLib::CheckFileSignature()
|
|
{
|
|
HRESULT hr = WBEM_S_SAME;
|
|
|
|
CNTRegistry reg;
|
|
int nRet = 0;
|
|
BYTE cCurrentMD5[16];
|
|
BYTE* cStoredMD5 = NULL;
|
|
|
|
// Set the performance key path
|
|
// ============================
|
|
|
|
WString wstr;
|
|
|
|
try
|
|
{
|
|
wstr = L"SYSTEM\\CurrentControlSet\\Services\\";
|
|
wstr += m_wstrServiceName;
|
|
wstr += L"\\Performance";
|
|
}
|
|
catch(...)
|
|
{
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
// Open the performance key
|
|
// ========================
|
|
|
|
nRet = reg.Open( HKEY_LOCAL_MACHINE , wstr );
|
|
|
|
switch ( nRet )
|
|
{
|
|
case CNTRegistry::no_error:
|
|
{
|
|
}break;
|
|
case CNTRegistry::access_denied:
|
|
{
|
|
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
|
|
WBEM_MC_ADAP_PERFLIB_REG_VALUE_FAILURE,
|
|
(LPCWSTR)wstr, nRet );
|
|
hr = WBEM_E_FAILED;
|
|
}break;
|
|
default:
|
|
{
|
|
hr = WBEM_E_FAILED;
|
|
}break;
|
|
}
|
|
}
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
// Get the stored file signature
|
|
// =============================
|
|
CheckLibStruct StoredLibStruct;
|
|
int nRet1;
|
|
int nRet2;
|
|
int nRet3;
|
|
|
|
DWORD dwSizeBlob;
|
|
nRet1 = reg.GetBinary( ADAP_PERFLIB_SIGNATURE, (PBYTE*)&cStoredMD5,&dwSizeBlob);
|
|
CDeleteMe<BYTE> dmStoredMD5( cStoredMD5 );
|
|
if (cStoredMD5)
|
|
{
|
|
if ( sizeof(cCurrentMD5) == dwSizeBlob)
|
|
{
|
|
memcpy(&StoredLibStruct.Signature,cStoredMD5,sizeof(StoredLibStruct.Signature));
|
|
}
|
|
else
|
|
{
|
|
nRet1 = CNTRegistry::failed;
|
|
}
|
|
}
|
|
|
|
BYTE * pFileTime = NULL;
|
|
nRet2 = reg.GetBinary( ADAP_PERFLIB_TIME, (PBYTE*)&pFileTime,&dwSizeBlob);
|
|
CDeleteMe<BYTE> dmFileTime( pFileTime );
|
|
if (pFileTime)
|
|
{
|
|
if (sizeof(FILETIME) == dwSizeBlob )
|
|
{
|
|
memcpy(&StoredLibStruct.FileTime,pFileTime,sizeof(FILETIME));
|
|
}
|
|
else
|
|
{
|
|
nRet2 = CNTRegistry::failed;
|
|
}
|
|
}
|
|
|
|
nRet3 = reg.GetDWORD(ADAP_PERFLIB_SIZE,&StoredLibStruct.FileSize);
|
|
|
|
if ((CNTRegistry::access_denied == nRet1) ||
|
|
(CNTRegistry::access_denied == nRet2) ||
|
|
(CNTRegistry::access_denied == nRet3))
|
|
{
|
|
WString wstrPath = wstr;
|
|
wstrPath += ADAP_PERFLIB_SIGNATURE;
|
|
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
|
|
WBEM_MC_ADAP_PERFLIB_REG_VALUE_FAILURE,
|
|
(LPCWSTR)wstrPath, nRet );
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
else if ((CNTRegistry::not_found == nRet1) ||
|
|
(CNTRegistry::not_found == nRet2) ||
|
|
(CNTRegistry::not_found == nRet3))
|
|
{
|
|
hr = WBEM_S_FALSE;
|
|
}
|
|
else if((CNTRegistry::out_of_memory == nRet1) ||
|
|
(CNTRegistry::out_of_memory == nRet2) ||
|
|
(CNTRegistry::out_of_memory == nRet3) ||
|
|
(CNTRegistry::failed == nRet1) ||
|
|
(CNTRegistry::failed == nRet2) ||
|
|
(CNTRegistry::failed == nRet3))
|
|
{
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
|
|
if ( SUCCEEDED( hr ) && ( WBEM_S_FALSE != hr ) )
|
|
{
|
|
// Get the current library's signature
|
|
// ===================================
|
|
CheckLibStruct CurrentLibStruct;
|
|
memset(&CurrentLibStruct,0,sizeof(CheckLibStruct));
|
|
|
|
hr = GetFileSignature( &CurrentLibStruct );
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
if ( (StoredLibStruct.FileSize == CurrentLibStruct.FileSize) &&
|
|
(0 == memcmp( &StoredLibStruct.Signature, &CurrentLibStruct.Signature, sizeof(CurrentLibStruct.Signature) )) &&
|
|
(0 == memcmp( &StoredLibStruct.FileTime, &CurrentLibStruct.FileTime, sizeof(FILETIME))) )
|
|
{
|
|
hr = WBEM_S_ALREADY_EXISTS;
|
|
}
|
|
else
|
|
{
|
|
hr = WBEM_S_FALSE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CAdapPerfLib::BeginProcessingStatus()
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Opens the registry key, reads the ADAP_PERFLIB_STATUS_KEY, and processes the value as
|
|
// follows:
|
|
//
|
|
// ADAP_PERFLIB_OK: The perflib has been successfully accessed before. Set
|
|
// the status flag to ADAP_PERFLIB_PROCESSING
|
|
//
|
|
// ADAP_PERFLIB_PROCESSING: The perflib caused the process to fail. It is corrupt,
|
|
// set the status flag to ADAP_PERFLIB_CORRUPT.
|
|
//
|
|
// ADAP_PERFLIB_CORRUPT: The perflib is known to be corrupt. Status flag retains
|
|
// its value.
|
|
//
|
|
// No Value: The perflib has not been accessed before. Set the
|
|
// status flag to ADAP_PERFLIB_PROCESSING.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
{
|
|
DEBUGTRACE( ( LOG_WMIADAP, "CAdapPerfLib::BeginProcessingStatus()...\n") );
|
|
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
CNTRegistry reg;
|
|
|
|
// Set the registry path
|
|
// =====================
|
|
|
|
WString wstr;
|
|
|
|
try
|
|
{
|
|
wstr = L"SYSTEM\\CurrentControlSet\\Services\\";
|
|
wstr += m_wstrServiceName;
|
|
wstr += L"\\Performance";
|
|
}
|
|
catch(...)
|
|
{
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
// Open the services key
|
|
// =====================
|
|
|
|
int nRet = reg.Open( HKEY_LOCAL_MACHINE, wstr );
|
|
|
|
switch ( nRet )
|
|
{
|
|
case CNTRegistry::access_denied:
|
|
{
|
|
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
|
|
WBEM_MC_ADAP_PERFLIB_REG_VALUE_FAILURE,
|
|
(LPCWSTR)wstr, nRet );
|
|
} break;
|
|
case CNTRegistry::no_error:
|
|
{
|
|
DWORD dwVal;
|
|
|
|
// Check perflib status
|
|
// ====================
|
|
|
|
hr = CheckFileSignature();
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
if ( WBEM_S_FALSE == hr )
|
|
{
|
|
// We've got a new perflib, reset the status
|
|
// =========================================
|
|
|
|
hr = SetFileSignature();
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = reg.SetDWORD( ADAP_PERFLIB_STATUS_KEY, ADAP_PERFLIB_PROCESSING );
|
|
}
|
|
|
|
}
|
|
else // WBEM_S_ALREADY_EXISTS
|
|
{
|
|
// It's the same perflib, check the status
|
|
// =======================================
|
|
|
|
nRet = reg.GetDWORD( ADAP_PERFLIB_STATUS_KEY, &dwVal );
|
|
|
|
if ( nRet == CNTRegistry::no_error )
|
|
{
|
|
switch ( dwVal )
|
|
{
|
|
case ADAP_PERFLIB_OK: // 0
|
|
case ADAP_PERFLIB_PROCESSING: // 1
|
|
case ADAP_PERFLIB_BOOBOO: // 2
|
|
{
|
|
// So far, perflib has behaved within reason. Set it to processing state
|
|
// =====================================================================
|
|
|
|
reg.SetDWORD( ADAP_PERFLIB_STATUS_KEY, dwVal + 1 );
|
|
|
|
//ERRORTRACE( ( LOG_WMIADAP, "Performance library %S status %d\n",(LPWSTR)m_wstrServiceName,dwVal + 1));
|
|
|
|
|
|
}break;
|
|
case ADAP_PERFLIB_LASTCHANCE: // 3
|
|
{
|
|
// Perflib failed in the last access attempt before processing ended. Set as bad perflib
|
|
// =====================================================================================
|
|
|
|
reg.SetDWORD( ADAP_PERFLIB_STATUS_KEY, ADAP_PERFLIB_CORRUPT );
|
|
|
|
ERRORTRACE( ( LOG_WMIADAP, "Performance library %S status was left in the \"Processing\" state.\n",(LPWSTR)m_pwcsLibrary) );
|
|
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
|
|
WBEM_MC_ADAP_BAD_PERFLIB_BAD_LIBRARY,
|
|
m_pwcsLibrary, CHex( (DWORD)-1 ) );
|
|
hr = WBEM_E_FAILED;
|
|
}break;
|
|
case ADAP_PERFLIB_CORRUPT: // -1
|
|
{
|
|
// Sign of a bad perflib. Do not open
|
|
// ==================================
|
|
|
|
ERRORTRACE( ( LOG_WMIADAP, "Performance library for %S has previously been disabled.\n",(LPWSTR)m_wstrServiceName) );
|
|
|
|
//CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE, WBEM_MC_ADAP_BAD_PERFLIB_BAD_LIBRARY, m_pwcsLibrary, CHex( ADAP_PERFLIB_CORRUPT ) );
|
|
|
|
hr = WBEM_E_FAILED;
|
|
|
|
}break;
|
|
}
|
|
}
|
|
else if ( nRet == CNTRegistry::not_found )
|
|
{
|
|
// The status does not exist
|
|
// =========================
|
|
|
|
hr = reg.SetDWORD( ADAP_PERFLIB_STATUS_KEY, ADAP_PERFLIB_PROCESSING );
|
|
}
|
|
}
|
|
} else {
|
|
|
|
DEBUGTRACE( ( LOG_WMIADAP, "CheckFileSignature for %S %08x\n",(LPWSTR)m_wstrServiceName,hr ) );
|
|
|
|
}
|
|
}break;
|
|
default:
|
|
{
|
|
hr = WBEM_E_FAILED;
|
|
}break;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CAdapPerfLib::EndProcessingStatus()
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Opens the service registry key, reads the ADAP_PERFLIB_STATUS_KEY, and processes the
|
|
// value as follows:
|
|
//
|
|
// ADAP_PERFLIB_PROCESSING: Valid state. Set status flag to ADAP_PERFLIB_OK.
|
|
//
|
|
// ADAP_PERFLIB_CORRUPT: Valid state (may have been set during processing).
|
|
// Leave status flag as is.
|
|
//
|
|
// ADAP_PERFLIB_OK: Invalid state. Return an error and log an event.
|
|
//
|
|
// No Value: Invalid state. Return an error and log an event.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
{
|
|
DEBUGTRACE( ( LOG_WMIADAP, "CAdapPerfLib::EndProcessingStatus()...\n") );
|
|
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
CNTRegistry reg;
|
|
|
|
WString wstr;
|
|
|
|
try
|
|
{
|
|
wstr = L"SYSTEM\\CurrentControlSet\\Services\\";
|
|
wstr += m_wstrServiceName;
|
|
wstr += L"\\Performance";
|
|
}
|
|
catch(...)
|
|
{
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
|
|
if (SUCCEEDED(hr)){
|
|
// Open the services key
|
|
// =====================
|
|
|
|
int nRet = reg.Open( HKEY_LOCAL_MACHINE, wstr );
|
|
|
|
if ( CNTRegistry::access_denied == nRet )
|
|
{
|
|
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
|
|
WBEM_MC_ADAP_PERFLIB_REG_VALUE_FAILURE,
|
|
(LPCWSTR)wstr, nRet );
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
else if ( CNTRegistry::no_error == nRet )
|
|
{
|
|
DWORD dwVal = 0;
|
|
|
|
// Check perflib status
|
|
// ====================
|
|
|
|
if ( CheckStatus( ADAP_PERFLIB_FAILED ) )
|
|
{
|
|
// If we have a failure, then immediately mark the perflib as corrupt
|
|
// ==================================================================
|
|
|
|
hr = reg.SetDWORD( ADAP_PERFLIB_STATUS_KEY, ADAP_PERFLIB_CORRUPT );
|
|
|
|
if (!m_EventLogCalled){
|
|
m_EventLogCalled = TRUE;
|
|
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE, WBEM_MC_ADAP_BAD_PERFLIB_EXCEPTION, (LPCWSTR)m_wstrServiceName, CHex( hr ) );
|
|
|
|
}
|
|
|
|
}
|
|
else if ( reg.GetDWORD( ADAP_PERFLIB_STATUS_KEY, &dwVal) == CNTRegistry::no_error )
|
|
{
|
|
switch ( dwVal )
|
|
{
|
|
case ADAP_PERFLIB_PROCESSING:
|
|
case ADAP_PERFLIB_BOOBOO:
|
|
case ADAP_PERFLIB_LASTCHANCE:
|
|
{
|
|
// Perflib is in expected state, reset as long as nothing bad has happened
|
|
// =======================================================================
|
|
|
|
hr = reg.SetDWORD( ADAP_PERFLIB_STATUS_KEY, ADAP_PERFLIB_OK );
|
|
|
|
//ERRORTRACE( ( LOG_WMIADAP, "Performance library %S EndProcessing\n",(LPWSTR)m_wstrServiceName) );
|
|
|
|
|
|
}break;
|
|
|
|
case ADAP_PERFLIB_CORRUPT:
|
|
{
|
|
// Valid state. Leave as is.
|
|
// ==========================
|
|
|
|
ERRORTRACE( ( LOG_WMIADAP, "Performance library for %S: status is corrupt.\n",(LPWSTR)m_wstrServiceName) );
|
|
hr = WBEM_E_FAILED;
|
|
|
|
}break;
|
|
|
|
case ADAP_PERFLIB_OK:
|
|
{
|
|
if (CheckStatus(ADAP_PERFLIB_IS_INACTIVE))
|
|
{
|
|
hr = reg.SetDWORD( ADAP_PERFLIB_STATUS_KEY, ADAP_PERFLIB_OK );
|
|
}
|
|
else
|
|
{
|
|
// Invalid state
|
|
ERRORTRACE( ( LOG_WMIADAP, "Performance library %S: status is still ADAP_PERFLIB_OK.\n",(LPWSTR)m_wstrServiceName) );
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
|
|
}break;
|
|
|
|
default:
|
|
{
|
|
// Really bad state
|
|
// ================
|
|
|
|
ERRORTRACE( ( LOG_WMIADAP, "Performance library %S: status is in an unknown state.\n",(LPWSTR)m_wstrServiceName) );
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// There is no status key. Something wacky has happened
|
|
// ====================================================
|
|
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CAdapPerfLib::Load()
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Loads the library and resolves the addresses for the Open, Collect and Close entry
|
|
// points.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
{
|
|
// Redundant, but it's a failsafe in case some perflib shuts this off on us
|
|
// during processing
|
|
// ========================================================================
|
|
|
|
SetErrorMode( SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX );
|
|
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
// Free the library if it has been previously loaded
|
|
// =================================================
|
|
|
|
if ( NULL != m_hLib )
|
|
{
|
|
try
|
|
{
|
|
FreeLibrary( m_hLib );
|
|
}
|
|
catch (...)
|
|
{
|
|
hr = WBEM_E_CRITICAL_ERROR;
|
|
}
|
|
}
|
|
|
|
// Load the predefined library
|
|
// ===========================
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
try
|
|
{
|
|
m_hLib = LoadLibraryExW( m_pwcsLibrary, NULL, LOAD_WITH_ALTERED_SEARCH_PATH );
|
|
}
|
|
catch(...)
|
|
{
|
|
hr = WBEM_E_CRITICAL_ERROR;
|
|
}
|
|
}
|
|
|
|
if ( SUCCEEDED( hr ) && ( NULL != m_hLib ) )
|
|
{
|
|
|
|
DEBUGTRACE( ( LOG_WMIADAP, "** %S Library Loaded.\n", m_wstrServiceName ) );
|
|
|
|
char szName[256];
|
|
DWORD Last1 = 0;
|
|
DWORD Last2 = 0;
|
|
DWORD Last3 = 0;
|
|
|
|
|
|
// Get the entry point addresses. No Wide version of GetProcAddress? sigh...
|
|
// ==========================================================================
|
|
|
|
if ( NULL != m_pwcsOpenProc )
|
|
{
|
|
if (0 != WideCharToMultiByte( CP_ACP, 0L, m_pwcsOpenProc, lstrlenW( m_pwcsOpenProc ) + 1,
|
|
szName, sizeof(szName), NULL, NULL ))
|
|
{
|
|
m_pfnOpenProc = (PM_OPEN_PROC*) GetProcAddress( m_hLib, szName );
|
|
}
|
|
Last1 = GetLastError();
|
|
}
|
|
|
|
if (0 != WideCharToMultiByte( CP_ACP, 0L, m_pwcsCollectProc, lstrlenW( m_pwcsCollectProc ) + 1,
|
|
szName, sizeof(szName), NULL, NULL ))
|
|
{
|
|
m_pfnCollectProc = (PM_COLLECT_PROC*) GetProcAddress( m_hLib, szName );
|
|
}
|
|
Last2 = GetLastError();
|
|
|
|
if ( NULL != m_pwcsCloseProc )
|
|
{
|
|
if (0 != WideCharToMultiByte( CP_ACP, 0L, m_pwcsCloseProc, lstrlenW( m_pwcsCloseProc ) + 1,
|
|
szName, sizeof(szName), NULL, NULL ))
|
|
{
|
|
m_pfnCloseProc = (PM_CLOSE_PROC*) GetProcAddress( m_hLib, szName );
|
|
}
|
|
Last3 = GetLastError();
|
|
}
|
|
|
|
if ( ( ( ( NULL != m_pwcsOpenProc ) && ( NULL != m_pfnOpenProc) ) || ( NULL == m_pwcsOpenProc ) ) &&
|
|
( NULL != m_pfnCollectProc ) &&
|
|
( ( ( NULL != m_pwcsCloseProc ) && ( NULL != m_pfnCloseProc ) ) || ( NULL == m_pwcsCloseProc ) ) )
|
|
{
|
|
hr = WBEM_S_NO_ERROR;
|
|
}
|
|
else
|
|
{
|
|
ERRORTRACE( ( LOG_WMIADAP, "A performance library function in %S failed to load.\n",(LPWSTR)m_wstrServiceName) );
|
|
|
|
WString wstr;
|
|
wstr += L"HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Services\\";
|
|
wstr += m_wstrServiceName;
|
|
|
|
if ( ( NULL != m_pwcsOpenProc ) && ( NULL == m_pfnOpenProc ) )
|
|
{
|
|
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
|
|
WBEM_MC_ADAP_PERFLIB_REG_VALUE_FAILURE,
|
|
(LPCWSTR)wstr, Last1 );
|
|
|
|
}
|
|
else if ( NULL == m_pfnCollectProc )
|
|
{
|
|
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
|
|
WBEM_MC_ADAP_PERFLIB_REG_VALUE_FAILURE,
|
|
(LPCWSTR)wstr, Last2 );
|
|
|
|
}
|
|
else if (( NULL != m_pwcsCloseProc ) && ( NULL == m_pfnCloseProc ))
|
|
{
|
|
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
|
|
WBEM_MC_ADAP_PERFLIB_REG_VALUE_FAILURE,
|
|
(LPCWSTR)wstr, Last3 );
|
|
|
|
}
|
|
|
|
SetStatus( ADAP_PERFLIB_FAILED );
|
|
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// If the library fails to load, then send an event, but do not charge a strike
|
|
// ============================================================================
|
|
|
|
ERRORTRACE( ( LOG_WMIADAP, "The performance library for %S failed to load.\n",(LPWSTR)m_wstrServiceName ) );
|
|
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE, WBEM_MC_ADAP_BAD_PERFLIB_BAD_LIBRARY, m_pwcsLibrary, CHex( hr ) );
|
|
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CAdapPerfLib::GetBlob( PERF_OBJECT_TYPE** ppPerfBlock, DWORD* pdwNumBytes, DWORD* pdwNumObjects, BOOL fCostly )
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
if ( m_fOpen )
|
|
{
|
|
hr = m_pPerfThread->GetPerfBlock( this, ppPerfBlock, pdwNumBytes, pdwNumObjects, fCostly );
|
|
}
|
|
|
|
if ( FAILED( hr ) )
|
|
{
|
|
if (!m_EventLogCalled){
|
|
//
|
|
//
|
|
//WBEM_MC_ADAP_BAD_PERFLIB_BAD_RETURN
|
|
//
|
|
m_EventLogCalled = TRUE;
|
|
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE, WBEM_MC_ADAP_BAD_PERFLIB_BAD_RETURN , (LPCWSTR)m_wstrServiceName, CHex( hr ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CAdapPerfLib::Close()
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
if ( m_fOpen )
|
|
{
|
|
m_pPerfThread->Close( this );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CAdapPerfLib::Cleanup()
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
// Terminate the worker thread
|
|
// ===========================
|
|
|
|
if ( NULL != m_pPerfThread )
|
|
m_pPerfThread->Shutdown();
|
|
|
|
// Adjust the status
|
|
// =================
|
|
|
|
EndProcessingStatus();
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CAdapPerfLib::_Open( void )
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Wraps a call to the perflib's open function. Fetches and passes an exports parameter
|
|
// to the open function if it exists.
|
|
//
|
|
// Note: We should use the named mutex to guard around the calls to Open/Collect/Close
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
// Check to ensure that the library has not yet been opened
|
|
// ========================================================
|
|
|
|
if ( ( !m_fOpen ) && SUCCEEDED ( hr ) )
|
|
{
|
|
CNTRegistry reg; // The registry wrapper class
|
|
|
|
// Build the service path
|
|
// ======================
|
|
|
|
WString wstr = L"SYSTEM\\CurrentControlSet\\Services\\";
|
|
wstr += m_wstrServiceName;
|
|
|
|
// Open the registry
|
|
// =================
|
|
|
|
if ( reg.Open( HKEY_LOCAL_MACHINE, wstr ) == CNTRegistry::no_error )
|
|
{
|
|
WCHAR* pwcsExports = NULL;
|
|
|
|
// Get Exports if they are available.
|
|
// ==============================================================
|
|
|
|
if ( reg.MoveToSubkey( L"Linkage" ) == CNTRegistry::no_error )
|
|
{
|
|
DWORD dwNumBytes = 0;
|
|
|
|
if (CNTRegistry::no_error != reg.GetMultiStr( L"Export", &pwcsExports, dwNumBytes ))
|
|
{
|
|
if ( ERROR_FILE_NOT_FOUND == reg.GetLastError())
|
|
{
|
|
// Linkage with no Export, that is OK
|
|
}
|
|
else
|
|
{
|
|
ERRORTRACE((LOG_WMIADAP,"Serivce %S has a non MSDN compliant or invalid Linkage Key\n",(WCHAR *)m_wstrServiceName));
|
|
if (CNTRegistry::no_error != reg.GetStr( L"Export", &pwcsExports))
|
|
{
|
|
pwcsExports = new WCHAR[2];
|
|
if (pwcsExports)
|
|
{
|
|
pwcsExports[0] = 0;
|
|
pwcsExports[1] = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Call the Open function for the perflib
|
|
// ======================================
|
|
|
|
switch ( WaitForSingleObject( m_hPLMutex, PL_TIMEOUT ) )
|
|
{
|
|
case WAIT_OBJECT_0:
|
|
{
|
|
try
|
|
{
|
|
if ( NULL != m_pfnOpenProc )
|
|
{
|
|
LONG lRes = m_pfnOpenProc( pwcsExports );
|
|
if (lRes == ERROR_SUCCESS )
|
|
{
|
|
hr = WBEM_S_NO_ERROR;
|
|
m_fOpen = TRUE;
|
|
}
|
|
else
|
|
{
|
|
SetStatus( ADAP_PERFLIB_IS_INACTIVE );
|
|
hr = WBEM_E_NOT_AVAILABLE;
|
|
}
|
|
|
|
DEBUGTRACE( ( LOG_WMIADAP, "Open called for %S returned %d\n", (LPCWSTR)m_wstrServiceName, lRes ) );
|
|
}
|
|
else
|
|
{
|
|
hr = WBEM_S_NO_ERROR;
|
|
m_fOpen = TRUE;
|
|
}
|
|
}
|
|
catch (...)
|
|
{
|
|
SetStatus( ADAP_PERFLIB_FAILED );
|
|
hr = WBEM_E_FAILED;
|
|
ERRORTRACE( ( LOG_WMIADAP, "Perflib Open function has thrown an exception in %S.\n",(LPWSTR)m_wstrServiceName) );
|
|
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE, WBEM_MC_ADAP_BAD_PERFLIB_EXCEPTION, (LPCWSTR)m_wstrServiceName, CHex( hr ) );
|
|
}
|
|
} break;
|
|
case WAIT_TIMEOUT:
|
|
{
|
|
hr = WBEM_E_NOT_AVAILABLE;
|
|
ERRORTRACE( ( LOG_WMIADAP, "Perflib access mutex timed out in %S.\n",(LPWSTR)m_wstrServiceName) );
|
|
}break;
|
|
case WAIT_ABANDONED:
|
|
{
|
|
hr = WBEM_E_FAILED;
|
|
ERRORTRACE( ( LOG_WMIADAP, "Perflib access mutex was abandoned in %S.\n",(LPWSTR)m_wstrServiceName) );
|
|
}break;
|
|
default:
|
|
{
|
|
hr = WBEM_E_FAILED;
|
|
ERRORTRACE( ( LOG_WMIADAP, "Unknown error with perflib access mutex in %S.\n",(LPWSTR)m_wstrServiceName) );
|
|
}
|
|
} // switch
|
|
|
|
ReleaseMutex( m_hPLMutex );
|
|
|
|
if ( NULL != pwcsExports )
|
|
{
|
|
delete [] pwcsExports;
|
|
}
|
|
|
|
} // IF reg.Open
|
|
else
|
|
{
|
|
hr = WBEM_E_FAILED;
|
|
ERRORTRACE( ( LOG_WMIADAP, "Could not open the %S registry key.\n", wstr ) );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ERRORTRACE( ( LOG_WMIADAP, "Performance library %S has not been loaded.\n",(LPWSTR)m_wstrServiceName) );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CAdapPerfLib::_GetPerfBlock( PERF_OBJECT_TYPE** ppData, DWORD* pdwBytes, DWORD* pdwNumObjTypes, BOOL fCostly )
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Wraps a call to the perflib's collect function. Will create progressively larger buffers
|
|
// in a private heap to attempt to fetch the performance data block.
|
|
//
|
|
// Parameters:
|
|
// ppData - a pointer to a buffer pointer for the data blob
|
|
// pdwBytes - a pointer to the byte-size of the data blob
|
|
// pdwNumObjTypes - a pointer to the number of objects in the data blob
|
|
// fCostly - a flag to determine what type of data to collect (costly or global)
|
|
//
|
|
// NOTE: This should always return perf object type data, since we cannot specify a
|
|
// foreign computer, which would cause the collect function to return a PERF_DATA_BLOCK
|
|
// structure.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
CAdapSafeBuffer SafeBuffer( m_wstrServiceName ); // The safe buffer
|
|
DWORD dwNumBytes = 0; // Byte counter for the buffer size
|
|
DWORD dwError = ERROR_MORE_DATA; // The return value for the collect function
|
|
DWORD Increment = 0x10000;
|
|
|
|
// this is a workaround for perfproc.dll
|
|
if (0 == wbem_wcsicmp(m_wstrServiceName,L"perfproc"))
|
|
{
|
|
Increment = 0x100000;
|
|
}
|
|
|
|
|
|
|
|
// Verify provider status
|
|
// ======================
|
|
|
|
if ( m_fOpen )
|
|
{
|
|
// Sets the data-to-fetch parameter
|
|
// ================================
|
|
|
|
WCHAR* pwcsValue = ( fCostly ? L"Costly" : L"Global" );
|
|
|
|
// Start buffer at 64k (the guarded (safe) buffer is 2 * GUARD_BLOCK bytes smaller)
|
|
// ==================================================================================
|
|
|
|
dwNumBytes = Increment;
|
|
|
|
// Repeatedly attempt to collect the data until successful (buffer is sufficiently
|
|
// large), or the attempt fails for a reason other than buffer size
|
|
// ===============================================================================
|
|
|
|
while ( (ERROR_MORE_DATA == dwError ) && ( SUCCEEDED( hr ) ) )
|
|
{
|
|
// Allocate a raw buffer of size dwNumBytes
|
|
// ========================================
|
|
if (dwNumBytes > s_MaxSizeCollect)
|
|
{
|
|
ERRORTRACE((LOG_WMIADAP,"Library %S: Collect function requires more than 0x%08x bytes to complete",(WCHAR *)m_wstrServiceName,s_MaxSizeCollect));
|
|
m_CollectOK = FALSE;
|
|
hr = WBEM_E_QUOTA_VIOLATION;
|
|
break;
|
|
}
|
|
hr = SafeBuffer.SetSize( dwNumBytes );
|
|
if (FAILED(hr)) break;
|
|
|
|
// Collect the data from the perflib
|
|
// =================================
|
|
|
|
switch ( WaitForSingleObject( m_hPLMutex, PL_TIMEOUT ) )
|
|
{
|
|
case WAIT_OBJECT_0:
|
|
{
|
|
try
|
|
{
|
|
dwError = m_pfnCollectProc( pwcsValue,
|
|
SafeBuffer.GetSafeBufferPtrPtr(),
|
|
SafeBuffer.GetDataBlobSizePtr(),
|
|
SafeBuffer.GetNumObjTypesPtr() );
|
|
|
|
DEBUGTRACE( ( LOG_WMIADAP, "Collect called for %S returned %d\n", (LPCWSTR)m_wstrServiceName, dwError ) );
|
|
}
|
|
catch (...)
|
|
{
|
|
SetStatus( ADAP_PERFLIB_FAILED );
|
|
hr = WBEM_E_FAILED;
|
|
|
|
ERRORTRACE( ( LOG_WMIADAP, "Perflib Collection function has thrown an exception in %S.\n",(LPCWSTR)m_wstrServiceName) );
|
|
if (!m_EventLogCalled){
|
|
m_EventLogCalled = TRUE;
|
|
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE, WBEM_MC_ADAP_BAD_PERFLIB_EXCEPTION, (LPCWSTR)m_wstrServiceName, CHex( dwError ) );
|
|
|
|
}
|
|
}
|
|
}break;
|
|
case WAIT_TIMEOUT:
|
|
{
|
|
hr = WBEM_E_NOT_AVAILABLE;
|
|
ERRORTRACE( ( LOG_WMIADAP, "Perflib access mutex timed out in %S.\n",(LPCWSTR)m_wstrServiceName) );
|
|
}break;
|
|
case WAIT_ABANDONED:
|
|
{
|
|
hr = WBEM_E_FAILED;
|
|
ERRORTRACE( ( LOG_WMIADAP, "Perflib access mutex was abandoned in %S.\n",(LPCWSTR)m_wstrServiceName) );
|
|
}break;
|
|
default:
|
|
{
|
|
hr = WBEM_E_FAILED;
|
|
ERRORTRACE( ( LOG_WMIADAP, "Unknown error with perflib access mutex in %S.\n",(LPCWSTR)m_wstrServiceName) );
|
|
}
|
|
} // switch
|
|
|
|
ReleaseMutex( m_hPLMutex );
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
switch (dwError)
|
|
{
|
|
case ERROR_SUCCESS:
|
|
{
|
|
//
|
|
// the Validate function can call ReportEvent
|
|
// by itself, and we don't want to bother user too much
|
|
//
|
|
hr = SafeBuffer.Validate(&m_EventLogCalled);
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = SafeBuffer.CopyData( (BYTE**) ppData, pdwBytes, pdwNumObjTypes );
|
|
}
|
|
else
|
|
{
|
|
// Catastrophic error has occured
|
|
// ==============================
|
|
|
|
SetStatus( ADAP_PERFLIB_FAILED );
|
|
|
|
if (!m_EventLogCalled)
|
|
{
|
|
m_EventLogCalled = TRUE;
|
|
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE,
|
|
WBEM_MC_ADAP_BAD_PERFLIB_INVALID_DATA,
|
|
(LPCWSTR)m_wstrServiceName,
|
|
CHex(hr));
|
|
|
|
}
|
|
}
|
|
} break;
|
|
case ERROR_MORE_DATA:
|
|
{
|
|
dwNumBytes += Increment;
|
|
} break;
|
|
default:
|
|
{
|
|
hr = WBEM_E_FAILED;
|
|
|
|
m_CollectOK = FALSE;
|
|
|
|
ERRORTRACE( ( LOG_WMIADAP, "Perflib Collection function has returned an unknown error(%d) in %S.\n", dwError,(LPCWSTR)m_wstrServiceName ) );
|
|
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE, WBEM_MC_ADAP_BAD_PERFLIB_BAD_RETURN, (LPCWSTR)m_wstrServiceName, CHex( dwError ) );
|
|
}
|
|
} // switch
|
|
} // IF SUCCEEDED()
|
|
} // WHILE
|
|
|
|
// Clean up the buffer
|
|
// ===================
|
|
} // IF CheckStatus
|
|
else
|
|
{
|
|
ERRORTRACE( ( LOG_WMIADAP, "Performance library %S has not been loaded.\n",(LPCWSTR)m_wstrServiceName) );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CAdapPerfLib::_Close( void )
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Wraps a call to the perflib's close function.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
// Verify that the perflib is actually open
|
|
// ========================================
|
|
|
|
if ( m_fOpen )
|
|
{
|
|
// Get the mutex
|
|
// =============
|
|
|
|
switch ( WaitForSingleObject( m_hPLMutex, PL_TIMEOUT ) )
|
|
{
|
|
case WAIT_OBJECT_0:
|
|
{
|
|
try
|
|
{
|
|
// And call the function
|
|
// =====================
|
|
|
|
if ( NULL != m_pfnCloseProc )
|
|
{
|
|
LONG lRet = m_pfnCloseProc();
|
|
|
|
DEBUGTRACE( ( LOG_WMIADAP, "Close called for %S returned %d\n", (LPCWSTR)m_wstrServiceName, lRet ) );
|
|
}
|
|
|
|
m_fOpen = FALSE;
|
|
}
|
|
catch (...)
|
|
{
|
|
// Ooops... something blew, return error code
|
|
// ==========================================
|
|
|
|
SetStatus( ADAP_PERFLIB_FAILED );
|
|
hr = WBEM_E_FAILED;
|
|
ERRORTRACE( ( LOG_WMIADAP, "Perflib Close function has thrown an exception in %S.\n",(LPCWSTR)m_wstrServiceName) );
|
|
CAdapUtility::NTLogEvent( EVENTLOG_WARNING_TYPE, WBEM_MC_ADAP_BAD_PERFLIB_EXCEPTION, (LPCWSTR)m_wstrServiceName, CHex( hr ) );
|
|
}
|
|
}break;
|
|
case WAIT_TIMEOUT:
|
|
{
|
|
hr = WBEM_E_NOT_AVAILABLE;
|
|
ERRORTRACE( ( LOG_WMIADAP, "Perflib access mutex timed out in %S.\n",(LPCWSTR)m_wstrServiceName) );
|
|
}break;
|
|
case WAIT_ABANDONED:
|
|
{
|
|
hr = WBEM_E_FAILED;
|
|
ERRORTRACE( ( LOG_WMIADAP, "Perflib access mutex was abandoned in %S.\n",(LPCWSTR)m_wstrServiceName) );
|
|
}break;
|
|
default:
|
|
{
|
|
hr = WBEM_E_FAILED;
|
|
ERRORTRACE( ( LOG_WMIADAP, "Unknown error with perflib access mutex in %S.\n",(LPCWSTR)m_wstrServiceName) );
|
|
} }
|
|
|
|
ReleaseMutex( m_hPLMutex );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CAdapPerfLib::SetStatus(DWORD dwStatus)
|
|
{
|
|
HRESULT hr = WBEM_NO_ERROR;
|
|
|
|
m_dwStatus |= dwStatus;
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CAdapPerfLib::ClearStatus(DWORD dwStatus)
|
|
{
|
|
HRESULT hr = WBEM_NO_ERROR;
|
|
|
|
m_dwStatus &= ~dwStatus;
|
|
|
|
return hr;
|
|
}
|
|
|
|
BOOL CAdapPerfLib::CheckStatus(DWORD dwStatus)
|
|
{
|
|
return ((m_dwStatus & dwStatus) == dwStatus);
|
|
}
|