664 lines
21 KiB
C++
664 lines
21 KiB
C++
// This is a part of the Active Template Library.
|
|
// Copyright (C) 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>
|
|
#include <atlsecurity.h>
|
|
|
|
#ifndef _ATL_PERF_NOXML
|
|
#include <atlenc.h>
|
|
#include <oaidl.h>
|
|
#include <xmldomdid.h>
|
|
|
|
/* xmldsodid and mshtmdid both have the same identifiers defined, with differing values. So we are renaming the XML ones since there are less identifiers dependent on those. */
|
|
#ifdef DISPID_XOBJ_MIN
|
|
/* in case the HTM one was included first, we'll undef these first */
|
|
#define _ATL_MSHTMDID_INCLUDED_ALREADY
|
|
#undef DISPID_XOBJ_MIN
|
|
#undef DISPID_XOBJ_MAX
|
|
#undef DISPID_XOBJ_BASE
|
|
#endif
|
|
|
|
#include <xmldsodid.h>
|
|
#include <msxmldid.h>
|
|
|
|
/* re-undef the clashing names, and their direct dependents */
|
|
#undef DISPID_XOBJ_MIN
|
|
#undef DISPID_XOBJ_MAX
|
|
#undef DISPID_XOBJ_BASE
|
|
#undef DISPID_XMLDSO
|
|
#undef DISPID_XMLELEMENTCOLLECTION
|
|
|
|
/* re-def the clashing names, and their direct dependents, with un-clashed values */
|
|
#define DISPID_XMLDSO_XOBJ_MIN 0x00010000
|
|
#define DISPID_XMLDSO_XOBJ_MAX 0x0001FFFF
|
|
#define DISPID_XMLDSO_XOBJ_BASE DISPID_XMLDSO_XOBJ_MIN
|
|
#define DISPID_XMLDSO DISPID_XMLDSO_XOBJ_BASE
|
|
#define DISPID_XMLELEMENTCOLLECTION DISPID_XMLDSO_XOBJ_BASE
|
|
#ifdef _ATL_MSHTMDID_INCLUDED_ALREADY
|
|
|
|
/* redef the clashing names to the HTM values */
|
|
#define DISPID_XOBJ_MIN 0x80010000
|
|
#define DISPID_XOBJ_MAX 0x8001FFFF
|
|
#define DISPID_XOBJ_BASE DISPID_XOBJ_MIN
|
|
#endif
|
|
#include <msxml.h>
|
|
#endif
|
|
|
|
#pragma warning(push)
|
|
#pragma warning(disable: 4625) // copy constructor could not be generated because a base class copy constructor is inaccessible
|
|
#pragma warning(disable: 4626) // assignment operator could not be generated because a base class assignment operator is inaccessible
|
|
|
|
|
|
#pragma pack(push,_ATL_PACKING)
|
|
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
|
|
{
|
|
// implementation
|
|
|
|
ULONG m_nAllocSize;
|
|
DWORD m_dwCategoryId;
|
|
DWORD m_dwInstance;
|
|
ULONG m_nRefCount;
|
|
ULONG m_nInstanceNameOffset; // byte offset from beginning of PerfObject to LPWSTR szInstanceName
|
|
};
|
|
|
|
class CPerfMon
|
|
{
|
|
public:
|
|
virtual ~CPerfMon() 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();
|
|
#endif
|
|
|
|
HRESULT Initialize() throw();
|
|
void UnInitialize() throw();
|
|
HRESULT CreateInstance(
|
|
DWORD dwCategoryId,
|
|
DWORD dwInstance,
|
|
LPCWSTR szInstanceName,
|
|
CPerfObject** ppInstance) throw();
|
|
HRESULT CreateInstanceByName(
|
|
DWORD dwCategoryId,
|
|
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::kCategoryId,
|
|
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::kCategoryId,
|
|
szInstanceName,
|
|
reinterpret_cast<CPerfObject**>(ppInstance)
|
|
);
|
|
}
|
|
|
|
HRESULT ReleaseInstance(CPerfObject* pInstance) throw();
|
|
HRESULT LockPerf(DWORD dwTimeout = INFINITE) throw();
|
|
void UnlockPerf() throw();
|
|
|
|
#ifndef _ATL_PERF_NOXML
|
|
HRESULT PersistToXML(IStream *pStream, BOOL bFirst=TRUE, BOOL bLast=TRUE) throw(...);
|
|
HRESULT LoadFromXML(IStream *pStream) throw(...);
|
|
#endif
|
|
|
|
// implementation
|
|
|
|
public:
|
|
// PerfMon entry point helpers
|
|
DWORD Open(LPWSTR lpDeviceNames) throw();
|
|
DWORD Collect(__in_z LPWSTR lpwszValue, __deref_inout_bcount(*pcbBytes) LPVOID* lppData, __inout LPDWORD lpcbBytes, __inout LPDWORD lpcObjectTypes) throw();
|
|
DWORD Close() throw();
|
|
|
|
// map building routines
|
|
HRESULT AddCategoryDefinition(
|
|
DWORD dwCategoryId,
|
|
LPCTSTR szCategoryName,
|
|
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();
|
|
|
|
// macro helpers
|
|
HRESULT RegisterCategory(
|
|
WORD wLanguage,
|
|
HINSTANCE hResInstance,
|
|
UINT* pSampleRes,
|
|
DWORD dwCategoryId,
|
|
UINT nNameString,
|
|
UINT nHelpString,
|
|
DWORD dwDetail,
|
|
BOOL bInstanceless,
|
|
UINT nStructSize,
|
|
UINT nMaxInstanceNameLen,
|
|
INT nDefaultCounter) throw();
|
|
HRESULT RegisterCategory(
|
|
WORD wLanguage,
|
|
HINSTANCE hResInstance,
|
|
UINT* pSampleRes,
|
|
DWORD dwCategoryId,
|
|
LPCTSTR szNameString,
|
|
LPCTSTR szHelpString,
|
|
DWORD dwDetail,
|
|
BOOL bInstanceless,
|
|
UINT nStructSize,
|
|
UINT nMaxInstanceNameLen,
|
|
INT nDefaultCounter) throw();
|
|
HRESULT RegisterCounter(
|
|
WORD wLanguage,
|
|
HINSTANCE hResInstance,
|
|
DWORD dwCounterId,
|
|
UINT nNameString,
|
|
UINT nHelpString,
|
|
DWORD dwDetail,
|
|
DWORD dwCounterType,
|
|
ULONG nMaxCounterSize,
|
|
UINT nOffset,
|
|
INT nDefaultScale) throw();
|
|
HRESULT RegisterCounter(
|
|
WORD wLanguage,
|
|
HINSTANCE hResInstance,
|
|
DWORD dwCounterId,
|
|
LPCTSTR szNameString,
|
|
LPCTSTR szHelpString,
|
|
DWORD dwDetail,
|
|
DWORD dwCounterType,
|
|
ULONG nMaxCounterSize,
|
|
UINT nOffset,
|
|
INT nDefaultScale) throw();
|
|
|
|
protected:
|
|
void ClearMap() throw();
|
|
|
|
virtual LPCTSTR GetAppName() const throw() = 0;
|
|
virtual HRESULT CreateMap(WORD wLanguage, HINSTANCE hResInstance, UINT* pSampleRes = NULL) throw();
|
|
virtual void OnBlockAlloc(CAtlFileMappingBase* /*pNewBlock*/) { }
|
|
#ifdef _ATL_PERF_REGISTER
|
|
static BOOL CALLBACK EnumResLangProc(HINSTANCE hModule, LPCTSTR szType, LPCTSTR szName, LANGID wIDLanguage, LPARAM lParam);
|
|
#endif
|
|
|
|
// implementation helpers
|
|
struct CounterInfo
|
|
{
|
|
CounterInfo() : m_dwCounterId(0), m_dwDetailLevel(0), m_nNameId(0),
|
|
m_nHelpId(0), m_dwCounterType(0), m_nDefaultScale(0),
|
|
m_nMaxCounterSize(0), m_nDataOffset(0)
|
|
{
|
|
ZeroMemory (&m_cache, sizeof(m_cache));
|
|
}
|
|
// implementation
|
|
|
|
DWORD m_dwCounterId;
|
|
CString m_strName;
|
|
CString m_strHelp;
|
|
DWORD m_dwDetailLevel;
|
|
|
|
// the ids that correspond to the name and help strings stored in the registry
|
|
UINT m_nNameId;
|
|
UINT m_nHelpId;
|
|
|
|
// counter data
|
|
|
|
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;
|
|
|
|
// cached data to be copied into request
|
|
PERF_COUNTER_DEFINITION m_cache;
|
|
};
|
|
|
|
struct CategoryInfo
|
|
{
|
|
// implementation
|
|
|
|
DWORD m_dwCategoryId;
|
|
CString m_strName;
|
|
CString m_strHelp;
|
|
DWORD m_dwDetailLevel;
|
|
|
|
// the ids that correspond to the name and help strings stored in the registry
|
|
UINT m_nNameId;
|
|
UINT m_nHelpId;
|
|
|
|
// category data
|
|
|
|
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;
|
|
|
|
// cached data to be copied into request
|
|
PERF_OBJECT_TYPE m_cache;
|
|
ULONG m_nCounterBlockSize;
|
|
|
|
// counters
|
|
UINT _GetNumCounters() throw();
|
|
CounterInfo* _GetCounterInfo(UINT nIndex) throw();
|
|
|
|
CAtlArray<CounterInfo> m_counters;
|
|
};
|
|
|
|
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)));
|
|
}
|
|
|
|
UINT _GetNumCategoriesAndCounters() throw();
|
|
CategoryInfo* _GetCategoryInfo(UINT nIndex) throw();
|
|
UINT _GetNumCategories() throw();
|
|
CPerfObject* _GetFirstInstance(CAtlFileMappingBase* pBlock) throw();
|
|
CPerfObject* _GetNextInstance(CPerfObject* pInstance) throw();
|
|
CAtlFileMappingBase* _GetNextBlock(CAtlFileMappingBase* pBlock) throw();
|
|
CAtlFileMappingBase* _OpenNextBlock(CAtlFileMappingBase* pPrev) throw();
|
|
CAtlFileMappingBase* _AllocNewBlock(CAtlFileMappingBase* pPrev, BOOL* pbExisted = NULL) throw();
|
|
HRESULT _OpenAllBlocks() throw();
|
|
DWORD& _GetBlockId(CAtlFileMappingBase* pBlock) throw(...);
|
|
DWORD* _GetBlockId_NoThrow(CAtlFileMappingBase* pBlock) throw();
|
|
CategoryInfo* _FindCategoryInfo(DWORD dwCategoryId) throw();
|
|
CounterInfo* _FindCounterInfo(CategoryInfo* pCategoryInfo, DWORD dwCounterId) throw();
|
|
CounterInfo* _FindCounterInfo(DWORD dwCategoryId, DWORD dwCounterId) throw();
|
|
BOOL _WantCategoryType(__in_z LPWSTR lpwszValue, __in DWORD dwPerfId) throw(...);
|
|
void _FillCategoryType(CategoryInfo* pCategoryInfo) throw();
|
|
void _FillCounterDef(CounterInfo* pCounterInfo, ULONG* pnCounterBlockSize) throw();
|
|
HRESULT CPerfMon::_CollectInstance(
|
|
CategoryInfo* pCategoryInfo,
|
|
LPBYTE& pData,
|
|
ULONG nBytesAvail,
|
|
ULONG* pnBytesUsed,
|
|
CPerfObject* pInstance,
|
|
PERF_OBJECT_TYPE* pObjectType,
|
|
PERF_COUNTER_DEFINITION* pCounterDefs
|
|
) throw();
|
|
HRESULT _CollectInstance(
|
|
CategoryInfo* pCategoryInfo,
|
|
LPBYTE& pData,
|
|
ULONG nBytesAvail,
|
|
ULONG* pnBytesUsed,
|
|
PERF_OBJECT_TYPE* pObjectType,
|
|
PERF_COUNTER_DEFINITION* pCounterDefs
|
|
) throw();
|
|
HRESULT _CollectCategoryType(
|
|
CategoryInfo* pCategoryInfo,
|
|
LPBYTE pData,
|
|
ULONG nBytesAvail,
|
|
ULONG* pnBytesUsed) throw();
|
|
HRESULT _LoadMap(DWORD* pData) throw();
|
|
HRESULT _SaveMap() throw();
|
|
HRESULT _GetAttribute(
|
|
IXMLDOMNode *pNode,
|
|
LPCWSTR szAttrName,
|
|
BSTR *pbstrVal) throw();
|
|
HRESULT CPerfMon::_CreateInstance(
|
|
DWORD dwCategoryId,
|
|
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<CategoryInfo> m_categories;
|
|
CAutoPtrArray<CAtlFileMappingBase> m_aMem;
|
|
CMutex m_lock;
|
|
ULONG m_nAllocSize;
|
|
ULONG m_nHeaderSize;
|
|
ULONG m_nSchemaSize;
|
|
CSecurityDesc m_sd;
|
|
};
|
|
|
|
class CPerfLock
|
|
{
|
|
public:
|
|
CPerfLock(CPerfMon* pPerfMon, DWORD dwTimeout = INFINITE)
|
|
{
|
|
ATLENSURE(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;
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// map macros
|
|
|
|
// 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() \
|
|
{ \
|
|
if (pSampleRes) \
|
|
*pSampleRes = 0; \
|
|
ClearMap();
|
|
|
|
#define BEGIN_COUNTER_MAP(categoryclass) \
|
|
public: \
|
|
typedef categoryclass _PerfCounterClass; \
|
|
static HRESULT CreateMap(CPerfMon* pPerf, WORD wLanguage, HINSTANCE hResInstance, UINT* pSampleRes) throw() \
|
|
{ \
|
|
HRESULT hr = RegisterCategory(pPerf, wLanguage, hResInstance, pSampleRes); \
|
|
if (FAILED(hr)) \
|
|
return hr;
|
|
|
|
#define DECLARE_PERF_CATEGORY_EX(dwCategoryId, namestring, helpstring, detail, instanceless, structsize, maxinstnamelen, defcounter) \
|
|
static HRESULT RegisterCategory(CPerfMon* pPerf, WORD wLanguage, HINSTANCE hResInstance, UINT* pSampleRes) throw() \
|
|
{ \
|
|
return pPerf->RegisterCategory(wLanguage, hResInstance, pSampleRes, dwCategoryId, namestring, helpstring, detail, instanceless, structsize, maxinstnamelen, defcounter); \
|
|
} \
|
|
/* NOTE: put a semicolon after your call to DECLARE_PERF_CATEGORY*(...) */ \
|
|
/* this is needed for the code wizards to parse things properly */ \
|
|
static const DWORD kCategoryId = dwCategoryId
|
|
|
|
#define CHAIN_PERF_CATEGORY(categoryclass) \
|
|
if (FAILED(categoryclass::CreateMap(this, wLanguage, hResInstance, pSampleRes))) \
|
|
return E_FAIL;
|
|
|
|
// 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::* ) throw() { }
|
|
template< class C > static void AssertValidFieldType( LONGLONG C::* ) throw() { }
|
|
};
|
|
|
|
#define DEFINE_COUNTER_EX(member, dwCounterId, namestring, helpstring, detail, countertype, maxcountersize, defscale) \
|
|
CAssertValidField< (countertype) & ATLPERF_SIZE_MASK >::AssertValidFieldType( &_PerfCounterClass::member ); \
|
|
hr = pPerf->RegisterCounter(wLanguage, hResInstance, dwCounterId, namestring, helpstring, 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; \
|
|
}
|
|
|
|
#else // _ATL_PERF_REGISTER
|
|
|
|
#define BEGIN_PERF_MAP(AppName) \
|
|
private: \
|
|
LPCTSTR GetAppName() const throw() { return AppName; }
|
|
|
|
#define BEGIN_COUNTER_MAP(objectclass)
|
|
|
|
#define DECLARE_PERF_CATEGORY_EX(dwCategoryId, namestring, helpstring, detail, instanceless, structsize, maxinstnamelen, defcounter) \
|
|
/* NOTE: put a semicolon after your call to DECLARE_PERF_CATEGORY*(...) */ \
|
|
/* this is needed for the code wizards to parse things properly */ \
|
|
static const DWORD kCategoryId = dwCategoryId
|
|
|
|
#define CHAIN_PERF_CATEGORY(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_CATEGORY(objectclass, dwCategoryId, namestring, helpstring, defcounter) \
|
|
DECLARE_PERF_CATEGORY_EX(dwCategoryId, namestring, helpstring, PERF_DETAIL_NOVICE, 0, sizeof(objectclass), ATLPERF_DEFAULT_MAXINSTNAMELENGTH, defcounter)
|
|
#define DECLARE_PERF_CATEGORY_NO_INSTANCES(objectclass, dwCategoryId, namestring, helpstring, defcounter) \
|
|
DECLARE_PERF_CATEGORY_EX(dwCategoryId, 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)
|
|
|
|
#pragma deprecated( DECLARE_PERF_OBJECT_EX )
|
|
#pragma deprecated( DECLARE_PERF_OBJECT )
|
|
#pragma deprecated( DECLARE_PERF_OBJECT_NO_INSTANCES )
|
|
#pragma deprecated( CHAIN_PERF_OBJECT )
|
|
#define DECLARE_PERF_OBJECT_EX DECLARE_PERF_CATEGORY_EX
|
|
#define DECLARE_PERF_OBJECT DECLARE_PERF_CATEGORY
|
|
#define DECLARE_PERF_OBJECT_NO_INSTANCES DECLARE_PERF_CATEGORY_NO_INSTANCES
|
|
#define CHAIN_PERF_OBJECT CHAIN_PERF_CATEGORY
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// automagic registration stuff
|
|
|
|
#if defined(_ATL_PERF_REGISTER) & !defined(_ATL_PERF_NOEXPORT)
|
|
|
|
// define _ATL_PERF_NOEXPORT if you don't want to use the PERFREG map and don't want these
|
|
// functions exported from your DLL
|
|
|
|
// Perf register map stuff
|
|
// this is for ease of integration with the module attribute and for the
|
|
// perfmon wizard
|
|
|
|
#pragma section("ATLP$A", read, shared)
|
|
#pragma section("ATLP$Z", read, shared)
|
|
#pragma section("ATLP$C", read, shared)
|
|
extern "C"
|
|
{
|
|
__declspec(selectany) __declspec(allocate("ATLP$A")) CPerfMon * __pperfA = NULL;
|
|
__declspec(selectany) __declspec(allocate("ATLP$Z")) CPerfMon * __pperfZ = NULL;
|
|
}
|
|
|
|
#if !defined(_M_IA64)
|
|
#pragma comment(linker, "/merge:ATLP=.rdata")
|
|
#endif
|
|
|
|
#if defined(_M_IA64) || defined(_M_AMD64)
|
|
#define ATLPERF_FUNCID_OPEN "OpenPerfMon"
|
|
#define ATLPERF_FUNCID_COLLECT "CollectPerfMon"
|
|
#define ATLPERF_FUNCID_CLOSE "ClosePerfMon"
|
|
#elif defined(_M_IX86)
|
|
#define ATLPERF_FUNCID_OPEN "_OpenPerfMon@4"
|
|
#define ATLPERF_FUNCID_COLLECT "_CollectPerfMon@16"
|
|
#define ATLPERF_FUNCID_CLOSE "_ClosePerfMon@0"
|
|
#else
|
|
#if !defined(ATLPERF_FUNCID_OPEN) || !defined(ATLPERF_FUNCID_COLLECT) || !defined (ATLPERF_FUNCID_CLOSE)
|
|
#error "Unknown platform. Define ATLPERF_FUNCID_OPEN, ATLPERF_FUNCID_COLLECT, ATLPERF_FUNCID_CLOSE"
|
|
#endif
|
|
#endif
|
|
|
|
HRESULT RegisterPerfMon(HINSTANCE hDllInstance = _AtlBaseModule.GetModuleInstance()) throw();
|
|
HRESULT UnregisterPerfMon() throw();
|
|
|
|
extern "C" DWORD __declspec(dllexport) WINAPI OpenPerfMon(LPWSTR lpDeviceNames) throw();
|
|
extern "C" DWORD __declspec(dllexport) WINAPI CollectPerfMon(LPWSTR lpwszValue, LPVOID* lppData,
|
|
LPDWORD lpcbBytes, LPDWORD lpcObjectTypes) throw();
|
|
extern "C" DWORD __declspec(dllexport) WINAPI ClosePerfMon() throw();
|
|
|
|
// this class handles integrating the registration with CComModule
|
|
class _CAtlPerfSetFuncPtr
|
|
{
|
|
public:
|
|
_CAtlPerfSetFuncPtr()
|
|
{
|
|
_pPerfRegFunc = RegisterPerfMon;
|
|
_pPerfUnRegFunc = UnregisterPerfMon;
|
|
}
|
|
};
|
|
|
|
extern "C" { __declspec(selectany) _CAtlPerfSetFuncPtr g_atlperfinit; }
|
|
|
|
#if defined(_M_IX86)
|
|
#pragma comment(linker, "/INCLUDE:_g_atlperfinit")
|
|
#elif defined(_M_IA64) || defined(_M_AMD64)
|
|
#pragma comment(linker, "/INCLUDE:g_atlperfinit")
|
|
#else
|
|
#pragma message("Unknown platform. Make sure the linker includes g_atlperfinit")
|
|
#endif
|
|
|
|
#ifndef PERF_ENTRY_PRAGMA
|
|
|
|
#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));
|
|
#elif defined(_M_AMD64)
|
|
#define PERF_ENTRY_PRAGMA(class) __pragma(comment(linker, "/include:__pperf_" #class));
|
|
#else
|
|
#error Unknown Platform. define PERF_ENTRY_PRAGMA
|
|
#endif
|
|
|
|
#endif // PERF_ENTRY_PRAGMA
|
|
|
|
#define PERFREG_ENTRY(className) \
|
|
__declspec(selectany) className __perf_##className; \
|
|
extern "C" __declspec(allocate("ATLP$C")) __declspec(selectany) CPerfMon * const __pperf_##className = \
|
|
static_cast<CPerfMon*>(&__perf_##className); \
|
|
PERF_ENTRY_PRAGMA(className)
|
|
|
|
#endif // _ATL_PERF_NOEXPORT
|
|
|
|
} // namespace ATL
|
|
|
|
|
|
#include <atlperf.inl>
|
|
|
|
#pragma pack(pop)
|
|
#pragma warning(pop)
|
|
|
|
#endif // __ATLPERF_H__
|