Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

608 lines
17 KiB

// This is a part of the Active Template Library.
// Copyright (C) 1996-2001 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Active Template Library Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Active Template Library product.
#ifndef __ATLPERF_H__
#define __ATLPERF_H__
#pragma once
#ifndef __cplusplus
#error ATL requires C++ compilation (use a .cpp suffix)
#endif
#include <atlbase.h>
#include <atlcom.h>
#include <atlstr.h>
#include <atlfile.h>
#include <atlsync.h>
#include <winperf.h>
#include <atlcoll.h>
#ifndef _ATL_PERF_NOXML
#include <atlenc.h>
#include <oaidl.h>
#include <xmldomdid.h>
#include <xmldsodid.h>
#include <msxmldid.h>
#include <msxml.h>
#endif
namespace ATL
{
const DWORD ATLPERF_SIZE_MASK = 0x00000300;
const DWORD ATLPERF_TYPE_MASK = 0x00000C00;
const DWORD ATLPERF_TEXT_MASK = 0x00010000;
#ifndef ATLPERF_DEFAULT_MAXINSTNAMELENGTH
#define ATLPERF_DEFAULT_MAXINSTNAMELENGTH 64
#endif
// base class for user-defined perf objects
struct CPerfObject
{
ULONG m_nAllocSize;
DWORD m_dwObjectId;
DWORD m_dwInstance;
ULONG m_nRefCount;
ULONG m_nInstanceNameOffset; // byte offset from beginning of PerfObject to LPWSTR szInstanceName
};
struct CPerfMapEntry
{
DWORD m_dwPerfId;
CString m_strName;
CString m_strHelp;
DWORD m_dwDetailLevel;
BOOL m_bIsObject;
// OBJECT INFO
ULONG m_nNumCounters;
LONG m_nDefaultCounter;
LONG m_nInstanceLess; // PERF_NO_INSTANCES if instanceless
// the size of the struct not counting the name and string counters
ULONG m_nStructSize;
// in characters including the null terminator
ULONG m_nMaxInstanceNameLen;
ULONG m_nAllocSize;
// COUNTER INFO
DWORD m_dwCounterType;
LONG m_nDefaultScale;
// the maximum size of the string counter data in characters, including the null terminator
// ignored if not a string counter
ULONG m_nMaxCounterSize;
ULONG m_nDataOffset;
// the ids that correspond to the name and help strings stored in the registry
UINT m_nNameId;
UINT m_nHelpId;
};
class CPerfMon
{
public:
~CPerfMon() throw();
// PerfMon entry point helpers
DWORD Open(LPWSTR lpDeviceNames) throw();
DWORD Collect(LPWSTR lpwszValue, LPVOID* lppData, LPDWORD lpcbBytes, LPDWORD lpcObjectTypes) throw();
DWORD Close() throw();
#ifdef _ATL_PERF_REGISTER
// registration
HRESULT Register(
LPCTSTR szOpenFunc,
LPCTSTR szCollectFunc,
LPCTSTR szCloseFunc,
HINSTANCE hDllInstance = _AtlBaseModule.GetModuleInstance()) throw();
HRESULT RegisterStrings(
LANGID wLanguage = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
HINSTANCE hResInstance = _AtlBaseModule.GetResourceInstance()) throw();
HRESULT RegisterAllStrings(HINSTANCE hResInstance = NULL) throw();
HRESULT Unregister() throw();
static BOOL CALLBACK EnumResLangProc(HINSTANCE hModule, LPCTSTR szType, LPCTSTR szName, LANGID wIDLanguage, LPARAM lParam);
#endif
HRESULT Initialize() throw();
void UnInitialize() throw();
HRESULT CreateInstance(
DWORD dwObjectId,
DWORD dwInstance,
LPCWSTR szInstanceName,
CPerfObject** ppInstance) throw();
HRESULT CreateInstanceByName(
DWORD dwObjectId,
LPCWSTR szInstanceName,
CPerfObject** ppInstance) throw();
template <class T>
HRESULT CreateInstance(
DWORD dwInstance,
LPCWSTR szInstanceName,
T** ppInstance) throw()
{
// Ensure T derives from CPerfObject
static_cast<CPerfObject*>(*ppInstance);
return CreateInstance(
T::kObjectId,
dwInstance,
szInstanceName,
reinterpret_cast<CPerfObject**>(ppInstance)
);
}
template <class T>
HRESULT CreateInstanceByName(
LPCWSTR szInstanceName,
T** ppInstance) throw()
{
// Ensure T derives from CPerfObject
static_cast<CPerfObject*>(*ppInstance);
return CreateInstanceByName(
T::kObjectId,
szInstanceName,
reinterpret_cast<CPerfObject**>(ppInstance)
);
}
HRESULT ReleaseInstance(CPerfObject* pInstance) throw();
HRESULT LockPerf(DWORD dwTimeout = INFINITE) throw();
void UnlockPerf() throw();
// map building routines
HRESULT AddObjectDefinition(
DWORD dwObjectId,
LPCTSTR szObjectName,
LPCTSTR szHelpString,
DWORD dwDetailLevel,
INT nDefaultCounter,
BOOL bInstanceLess,
UINT nStructSize,
UINT nMaxInstanceNameLen = ATLPERF_DEFAULT_MAXINSTNAMELENGTH) throw();
HRESULT AddCounterDefinition(
DWORD dwCounterId,
LPCTSTR szCounterName,
LPCTSTR szHelpString,
DWORD dwDetailLevel,
DWORD dwCounterType,
ULONG nMaxCounterSize,
UINT nOffset,
INT nDefaultScale) throw();
void ClearMap() throw();
#ifndef _ATL_PERF_NOXML
HRESULT PersistToXML(IStream *pStream, BOOL bFirst=TRUE, BOOL bLast=TRUE) throw(...);
HRESULT LoadFromXML(IStream *pStream) throw(...);
#endif
protected:
virtual LPCTSTR GetAppName() const throw() = 0;
virtual HRESULT CreateMap(WORD wLanguage, HINSTANCE hResInstance, UINT* pSampleRes = NULL) throw();
virtual void OnBlockAlloc(CAtlFileMappingBase* /*pNewBlock*/) { }
// implementation helpers
LPBYTE _AllocData(LPBYTE& pData, ULONG nBytesAvail, ULONG* pnBytesUsed, size_t nBytesNeeded) throw();
template<typename T> T* _AllocStruct(LPBYTE& pData, ULONG nBytesAvail, ULONG* pnBytesUsed, T*) throw()
{
return reinterpret_cast<T*>(_AllocData(pData, nBytesAvail, pnBytesUsed, sizeof(T)));
}
CPerfMapEntry& _GetMapEntry(UINT nIndex) throw();
UINT _GetNumMapEntries() throw();
CPerfObject* _GetFirstObject(CAtlFileMappingBase* pBlock) throw();
CPerfObject* _GetNextObject(CPerfObject* pInstance) throw();
CAtlFileMappingBase* _GetNextBlock(CAtlFileMappingBase* pBlock) throw();
CAtlFileMappingBase* _AllocNewBlock(CAtlFileMappingBase* pPrev, BOOL* pbExisted = NULL) throw();
DWORD& _GetBlockId(CAtlFileMappingBase* pBlock) throw();
CPerfMapEntry* _FindObjectInfo(DWORD dwObjectId) throw();
CPerfMapEntry* _FindCounterInfo(CPerfMapEntry* pObjectEntry, DWORD dwCounterId) throw();
CPerfMapEntry* _FindCounterInfo(DWORD dwObjectId, DWORD dwCounterId) throw();
BOOL _WantObjectType(LPWSTR lpwszValue, DWORD dwPerfId) throw(...);
void _FillObjectType(PERF_OBJECT_TYPE* pObjectType, CPerfMapEntry* pObjectEntry) throw();
void _FillCounterDef(
PERF_COUNTER_DEFINITION* pCounterDef,
CPerfMapEntry* pCounterEntry,
ULONG& nCBSize) throw();
HRESULT _CollectObjectType(
CPerfMapEntry* pObjectEntry,
LPBYTE pData,
ULONG nBytesAvail,
ULONG* pnBytesUsed) throw();
HRESULT _LoadMap() throw();
HRESULT _SaveMap() throw();
HRESULT _GetAttribute(
IXMLDOMNode *pNode,
LPCWSTR szAttrName,
BSTR *pbstrVal) throw();
HRESULT CPerfMon::_CreateInstance(
DWORD dwObjectId,
DWORD dwInstance,
LPCWSTR szInstanceName,
CPerfObject** ppInstance,
bool bByName) throw();
#ifdef _ATL_PERF_REGISTER
void _AppendStrings(
LPTSTR& pszNew,
CAtlArray<CString>& astrStrings,
ULONG iFirstIndex
) throw();
HRESULT _AppendRegStrings(
CRegKey& rkLang,
LPCTSTR szValue,
CAtlArray<CString>& astrStrings,
ULONG nNewStringSize,
ULONG iFirstIndex,
ULONG iLastIndex) throw();
HRESULT _RemoveRegStrings(
CRegKey& rkLang,
LPCTSTR szValue,
ULONG iFirstIndex,
ULONG iLastIndex) throw();
HRESULT _ReserveStringRange(DWORD& dwFirstCounter, DWORD& dwFirstHelp) throw();
HRESULT _UnregisterStrings() throw();
HRESULT _RegisterAllStrings(UINT nRes, HINSTANCE hResInstance) throw();
#endif
private:
CAtlArray<CPerfMapEntry> m_map;
CAutoPtrArray<CAtlFileMappingBase> m_aMem;
CMutex m_lock;
ULONG m_nAllocSize;
ULONG m_nHeaderSize;
ULONG m_nSchemaSize;
ULONG m_nNumObjectTypes;
};
class CPerfLock
{
public:
CPerfLock(CPerfMon* pPerfMon, DWORD dwTimeout = INFINITE) throw()
{
ATLASSERT(pPerfMon != NULL);
m_pPerfMon = pPerfMon;
m_hrStatus = m_pPerfMon->LockPerf(dwTimeout);
}
~CPerfLock() throw()
{
if (SUCCEEDED(m_hrStatus))
m_pPerfMon->UnlockPerf();
}
HRESULT GetStatus() const throw()
{
return m_hrStatus;
}
private:
CPerfMon* m_pPerfMon;
HRESULT m_hrStatus;
};
// empty definition just for ease of use with code wizards, etc.
#define BEGIN_PERFREG_MAP()
// empty definition just for ease of use with code wizards, etc.
#define END_PERFREG_MAP()
#if !defined(_ATL_PERF_REGISTER) | defined(_ATL_PERF_NOEXPORT)
#define PERFREG_ENTRY(className)
#endif
#ifdef _ATL_PERF_REGISTER
#define BEGIN_PERF_MAP(AppName) \
private: \
LPCTSTR GetAppName() const throw() { return AppName; } \
HRESULT CreateMap(WORD wLanguage, HINSTANCE hResInstance, UINT* pSampleRes = NULL) throw() \
{ \
CPerfMon* pPerf = this; \
wLanguage; \
hResInstance; \
if (pSampleRes) \
*pSampleRes = 0; \
CString strName; \
CString strHelp; \
HRESULT hr; \
ClearMap();
#define BEGIN_COUNTER_MAP(objectclass) \
public: \
typedef objectclass _PerfCounterClass; \
static HRESULT CreateMap(CPerfMon* pPerf, WORD wLanguage, HINSTANCE hResInstance, UINT* pSampleRes) throw() \
{ \
wLanguage; \
hResInstance; \
pSampleRes; \
CString strName; \
CString strHelp; \
HRESULT hr; \
hr = RegisterObject(pPerf, wLanguage, hResInstance, pSampleRes); \
if (FAILED(hr)) \
return hr;
#define DECLARE_PERF_OBJECT_EX(dwObjectId, namestring, helpstring, detail, instanceless, structsize, maxinstnamelen, defcounter) \
static HRESULT RegisterObject(CPerfMon* pPerf, WORD wLanguage, HINSTANCE hResInstance, UINT* pSampleRes) throw() \
{ \
CString strName; \
CString strHelp; \
HRESULT hr; \
_ATLTRY \
{ \
if (IS_INTRESOURCE(namestring)) \
{ \
ATLASSERT(IS_INTRESOURCE(helpstring)); \
if (pSampleRes) \
*pSampleRes = (UINT) (UINT_PTR) namestring; \
if (hResInstance && !strName.LoadString(hResInstance, (UINT) (UINT_PTR) namestring, wLanguage)) \
return E_FAIL; \
if (hResInstance && !strHelp.LoadString(hResInstance, (UINT) (UINT_PTR) helpstring, wLanguage)) \
return E_FAIL; \
} \
else \
{ \
ATLASSERT(!IS_INTRESOURCE(helpstring)); \
strName = (LPCTSTR) namestring; \
strHelp = (LPCTSTR) helpstring; \
} \
} \
_ATLCATCHALL() \
{ \
return E_FAIL; \
} \
hr = pPerf->AddObjectDefinition(dwObjectId, strName, strHelp, detail, defcounter, instanceless, (ULONG) structsize, maxinstnamelen); \
if (FAILED(hr)) \
return hr; \
return S_OK; \
} \
/* NOTE: put a semicolon after your call to DECLARE_PERF_OBJECT*(...) */ \
/* this is needed for the code wizards to parse things properly */ \
static const DWORD kObjectId = dwObjectId
#define CHAIN_PERF_OBJECT(objectclass) \
hr = objectclass::CreateMap(pPerf, wLanguage, hResInstance, pSampleRes); \
if (FAILED(hr)) \
return hr;
// CAssertValidField ensures that the member variable that's being passed to
// DEFINE_COUNTER[_EX] is the proper type. only 32-bit integral types can be used with
// PERF_SIZE_DWORD and only 64-bit integral types can be used with PERF_SIZE_LARGE
template< DWORD t_dwSize >
class CAssertValidField
{
};
template<>
class CAssertValidField< PERF_SIZE_DWORD >
{
public:
template< class C > static void AssertValidFieldType( ULONG C::* ) throw() { }
template< class C > static void AssertValidFieldType( LONG C::* ) throw() { }
};
template<>
class CAssertValidField< PERF_SIZE_LARGE >
{
public:
template< class C > static void AssertValidFieldType( ULONGLONG C::* p ) throw() { }
template< class C > static void AssertValidFieldType( LONGLONG C::* p ) throw() { }
};
#define DEFINE_COUNTER_EX(member, dwCounterId, namestring, helpstring, detail, countertype, maxcountersize, defscale) \
CAssertValidField< (countertype) & ATLPERF_SIZE_MASK >::AssertValidFieldType( &_PerfCounterClass::member ); \
_ATLTRY \
{ \
if (IS_INTRESOURCE(namestring)) \
{ \
ATLASSERT(IS_INTRESOURCE(helpstring)); \
if (hResInstance && !strName.LoadString(hResInstance, (UINT) (UINT_PTR) namestring, wLanguage)) \
return E_FAIL; \
if (hResInstance && !strHelp.LoadString(hResInstance, (UINT) (UINT_PTR) helpstring, wLanguage)) \
return E_FAIL; \
} \
else \
{ \
ATLASSERT(!IS_INTRESOURCE(helpstring)); \
strName = (LPCTSTR) namestring; \
strHelp = (LPCTSTR) helpstring; \
} \
} \
_ATLCATCHALL() \
{ \
return E_FAIL; \
} \
hr = pPerf->AddCounterDefinition(dwCounterId, strName, strHelp, detail, countertype, maxcountersize, (ULONG) offsetof(_PerfCounterClass, member), defscale); \
if (FAILED(hr)) \
return hr;
#define END_PERF_MAP() \
return S_OK; \
}
#define END_COUNTER_MAP() \
return S_OK; \
}
// define _ATL_PERF_NOEXPORT if you don't want to use the PERFREG map and don't want these
// functions exported from your DLL
#ifndef _ATL_PERF_NOEXPORT
// Perf register map stuff
// this is for ease of integration with the module attribute and for the
// perfmon wizard
#pragma data_seg(push)
#pragma data_seg("ATLP$A")
__declspec(selectany) CPerfMon * __pperfA = NULL;
#pragma data_seg("ATLP$Z")
__declspec(selectany) CPerfMon * __pperfZ = NULL;
#pragma data_seg("ATLP$C")
#pragma data_seg(pop)
ATL_NOINLINE inline HRESULT RegisterPerfMon(HINSTANCE hDllInstance = _AtlBaseModule.GetModuleInstance()) throw()
{
CPerfMon **ppPerf = &__pperfA;
HRESULT hr = S_OK;
while (ppPerf != &__pperfZ)
{
if (*ppPerf != NULL)
{
hr = (*ppPerf)->Register(_T("_OpenPerfMon"), _T("_CollectPerfMon"), _T("_ClosePerfMon"), hDllInstance);
if (FAILED(hr))
return hr;
hr = (*ppPerf)->RegisterAllStrings(hDllInstance);
if (FAILED(hr))
return hr;
}
ppPerf++;
}
return S_OK;
}
ATL_NOINLINE inline HRESULT UnregisterPerfMon() throw()
{
CPerfMon **ppPerf = &__pperfA;
HRESULT hr = S_OK;
while (ppPerf != &__pperfZ)
{
if (*ppPerf != NULL)
{
hr = (*ppPerf)->Unregister();
if (FAILED(hr))
return hr;
}
ppPerf++;
}
return S_OK;
}
extern "C" ATL_NOINLINE inline DWORD __declspec(dllexport) WINAPI OpenPerfMon(LPWSTR lpDeviceNames) throw()
{
CPerfMon **ppPerf = &__pperfA;
DWORD dwErr = 0;
while (ppPerf != &__pperfZ)
{
if (*ppPerf != NULL)
{
dwErr = (*ppPerf)->Open(lpDeviceNames);
if (dwErr != 0)
return dwErr;
}
ppPerf++;
}
return 0;
}
extern "C" ATL_NOINLINE inline DWORD __declspec(dllexport) WINAPI CollectPerfMon(LPWSTR lpwszValue, LPVOID* lppData,
LPDWORD lpcbBytes, LPDWORD lpcObjectTypes) throw()
{
DWORD dwOrigBytes = *lpcbBytes;
DWORD dwBytesRemaining = *lpcbBytes;
CPerfMon **ppPerf = &__pperfA;
DWORD dwErr = 0;
while (ppPerf != &__pperfZ)
{
if (*ppPerf != NULL)
{
dwErr = (*ppPerf)->Collect(lpwszValue, lppData, lpcbBytes, lpcObjectTypes);
if (dwErr != 0)
return dwErr;
dwBytesRemaining -= *lpcbBytes;
*lpcbBytes = dwBytesRemaining;
}
ppPerf++;
}
*lpcbBytes = dwOrigBytes - dwBytesRemaining;
return 0;
}
extern "C" ATL_NOINLINE inline DWORD __declspec(dllexport) WINAPI ClosePerfMon() throw()
{
CPerfMon **ppPerf = &__pperfA;
while (ppPerf != &__pperfZ)
{
if (*ppPerf != NULL)
{
(*ppPerf)->Close();
}
ppPerf++;
}
return 0;
}
// this class handles integrating the registration with CComModule
class _CAtlPerfSetFuncPtr
{
public:
_CAtlPerfSetFuncPtr()
{
_pPerfRegFunc = RegisterPerfMon;
_pPerfUnRegFunc = UnregisterPerfMon;
}
};
extern "C" { __declspec(selectany) _CAtlPerfSetFuncPtr g_atlperfinit; }
#pragma comment(linker, "/INCLUDE:_g_atlperfinit")
#if defined(_M_IX86)
#define PERF_ENTRY_PRAGMA(class) __pragma(comment(linker, "/include:___pperf_" #class))
#elif defined(_M_IA64)
#define PERF_ENTRY_PRAGMA(class) __pragma(comment(linker, "/include:__pperf_" #class))
#else
#error Unknown Platform. define PERF_ENTRY_PRAGMA
#endif
#define PERFREG_ENTRY(className) \
className __perf_##className; \
extern "C" __declspec(allocate("ATLP$C")) CPerfMon * __pperf_##className = \
static_cast<CPerfMon*>(&__perf_##className); \
PERF_ENTRY_PRAGMA(className)
#endif // _ATL_PERF_NOEXPORT
#else // _ATL_PERF_REGISTER
#define BEGIN_PERF_MAP(AppName) \
private: \
LPCTSTR GetAppName() const throw() { return AppName; }
#define BEGIN_COUNTER_MAP(objectclass)
#define DECLARE_PERF_OBJECT_EX(dwObjectId, namestring, helpstring, detail, instanceless, structsize, maxinstnamelen, defcounter) \
/* NOTE: put a semicolon after your call to DECLARE_PERF_OBJECT*(...) */ \
/* this is needed for the code wizards to parse things properly */ \
static const DWORD kObjectId = dwObjectId
#define CHAIN_PERF_OBJECT(objectclass)
#define DEFINE_COUNTER_EX(member, dwCounterId, namestring, helpstring, detail, countertype, maxcountersize, defscale)
#define END_PERF_MAP()
#define END_COUNTER_MAP()
#endif // _ATL_PERF_REGISTER
#define DECLARE_PERF_OBJECT(objectclass, dwObjectId, namestring, helpstring, defcounter) \
DECLARE_PERF_OBJECT_EX(dwObjectId, namestring, helpstring, PERF_DETAIL_NOVICE, 0, sizeof(objectclass), ATLPERF_DEFAULT_MAXINSTNAMELENGTH, defcounter)
#define DECLARE_PERF_OBJECT_NO_INSTANCES(objectclass, dwObjectId, namestring, helpstring, defcounter) \
DECLARE_PERF_OBJECT_EX(dwObjectId, namestring, helpstring, PERF_DETAIL_NOVICE, PERF_NO_INSTANCES, sizeof(objectclass), 0, defcounter)
#define DEFINE_COUNTER(member, namestring, helpstring, countertype, defscale) \
DEFINE_COUNTER_EX(member, 0, namestring, helpstring, PERF_DETAIL_NOVICE, countertype, 0, defscale)
} // namespace ATL
#include <atlperf.inl>
#endif // __ATLPERF_H__