1 // This is a part of the Active Template Library.
2 // Copyright (C) Microsoft Corporation
3 // All rights reserved.
5 // This source code is only intended as a supplement to the
6 // Active Template Library Reference and related
7 // electronic documentation provided with the library.
8 // See these sources for detailed information regarding the
9 // Active Template Library product.
17 #error ATL requires C++ compilation (use a .cpp suffix)
27 #include <atlsecurity.h>
29 #ifndef _ATL_PERF_NOXML
32 #include <xmldomdid.h>
34 /* 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. */
35 #ifdef DISPID_XOBJ_MIN
36 /* in case the HTM one was included first, we'll undef these first */
37 #define _ATL_MSHTMDID_INCLUDED_ALREADY
38 #undef DISPID_XOBJ_MIN
39 #undef DISPID_XOBJ_MAX
40 #undef DISPID_XOBJ_BASE
43 #include <xmldsodid.h>
46 /* re-undef the clashing names, and their direct dependents */
47 #undef DISPID_XOBJ_MIN
48 #undef DISPID_XOBJ_MAX
49 #undef DISPID_XOBJ_BASE
51 #undef DISPID_XMLELEMENTCOLLECTION
53 /* re-def the clashing names, and their direct dependents, with un-clashed values */
54 #define DISPID_XMLDSO_XOBJ_MIN 0x00010000
55 #define DISPID_XMLDSO_XOBJ_MAX 0x0001FFFF
56 #define DISPID_XMLDSO_XOBJ_BASE DISPID_XMLDSO_XOBJ_MIN
57 #define DISPID_XMLDSO DISPID_XMLDSO_XOBJ_BASE
58 #define DISPID_XMLELEMENTCOLLECTION DISPID_XMLDSO_XOBJ_BASE
59 #ifdef _ATL_MSHTMDID_INCLUDED_ALREADY
61 /* redef the clashing names to the HTM values */
62 #define DISPID_XOBJ_MIN 0x80010000
63 #define DISPID_XOBJ_MAX 0x8001FFFF
64 #define DISPID_XOBJ_BASE DISPID_XOBJ_MIN
70 #pragma warning(disable: 4625) // copy constructor could not be generated because a base class copy constructor is inaccessible
71 #pragma warning(disable: 4626) // assignment operator could not be generated because a base class assignment operator is inaccessible
74 #pragma pack(push,_ATL_PACKING)
78 const DWORD ATLPERF_SIZE_MASK
= 0x00000300;
79 const DWORD ATLPERF_TYPE_MASK
= 0x00000C00;
80 const DWORD ATLPERF_TEXT_MASK
= 0x00010000;
82 #ifndef ATLPERF_DEFAULT_MAXINSTNAMELENGTH
83 #define ATLPERF_DEFAULT_MAXINSTNAMELENGTH 64
86 // base class for user-defined perf objects
95 ULONG m_nInstanceNameOffset
; // byte offset from beginning of PerfObject to LPWSTR szInstanceName
101 virtual ~CPerfMon() throw();
103 #ifdef _ATL_PERF_REGISTER
107 LPCTSTR szCollectFunc
,
109 HINSTANCE hDllInstance
= _AtlBaseModule
.GetModuleInstance()) throw();
110 HRESULT
RegisterStrings(
111 LANGID wLanguage
= MAKELANGID(LANG_NEUTRAL
, SUBLANG_NEUTRAL
),
112 HINSTANCE hResInstance
= _AtlBaseModule
.GetResourceInstance()) throw();
113 HRESULT
RegisterAllStrings(HINSTANCE hResInstance
= NULL
) throw();
114 HRESULT
Unregister() throw();
117 HRESULT
Initialize() throw();
118 void UnInitialize() throw();
119 HRESULT
CreateInstance(
122 LPCWSTR szInstanceName
,
123 CPerfObject
** ppInstance
) throw();
124 HRESULT
CreateInstanceByName(
126 LPCWSTR szInstanceName
,
127 CPerfObject
** ppInstance
) throw();
130 HRESULT
CreateInstance(
132 LPCWSTR szInstanceName
,
133 T
** ppInstance
) throw()
135 // Ensure T derives from CPerfObject
136 static_cast<CPerfObject
*>(*ppInstance
);
138 return CreateInstance(
142 reinterpret_cast<CPerfObject
**>(ppInstance
)
147 HRESULT
CreateInstanceByName(
148 LPCWSTR szInstanceName
,
149 T
** ppInstance
) throw()
151 // Ensure T derives from CPerfObject
152 static_cast<CPerfObject
*>(*ppInstance
);
154 return CreateInstanceByName(
157 reinterpret_cast<CPerfObject
**>(ppInstance
)
161 HRESULT
ReleaseInstance(CPerfObject
* pInstance
) throw();
162 HRESULT
LockPerf(DWORD dwTimeout
= INFINITE
) throw();
163 void UnlockPerf() throw();
165 #ifndef _ATL_PERF_NOXML
166 HRESULT
PersistToXML(IStream
*pStream
, BOOL bFirst
=TRUE
, BOOL bLast
=TRUE
) throw(...);
167 HRESULT
LoadFromXML(IStream
*pStream
) throw(...);
173 // PerfMon entry point helpers
174 DWORD
Open(LPWSTR lpDeviceNames
) throw();
175 DWORD
Collect(__in_z LPWSTR lpwszValue
, __deref_inout_bcount(*pcbBytes
) LPVOID
* lppData
, __inout LPDWORD lpcbBytes
, __inout LPDWORD lpcObjectTypes
) throw();
176 DWORD
Close() throw();
178 // map building routines
179 HRESULT
AddCategoryDefinition(
181 LPCTSTR szCategoryName
,
182 LPCTSTR szHelpString
,
187 UINT nMaxInstanceNameLen
= ATLPERF_DEFAULT_MAXINSTNAMELENGTH
) throw();
188 HRESULT
AddCounterDefinition(
190 LPCTSTR szCounterName
,
191 LPCTSTR szHelpString
,
194 ULONG nMaxCounterSize
,
196 INT nDefaultScale
) throw();
199 HRESULT
RegisterCategory(
201 HINSTANCE hResInstance
,
209 UINT nMaxInstanceNameLen
,
210 INT nDefaultCounter
) throw();
211 HRESULT
RegisterCategory(
213 HINSTANCE hResInstance
,
216 LPCTSTR szNameString
,
217 LPCTSTR szHelpString
,
221 UINT nMaxInstanceNameLen
,
222 INT nDefaultCounter
) throw();
223 HRESULT
RegisterCounter(
225 HINSTANCE hResInstance
,
231 ULONG nMaxCounterSize
,
233 INT nDefaultScale
) throw();
234 HRESULT
RegisterCounter(
236 HINSTANCE hResInstance
,
238 LPCTSTR szNameString
,
239 LPCTSTR szHelpString
,
242 ULONG nMaxCounterSize
,
244 INT nDefaultScale
) throw();
247 void ClearMap() throw();
249 virtual LPCTSTR
GetAppName() const throw() = 0;
250 virtual HRESULT
CreateMap(WORD wLanguage
, HINSTANCE hResInstance
, UINT
* pSampleRes
= NULL
) throw();
251 virtual void OnBlockAlloc(CAtlFileMappingBase
* /*pNewBlock*/) { }
252 #ifdef _ATL_PERF_REGISTER
253 static BOOL CALLBACK
EnumResLangProc(HINSTANCE hModule
, LPCTSTR szType
, LPCTSTR szName
, LANGID wIDLanguage
, LPARAM lParam
);
256 // implementation helpers
259 CounterInfo() : m_dwCounterId(0), m_dwDetailLevel(0), m_nNameId(0),
260 m_nHelpId(0), m_dwCounterType(0), m_nDefaultScale(0),
261 m_nMaxCounterSize(0), m_nDataOffset(0)
263 ZeroMemory (&m_cache
, sizeof(m_cache
));
270 DWORD m_dwDetailLevel
;
272 // the ids that correspond to the name and help strings stored in the registry
278 DWORD m_dwCounterType
;
279 LONG m_nDefaultScale
;
281 // the maximum size of the string counter data in characters, including the null terminator
282 // ignored if not a string counter
283 ULONG m_nMaxCounterSize
;
287 // cached data to be copied into request
288 PERF_COUNTER_DEFINITION m_cache
;
295 DWORD m_dwCategoryId
;
298 DWORD m_dwDetailLevel
;
300 // the ids that correspond to the name and help strings stored in the registry
306 LONG m_nDefaultCounter
;
307 LONG m_nInstanceLess
; // PERF_NO_INSTANCES if instanceless
309 // the size of the struct not counting the name and string counters
312 // in characters including the null terminator
313 ULONG m_nMaxInstanceNameLen
;
317 // cached data to be copied into request
318 PERF_OBJECT_TYPE m_cache
;
319 ULONG m_nCounterBlockSize
;
322 UINT
_GetNumCounters() throw();
323 CounterInfo
* _GetCounterInfo(UINT nIndex
) throw();
325 CAtlArray
<CounterInfo
> m_counters
;
328 LPBYTE
_AllocData(LPBYTE
& pData
, ULONG nBytesAvail
, ULONG
* pnBytesUsed
, size_t nBytesNeeded
) throw();
329 template<typename T
> T
* _AllocStruct(LPBYTE
& pData
, ULONG nBytesAvail
, ULONG
* pnBytesUsed
, T
*) throw()
331 return reinterpret_cast<T
*>(_AllocData(pData
, nBytesAvail
, pnBytesUsed
, sizeof(T
)));
334 UINT
_GetNumCategoriesAndCounters() throw();
335 CategoryInfo
* _GetCategoryInfo(UINT nIndex
) throw();
336 UINT
_GetNumCategories() throw();
337 CPerfObject
* _GetFirstInstance(CAtlFileMappingBase
* pBlock
) throw();
338 CPerfObject
* _GetNextInstance(CPerfObject
* pInstance
) throw();
339 CAtlFileMappingBase
* _GetNextBlock(CAtlFileMappingBase
* pBlock
) throw();
340 CAtlFileMappingBase
* _OpenNextBlock(CAtlFileMappingBase
* pPrev
) throw();
341 CAtlFileMappingBase
* _AllocNewBlock(CAtlFileMappingBase
* pPrev
, BOOL
* pbExisted
= NULL
) throw();
342 HRESULT
_OpenAllBlocks() throw();
343 DWORD
& _GetBlockId(CAtlFileMappingBase
* pBlock
) throw(...);
344 DWORD
* _GetBlockId_NoThrow(CAtlFileMappingBase
* pBlock
) throw();
345 CategoryInfo
* _FindCategoryInfo(DWORD dwCategoryId
) throw();
346 CounterInfo
* _FindCounterInfo(CategoryInfo
* pCategoryInfo
, DWORD dwCounterId
) throw();
347 CounterInfo
* _FindCounterInfo(DWORD dwCategoryId
, DWORD dwCounterId
) throw();
348 BOOL
_WantCategoryType(__in_z LPWSTR lpwszValue
, __in DWORD dwPerfId
) throw(...);
349 void _FillCategoryType(CategoryInfo
* pCategoryInfo
) throw();
350 void _FillCounterDef(CounterInfo
* pCounterInfo
, ULONG
* pnCounterBlockSize
) throw();
351 HRESULT
CPerfMon::_CollectInstance(
352 CategoryInfo
* pCategoryInfo
,
356 CPerfObject
* pInstance
,
357 PERF_OBJECT_TYPE
* pObjectType
,
358 PERF_COUNTER_DEFINITION
* pCounterDefs
360 HRESULT
_CollectInstance(
361 CategoryInfo
* pCategoryInfo
,
365 PERF_OBJECT_TYPE
* pObjectType
,
366 PERF_COUNTER_DEFINITION
* pCounterDefs
368 HRESULT
_CollectCategoryType(
369 CategoryInfo
* pCategoryInfo
,
372 ULONG
* pnBytesUsed
) throw();
373 HRESULT
_LoadMap(DWORD
* pData
) throw();
374 HRESULT
_SaveMap() throw();
375 HRESULT
_GetAttribute(
378 BSTR
*pbstrVal
) throw();
379 HRESULT
CPerfMon::_CreateInstance(
382 LPCWSTR szInstanceName
,
383 CPerfObject
** ppInstance
,
384 bool bByName
) throw();
386 #ifdef _ATL_PERF_REGISTER
389 CAtlArray
<CString
>& astrStrings
,
392 HRESULT
_AppendRegStrings(
395 CAtlArray
<CString
>& astrStrings
,
396 ULONG nNewStringSize
,
398 ULONG iLastIndex
) throw();
399 HRESULT
_RemoveRegStrings(
403 ULONG iLastIndex
) throw();
404 HRESULT
_ReserveStringRange(DWORD
& dwFirstCounter
, DWORD
& dwFirstHelp
) throw();
405 HRESULT
_UnregisterStrings() throw();
406 HRESULT
_RegisterAllStrings(UINT nRes
, HINSTANCE hResInstance
) throw();
409 CAtlArray
<CategoryInfo
> m_categories
;
410 CAutoPtrArray
<CAtlFileMappingBase
> m_aMem
;
421 CPerfLock(CPerfMon
* pPerfMon
, DWORD dwTimeout
= INFINITE
)
423 ATLENSURE(pPerfMon
!= NULL
);
424 m_pPerfMon
= pPerfMon
;
425 m_hrStatus
= m_pPerfMon
->LockPerf(dwTimeout
);
430 if (SUCCEEDED(m_hrStatus
))
431 m_pPerfMon
->UnlockPerf();
434 HRESULT
GetStatus() const throw()
440 CPerfMon
* m_pPerfMon
;
444 ////////////////////////////////////////////////////////////////////////
447 // empty definition just for ease of use with code wizards, etc.
448 #define BEGIN_PERFREG_MAP()
450 // empty definition just for ease of use with code wizards, etc.
451 #define END_PERFREG_MAP()
453 #if !defined(_ATL_PERF_REGISTER) | defined(_ATL_PERF_NOEXPORT)
454 #define PERFREG_ENTRY(className)
457 #ifdef _ATL_PERF_REGISTER
458 #define BEGIN_PERF_MAP(AppName) \
460 LPCTSTR GetAppName() const throw() { return AppName; } \
461 HRESULT CreateMap(WORD wLanguage, HINSTANCE hResInstance, UINT* pSampleRes = NULL) throw() \
467 #define BEGIN_COUNTER_MAP(categoryclass) \
469 typedef categoryclass _PerfCounterClass; \
470 static HRESULT CreateMap(CPerfMon* pPerf, WORD wLanguage, HINSTANCE hResInstance, UINT* pSampleRes) throw() \
472 HRESULT hr = RegisterCategory(pPerf, wLanguage, hResInstance, pSampleRes); \
476 #define DECLARE_PERF_CATEGORY_EX(dwCategoryId, namestring, helpstring, detail, instanceless, structsize, maxinstnamelen, defcounter) \
477 static HRESULT RegisterCategory(CPerfMon* pPerf, WORD wLanguage, HINSTANCE hResInstance, UINT* pSampleRes) throw() \
479 return pPerf->RegisterCategory(wLanguage, hResInstance, pSampleRes, dwCategoryId, namestring, helpstring, detail, instanceless, structsize, maxinstnamelen, defcounter); \
481 /* NOTE: put a semicolon after your call to DECLARE_PERF_CATEGORY*(...) */ \
482 /* this is needed for the code wizards to parse things properly */ \
483 static const DWORD kCategoryId = dwCategoryId
485 #define CHAIN_PERF_CATEGORY(categoryclass) \
486 if (FAILED(categoryclass::CreateMap(this, wLanguage, hResInstance, pSampleRes))) \
489 // CAssertValidField ensures that the member variable that's being passed to
490 // DEFINE_COUNTER[_EX] is the proper type. only 32-bit integral types can be used with
491 // PERF_SIZE_DWORD and only 64-bit integral types can be used with PERF_SIZE_LARGE
492 template< DWORD t_dwSize
>
493 class CAssertValidField
498 class CAssertValidField
< PERF_SIZE_DWORD
>
501 template< class C
> static void AssertValidFieldType( ULONG
C::* ) throw() { }
502 template< class C
> static void AssertValidFieldType( LONG
C::* ) throw() { }
506 class CAssertValidField
< PERF_SIZE_LARGE
>
509 template< class C
> static void AssertValidFieldType( ULONGLONG
C::* ) throw() { }
510 template< class C
> static void AssertValidFieldType( LONGLONG
C::* ) throw() { }
513 #define DEFINE_COUNTER_EX(member, dwCounterId, namestring, helpstring, detail, countertype, maxcountersize, defscale) \
514 CAssertValidField< (countertype) & ATLPERF_SIZE_MASK >::AssertValidFieldType( &_PerfCounterClass::member ); \
515 hr = pPerf->RegisterCounter(wLanguage, hResInstance, dwCounterId, namestring, helpstring, detail, countertype, maxcountersize, (ULONG) offsetof(_PerfCounterClass, member), defscale); \
519 #define END_PERF_MAP() \
523 #define END_COUNTER_MAP() \
527 #else // _ATL_PERF_REGISTER
529 #define BEGIN_PERF_MAP(AppName) \
531 LPCTSTR GetAppName() const throw() { return AppName; }
533 #define BEGIN_COUNTER_MAP(objectclass)
535 #define DECLARE_PERF_CATEGORY_EX(dwCategoryId, namestring, helpstring, detail, instanceless, structsize, maxinstnamelen, defcounter) \
536 /* NOTE: put a semicolon after your call to DECLARE_PERF_CATEGORY*(...) */ \
537 /* this is needed for the code wizards to parse things properly */ \
538 static const DWORD kCategoryId = dwCategoryId
540 #define CHAIN_PERF_CATEGORY(objectclass)
541 #define DEFINE_COUNTER_EX(member, dwCounterId, namestring, helpstring, detail, countertype, maxcountersize, defscale)
543 #define END_PERF_MAP()
544 #define END_COUNTER_MAP()
546 #endif // _ATL_PERF_REGISTER
548 #define DECLARE_PERF_CATEGORY(objectclass, dwCategoryId, namestring, helpstring, defcounter) \
549 DECLARE_PERF_CATEGORY_EX(dwCategoryId, namestring, helpstring, PERF_DETAIL_NOVICE, 0, sizeof(objectclass), ATLPERF_DEFAULT_MAXINSTNAMELENGTH, defcounter)
550 #define DECLARE_PERF_CATEGORY_NO_INSTANCES(objectclass, dwCategoryId, namestring, helpstring, defcounter) \
551 DECLARE_PERF_CATEGORY_EX(dwCategoryId, namestring, helpstring, PERF_DETAIL_NOVICE, PERF_NO_INSTANCES, sizeof(objectclass), 0, defcounter)
553 #define DEFINE_COUNTER(member, namestring, helpstring, countertype, defscale) \
554 DEFINE_COUNTER_EX(member, 0, namestring, helpstring, PERF_DETAIL_NOVICE, countertype, 0, defscale)
556 #pragma deprecated( DECLARE_PERF_OBJECT_EX )
557 #pragma deprecated( DECLARE_PERF_OBJECT )
558 #pragma deprecated( DECLARE_PERF_OBJECT_NO_INSTANCES )
559 #pragma deprecated( CHAIN_PERF_OBJECT )
560 #define DECLARE_PERF_OBJECT_EX DECLARE_PERF_CATEGORY_EX
561 #define DECLARE_PERF_OBJECT DECLARE_PERF_CATEGORY
562 #define DECLARE_PERF_OBJECT_NO_INSTANCES DECLARE_PERF_CATEGORY_NO_INSTANCES
563 #define CHAIN_PERF_OBJECT CHAIN_PERF_CATEGORY
565 ////////////////////////////////////////////////////////////////////////
566 // automagic registration stuff
568 #if defined(_ATL_PERF_REGISTER) & !defined(_ATL_PERF_NOEXPORT)
570 // define _ATL_PERF_NOEXPORT if you don't want to use the PERFREG map and don't want these
571 // functions exported from your DLL
573 // Perf register map stuff
574 // this is for ease of integration with the module attribute and for the
577 #pragma section("ATLP$A", read, shared)
578 #pragma section("ATLP$Z", read, shared)
579 #pragma section("ATLP$C", read, shared)
582 __declspec(selectany
) __declspec(allocate("ATLP$A")) CPerfMon
* __pperfA
= NULL
;
583 __declspec(selectany
) __declspec(allocate("ATLP$Z")) CPerfMon
* __pperfZ
= NULL
;
586 #if !defined(_M_IA64)
587 #pragma comment(linker, "/merge:ATLP=.rdata")
590 #if defined(_M_IA64) || defined(_M_AMD64)
591 #define ATLPERF_FUNCID_OPEN "OpenPerfMon"
592 #define ATLPERF_FUNCID_COLLECT "CollectPerfMon"
593 #define ATLPERF_FUNCID_CLOSE "ClosePerfMon"
594 #elif defined(_M_IX86)
595 #define ATLPERF_FUNCID_OPEN "_OpenPerfMon@4"
596 #define ATLPERF_FUNCID_COLLECT "_CollectPerfMon@16"
597 #define ATLPERF_FUNCID_CLOSE "_ClosePerfMon@0"
599 #if !defined(ATLPERF_FUNCID_OPEN) || !defined(ATLPERF_FUNCID_COLLECT) || !defined (ATLPERF_FUNCID_CLOSE)
600 #error "Unknown platform. Define ATLPERF_FUNCID_OPEN, ATLPERF_FUNCID_COLLECT, ATLPERF_FUNCID_CLOSE"
604 HRESULT
RegisterPerfMon(HINSTANCE hDllInstance
= _AtlBaseModule
.GetModuleInstance()) throw();
605 HRESULT
UnregisterPerfMon() throw();
607 extern "C" DWORD
__declspec(dllexport
) WINAPI
OpenPerfMon(LPWSTR lpDeviceNames
) throw();
608 extern "C" DWORD
__declspec(dllexport
) WINAPI
CollectPerfMon(LPWSTR lpwszValue
, LPVOID
* lppData
,
609 LPDWORD lpcbBytes
, LPDWORD lpcObjectTypes
) throw();
610 extern "C" DWORD
__declspec(dllexport
) WINAPI
ClosePerfMon() throw();
612 // this class handles integrating the registration with CComModule
613 class _CAtlPerfSetFuncPtr
616 _CAtlPerfSetFuncPtr()
618 _pPerfRegFunc
= RegisterPerfMon
;
619 _pPerfUnRegFunc
= UnregisterPerfMon
;
623 extern "C" { __declspec(selectany
) _CAtlPerfSetFuncPtr g_atlperfinit
; }
626 #pragma comment(linker, "/INCLUDE:_g_atlperfinit")
627 #elif defined(_M_IA64) || defined(_M_AMD64)
628 #pragma comment(linker, "/INCLUDE:g_atlperfinit")
630 #pragma message("Unknown platform. Make sure the linker includes g_atlperfinit")
633 #ifndef PERF_ENTRY_PRAGMA
636 #define PERF_ENTRY_PRAGMA(class) __pragma(comment(linker, "/include:___pperf_" #class));
637 #elif defined(_M_IA64)
638 #define PERF_ENTRY_PRAGMA(class) __pragma(comment(linker, "/include:__pperf_" #class));
639 #elif defined(_M_AMD64)
640 #define PERF_ENTRY_PRAGMA(class) __pragma(comment(linker, "/include:__pperf_" #class));
642 #error Unknown Platform. define PERF_ENTRY_PRAGMA
645 #endif // PERF_ENTRY_PRAGMA
647 #define PERFREG_ENTRY(className) \
648 __declspec(selectany) className __perf_##className; \
649 extern "C" __declspec(allocate("ATLP$C")) __declspec(selectany) CPerfMon * const __pperf_##className = \
650 static_cast<CPerfMon*>(&__perf_##className); \
651 PERF_ENTRY_PRAGMA(className)
653 #endif // _ATL_PERF_NOEXPORT
658 #include <atlperf.inl>
663 #endif // __ATLPERF_H__