609 lines
17 KiB
C++
609 lines
17 KiB
C++
// 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__
|