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

  1. // This is a part of the Active Template Library.
  2. // Copyright (C) 1996-2001 Microsoft Corporation
  3. // All rights reserved.
  4. //
  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.
  10. #ifndef __ATLPERF_H__
  11. #define __ATLPERF_H__
  12. #pragma once
  13. #ifndef __cplusplus
  14. #error ATL requires C++ compilation (use a .cpp suffix)
  15. #endif
  16. #include <atlbase.h>
  17. #include <atlcom.h>
  18. #include <atlstr.h>
  19. #include <atlfile.h>
  20. #include <atlsync.h>
  21. #include <winperf.h>
  22. #include <atlcoll.h>
  23. #ifndef _ATL_PERF_NOXML
  24. #include <atlenc.h>
  25. #include <oaidl.h>
  26. #include <xmldomdid.h>
  27. #include <xmldsodid.h>
  28. #include <msxmldid.h>
  29. #include <msxml.h>
  30. #endif
  31. namespace ATL
  32. {
  33. const DWORD ATLPERF_SIZE_MASK = 0x00000300;
  34. const DWORD ATLPERF_TYPE_MASK = 0x00000C00;
  35. const DWORD ATLPERF_TEXT_MASK = 0x00010000;
  36. #ifndef ATLPERF_DEFAULT_MAXINSTNAMELENGTH
  37. #define ATLPERF_DEFAULT_MAXINSTNAMELENGTH 64
  38. #endif
  39. // base class for user-defined perf objects
  40. struct CPerfObject
  41. {
  42. ULONG m_nAllocSize;
  43. DWORD m_dwObjectId;
  44. DWORD m_dwInstance;
  45. ULONG m_nRefCount;
  46. ULONG m_nInstanceNameOffset; // byte offset from beginning of PerfObject to LPWSTR szInstanceName
  47. };
  48. struct CPerfMapEntry
  49. {
  50. DWORD m_dwPerfId;
  51. CString m_strName;
  52. CString m_strHelp;
  53. DWORD m_dwDetailLevel;
  54. BOOL m_bIsObject;
  55. // OBJECT INFO
  56. ULONG m_nNumCounters;
  57. LONG m_nDefaultCounter;
  58. LONG m_nInstanceLess; // PERF_NO_INSTANCES if instanceless
  59. // the size of the struct not counting the name and string counters
  60. ULONG m_nStructSize;
  61. // in characters including the null terminator
  62. ULONG m_nMaxInstanceNameLen;
  63. ULONG m_nAllocSize;
  64. // COUNTER INFO
  65. DWORD m_dwCounterType;
  66. LONG m_nDefaultScale;
  67. // the maximum size of the string counter data in characters, including the null terminator
  68. // ignored if not a string counter
  69. ULONG m_nMaxCounterSize;
  70. ULONG m_nDataOffset;
  71. // the ids that correspond to the name and help strings stored in the registry
  72. UINT m_nNameId;
  73. UINT m_nHelpId;
  74. };
  75. class CPerfMon
  76. {
  77. public:
  78. ~CPerfMon() throw();
  79. // PerfMon entry point helpers
  80. DWORD Open(LPWSTR lpDeviceNames) throw();
  81. DWORD Collect(LPWSTR lpwszValue, LPVOID* lppData, LPDWORD lpcbBytes, LPDWORD lpcObjectTypes) throw();
  82. DWORD Close() throw();
  83. #ifdef _ATL_PERF_REGISTER
  84. // registration
  85. HRESULT Register(
  86. LPCTSTR szOpenFunc,
  87. LPCTSTR szCollectFunc,
  88. LPCTSTR szCloseFunc,
  89. HINSTANCE hDllInstance = _AtlBaseModule.GetModuleInstance()) throw();
  90. HRESULT RegisterStrings(
  91. LANGID wLanguage = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
  92. HINSTANCE hResInstance = _AtlBaseModule.GetResourceInstance()) throw();
  93. HRESULT RegisterAllStrings(HINSTANCE hResInstance = NULL) throw();
  94. HRESULT Unregister() throw();
  95. static BOOL CALLBACK EnumResLangProc(HINSTANCE hModule, LPCTSTR szType, LPCTSTR szName, LANGID wIDLanguage, LPARAM lParam);
  96. #endif
  97. HRESULT Initialize() throw();
  98. void UnInitialize() throw();
  99. HRESULT CreateInstance(
  100. DWORD dwObjectId,
  101. DWORD dwInstance,
  102. LPCWSTR szInstanceName,
  103. CPerfObject** ppInstance) throw();
  104. HRESULT CreateInstanceByName(
  105. DWORD dwObjectId,
  106. LPCWSTR szInstanceName,
  107. CPerfObject** ppInstance) throw();
  108. template <class T>
  109. HRESULT CreateInstance(
  110. DWORD dwInstance,
  111. LPCWSTR szInstanceName,
  112. T** ppInstance) throw()
  113. {
  114. // Ensure T derives from CPerfObject
  115. static_cast<CPerfObject*>(*ppInstance);
  116. return CreateInstance(
  117. T::kObjectId,
  118. dwInstance,
  119. szInstanceName,
  120. reinterpret_cast<CPerfObject**>(ppInstance)
  121. );
  122. }
  123. template <class T>
  124. HRESULT CreateInstanceByName(
  125. LPCWSTR szInstanceName,
  126. T** ppInstance) throw()
  127. {
  128. // Ensure T derives from CPerfObject
  129. static_cast<CPerfObject*>(*ppInstance);
  130. return CreateInstanceByName(
  131. T::kObjectId,
  132. szInstanceName,
  133. reinterpret_cast<CPerfObject**>(ppInstance)
  134. );
  135. }
  136. HRESULT ReleaseInstance(CPerfObject* pInstance) throw();
  137. HRESULT LockPerf(DWORD dwTimeout = INFINITE) throw();
  138. void UnlockPerf() throw();
  139. // map building routines
  140. HRESULT AddObjectDefinition(
  141. DWORD dwObjectId,
  142. LPCTSTR szObjectName,
  143. LPCTSTR szHelpString,
  144. DWORD dwDetailLevel,
  145. INT nDefaultCounter,
  146. BOOL bInstanceLess,
  147. UINT nStructSize,
  148. UINT nMaxInstanceNameLen = ATLPERF_DEFAULT_MAXINSTNAMELENGTH) throw();
  149. HRESULT AddCounterDefinition(
  150. DWORD dwCounterId,
  151. LPCTSTR szCounterName,
  152. LPCTSTR szHelpString,
  153. DWORD dwDetailLevel,
  154. DWORD dwCounterType,
  155. ULONG nMaxCounterSize,
  156. UINT nOffset,
  157. INT nDefaultScale) throw();
  158. void ClearMap() throw();
  159. #ifndef _ATL_PERF_NOXML
  160. HRESULT PersistToXML(IStream *pStream, BOOL bFirst=TRUE, BOOL bLast=TRUE) throw(...);
  161. HRESULT LoadFromXML(IStream *pStream) throw(...);
  162. #endif
  163. protected:
  164. virtual LPCTSTR GetAppName() const throw() = 0;
  165. virtual HRESULT CreateMap(WORD wLanguage, HINSTANCE hResInstance, UINT* pSampleRes = NULL) throw();
  166. virtual void OnBlockAlloc(CAtlFileMappingBase* /*pNewBlock*/) { }
  167. // implementation helpers
  168. LPBYTE _AllocData(LPBYTE& pData, ULONG nBytesAvail, ULONG* pnBytesUsed, size_t nBytesNeeded) throw();
  169. template<typename T> T* _AllocStruct(LPBYTE& pData, ULONG nBytesAvail, ULONG* pnBytesUsed, T*) throw()
  170. {
  171. return reinterpret_cast<T*>(_AllocData(pData, nBytesAvail, pnBytesUsed, sizeof(T)));
  172. }
  173. CPerfMapEntry& _GetMapEntry(UINT nIndex) throw();
  174. UINT _GetNumMapEntries() throw();
  175. CPerfObject* _GetFirstObject(CAtlFileMappingBase* pBlock) throw();
  176. CPerfObject* _GetNextObject(CPerfObject* pInstance) throw();
  177. CAtlFileMappingBase* _GetNextBlock(CAtlFileMappingBase* pBlock) throw();
  178. CAtlFileMappingBase* _AllocNewBlock(CAtlFileMappingBase* pPrev, BOOL* pbExisted = NULL) throw();
  179. DWORD& _GetBlockId(CAtlFileMappingBase* pBlock) throw();
  180. CPerfMapEntry* _FindObjectInfo(DWORD dwObjectId) throw();
  181. CPerfMapEntry* _FindCounterInfo(CPerfMapEntry* pObjectEntry, DWORD dwCounterId) throw();
  182. CPerfMapEntry* _FindCounterInfo(DWORD dwObjectId, DWORD dwCounterId) throw();
  183. BOOL _WantObjectType(LPWSTR lpwszValue, DWORD dwPerfId) throw(...);
  184. void _FillObjectType(PERF_OBJECT_TYPE* pObjectType, CPerfMapEntry* pObjectEntry) throw();
  185. void _FillCounterDef(
  186. PERF_COUNTER_DEFINITION* pCounterDef,
  187. CPerfMapEntry* pCounterEntry,
  188. ULONG& nCBSize) throw();
  189. HRESULT _CollectObjectType(
  190. CPerfMapEntry* pObjectEntry,
  191. LPBYTE pData,
  192. ULONG nBytesAvail,
  193. ULONG* pnBytesUsed) throw();
  194. HRESULT _LoadMap() throw();
  195. HRESULT _SaveMap() throw();
  196. HRESULT _GetAttribute(
  197. IXMLDOMNode *pNode,
  198. LPCWSTR szAttrName,
  199. BSTR *pbstrVal) throw();
  200. HRESULT CPerfMon::_CreateInstance(
  201. DWORD dwObjectId,
  202. DWORD dwInstance,
  203. LPCWSTR szInstanceName,
  204. CPerfObject** ppInstance,
  205. bool bByName) throw();
  206. #ifdef _ATL_PERF_REGISTER
  207. void _AppendStrings(
  208. LPTSTR& pszNew,
  209. CAtlArray<CString>& astrStrings,
  210. ULONG iFirstIndex
  211. ) throw();
  212. HRESULT _AppendRegStrings(
  213. CRegKey& rkLang,
  214. LPCTSTR szValue,
  215. CAtlArray<CString>& astrStrings,
  216. ULONG nNewStringSize,
  217. ULONG iFirstIndex,
  218. ULONG iLastIndex) throw();
  219. HRESULT _RemoveRegStrings(
  220. CRegKey& rkLang,
  221. LPCTSTR szValue,
  222. ULONG iFirstIndex,
  223. ULONG iLastIndex) throw();
  224. HRESULT _ReserveStringRange(DWORD& dwFirstCounter, DWORD& dwFirstHelp) throw();
  225. HRESULT _UnregisterStrings() throw();
  226. HRESULT _RegisterAllStrings(UINT nRes, HINSTANCE hResInstance) throw();
  227. #endif
  228. private:
  229. CAtlArray<CPerfMapEntry> m_map;
  230. CAutoPtrArray<CAtlFileMappingBase> m_aMem;
  231. CMutex m_lock;
  232. ULONG m_nAllocSize;
  233. ULONG m_nHeaderSize;
  234. ULONG m_nSchemaSize;
  235. ULONG m_nNumObjectTypes;
  236. };
  237. class CPerfLock
  238. {
  239. public:
  240. CPerfLock(CPerfMon* pPerfMon, DWORD dwTimeout = INFINITE) throw()
  241. {
  242. ATLASSERT(pPerfMon != NULL);
  243. m_pPerfMon = pPerfMon;
  244. m_hrStatus = m_pPerfMon->LockPerf(dwTimeout);
  245. }
  246. ~CPerfLock() throw()
  247. {
  248. if (SUCCEEDED(m_hrStatus))
  249. m_pPerfMon->UnlockPerf();
  250. }
  251. HRESULT GetStatus() const throw()
  252. {
  253. return m_hrStatus;
  254. }
  255. private:
  256. CPerfMon* m_pPerfMon;
  257. HRESULT m_hrStatus;
  258. };
  259. // empty definition just for ease of use with code wizards, etc.
  260. #define BEGIN_PERFREG_MAP()
  261. // empty definition just for ease of use with code wizards, etc.
  262. #define END_PERFREG_MAP()
  263. #if !defined(_ATL_PERF_REGISTER) | defined(_ATL_PERF_NOEXPORT)
  264. #define PERFREG_ENTRY(className)
  265. #endif
  266. #ifdef _ATL_PERF_REGISTER
  267. #define BEGIN_PERF_MAP(AppName) \
  268. private: \
  269. LPCTSTR GetAppName() const throw() { return AppName; } \
  270. HRESULT CreateMap(WORD wLanguage, HINSTANCE hResInstance, UINT* pSampleRes = NULL) throw() \
  271. { \
  272. CPerfMon* pPerf = this; \
  273. wLanguage; \
  274. hResInstance; \
  275. if (pSampleRes) \
  276. *pSampleRes = 0; \
  277. CString strName; \
  278. CString strHelp; \
  279. HRESULT hr; \
  280. ClearMap();
  281. #define BEGIN_COUNTER_MAP(objectclass) \
  282. public: \
  283. typedef objectclass _PerfCounterClass; \
  284. static HRESULT CreateMap(CPerfMon* pPerf, WORD wLanguage, HINSTANCE hResInstance, UINT* pSampleRes) throw() \
  285. { \
  286. wLanguage; \
  287. hResInstance; \
  288. pSampleRes; \
  289. CString strName; \
  290. CString strHelp; \
  291. HRESULT hr; \
  292. hr = RegisterObject(pPerf, wLanguage, hResInstance, pSampleRes); \
  293. if (FAILED(hr)) \
  294. return hr;
  295. #define DECLARE_PERF_OBJECT_EX(dwObjectId, namestring, helpstring, detail, instanceless, structsize, maxinstnamelen, defcounter) \
  296. static HRESULT RegisterObject(CPerfMon* pPerf, WORD wLanguage, HINSTANCE hResInstance, UINT* pSampleRes) throw() \
  297. { \
  298. CString strName; \
  299. CString strHelp; \
  300. HRESULT hr; \
  301. _ATLTRY \
  302. { \
  303. if (IS_INTRESOURCE(namestring)) \
  304. { \
  305. ATLASSERT(IS_INTRESOURCE(helpstring)); \
  306. if (pSampleRes) \
  307. *pSampleRes = (UINT) (UINT_PTR) namestring; \
  308. if (hResInstance && !strName.LoadString(hResInstance, (UINT) (UINT_PTR) namestring, wLanguage)) \
  309. return E_FAIL; \
  310. if (hResInstance && !strHelp.LoadString(hResInstance, (UINT) (UINT_PTR) helpstring, wLanguage)) \
  311. return E_FAIL; \
  312. } \
  313. else \
  314. { \
  315. ATLASSERT(!IS_INTRESOURCE(helpstring)); \
  316. strName = (LPCTSTR) namestring; \
  317. strHelp = (LPCTSTR) helpstring; \
  318. } \
  319. } \
  320. _ATLCATCHALL() \
  321. { \
  322. return E_FAIL; \
  323. } \
  324. hr = pPerf->AddObjectDefinition(dwObjectId, strName, strHelp, detail, defcounter, instanceless, (ULONG) structsize, maxinstnamelen); \
  325. if (FAILED(hr)) \
  326. return hr; \
  327. return S_OK; \
  328. } \
  329. /* NOTE: put a semicolon after your call to DECLARE_PERF_OBJECT*(...) */ \
  330. /* this is needed for the code wizards to parse things properly */ \
  331. static const DWORD kObjectId = dwObjectId
  332. #define CHAIN_PERF_OBJECT(objectclass) \
  333. hr = objectclass::CreateMap(pPerf, wLanguage, hResInstance, pSampleRes); \
  334. if (FAILED(hr)) \
  335. return hr;
  336. // CAssertValidField ensures that the member variable that's being passed to
  337. // DEFINE_COUNTER[_EX] is the proper type. only 32-bit integral types can be used with
  338. // PERF_SIZE_DWORD and only 64-bit integral types can be used with PERF_SIZE_LARGE
  339. template< DWORD t_dwSize >
  340. class CAssertValidField
  341. {
  342. };
  343. template<>
  344. class CAssertValidField< PERF_SIZE_DWORD >
  345. {
  346. public:
  347. template< class C > static void AssertValidFieldType( ULONG C::* ) throw() { }
  348. template< class C > static void AssertValidFieldType( LONG C::* ) throw() { }
  349. };
  350. template<>
  351. class CAssertValidField< PERF_SIZE_LARGE >
  352. {
  353. public:
  354. template< class C > static void AssertValidFieldType( ULONGLONG C::* p ) throw() { }
  355. template< class C > static void AssertValidFieldType( LONGLONG C::* p ) throw() { }
  356. };
  357. #define DEFINE_COUNTER_EX(member, dwCounterId, namestring, helpstring, detail, countertype, maxcountersize, defscale) \
  358. CAssertValidField< (countertype) & ATLPERF_SIZE_MASK >::AssertValidFieldType( &_PerfCounterClass::member ); \
  359. _ATLTRY \
  360. { \
  361. if (IS_INTRESOURCE(namestring)) \
  362. { \
  363. ATLASSERT(IS_INTRESOURCE(helpstring)); \
  364. if (hResInstance && !strName.LoadString(hResInstance, (UINT) (UINT_PTR) namestring, wLanguage)) \
  365. return E_FAIL; \
  366. if (hResInstance && !strHelp.LoadString(hResInstance, (UINT) (UINT_PTR) helpstring, wLanguage)) \
  367. return E_FAIL; \
  368. } \
  369. else \
  370. { \
  371. ATLASSERT(!IS_INTRESOURCE(helpstring)); \
  372. strName = (LPCTSTR) namestring; \
  373. strHelp = (LPCTSTR) helpstring; \
  374. } \
  375. } \
  376. _ATLCATCHALL() \
  377. { \
  378. return E_FAIL; \
  379. } \
  380. hr = pPerf->AddCounterDefinition(dwCounterId, strName, strHelp, detail, countertype, maxcountersize, (ULONG) offsetof(_PerfCounterClass, member), defscale); \
  381. if (FAILED(hr)) \
  382. return hr;
  383. #define END_PERF_MAP() \
  384. return S_OK; \
  385. }
  386. #define END_COUNTER_MAP() \
  387. return S_OK; \
  388. }
  389. // define _ATL_PERF_NOEXPORT if you don't want to use the PERFREG map and don't want these
  390. // functions exported from your DLL
  391. #ifndef _ATL_PERF_NOEXPORT
  392. // Perf register map stuff
  393. // this is for ease of integration with the module attribute and for the
  394. // perfmon wizard
  395. #pragma data_seg(push)
  396. #pragma data_seg("ATLP$A")
  397. __declspec(selectany) CPerfMon * __pperfA = NULL;
  398. #pragma data_seg("ATLP$Z")
  399. __declspec(selectany) CPerfMon * __pperfZ = NULL;
  400. #pragma data_seg("ATLP$C")
  401. #pragma data_seg(pop)
  402. ATL_NOINLINE inline HRESULT RegisterPerfMon(HINSTANCE hDllInstance = _AtlBaseModule.GetModuleInstance()) throw()
  403. {
  404. CPerfMon **ppPerf = &__pperfA;
  405. HRESULT hr = S_OK;
  406. while (ppPerf != &__pperfZ)
  407. {
  408. if (*ppPerf != NULL)
  409. {
  410. hr = (*ppPerf)->Register(_T("_OpenPerfMon"), _T("_CollectPerfMon"), _T("_ClosePerfMon"), hDllInstance);
  411. if (FAILED(hr))
  412. return hr;
  413. hr = (*ppPerf)->RegisterAllStrings(hDllInstance);
  414. if (FAILED(hr))
  415. return hr;
  416. }
  417. ppPerf++;
  418. }
  419. return S_OK;
  420. }
  421. ATL_NOINLINE inline HRESULT UnregisterPerfMon() throw()
  422. {
  423. CPerfMon **ppPerf = &__pperfA;
  424. HRESULT hr = S_OK;
  425. while (ppPerf != &__pperfZ)
  426. {
  427. if (*ppPerf != NULL)
  428. {
  429. hr = (*ppPerf)->Unregister();
  430. if (FAILED(hr))
  431. return hr;
  432. }
  433. ppPerf++;
  434. }
  435. return S_OK;
  436. }
  437. extern "C" ATL_NOINLINE inline DWORD __declspec(dllexport) WINAPI OpenPerfMon(LPWSTR lpDeviceNames) throw()
  438. {
  439. CPerfMon **ppPerf = &__pperfA;
  440. DWORD dwErr = 0;
  441. while (ppPerf != &__pperfZ)
  442. {
  443. if (*ppPerf != NULL)
  444. {
  445. dwErr = (*ppPerf)->Open(lpDeviceNames);
  446. if (dwErr != 0)
  447. return dwErr;
  448. }
  449. ppPerf++;
  450. }
  451. return 0;
  452. }
  453. extern "C" ATL_NOINLINE inline DWORD __declspec(dllexport) WINAPI CollectPerfMon(LPWSTR lpwszValue, LPVOID* lppData,
  454. LPDWORD lpcbBytes, LPDWORD lpcObjectTypes) throw()
  455. {
  456. DWORD dwOrigBytes = *lpcbBytes;
  457. DWORD dwBytesRemaining = *lpcbBytes;
  458. CPerfMon **ppPerf = &__pperfA;
  459. DWORD dwErr = 0;
  460. while (ppPerf != &__pperfZ)
  461. {
  462. if (*ppPerf != NULL)
  463. {
  464. dwErr = (*ppPerf)->Collect(lpwszValue, lppData, lpcbBytes, lpcObjectTypes);
  465. if (dwErr != 0)
  466. return dwErr;
  467. dwBytesRemaining -= *lpcbBytes;
  468. *lpcbBytes = dwBytesRemaining;
  469. }
  470. ppPerf++;
  471. }
  472. *lpcbBytes = dwOrigBytes - dwBytesRemaining;
  473. return 0;
  474. }
  475. extern "C" ATL_NOINLINE inline DWORD __declspec(dllexport) WINAPI ClosePerfMon() throw()
  476. {
  477. CPerfMon **ppPerf = &__pperfA;
  478. while (ppPerf != &__pperfZ)
  479. {
  480. if (*ppPerf != NULL)
  481. {
  482. (*ppPerf)->Close();
  483. }
  484. ppPerf++;
  485. }
  486. return 0;
  487. }
  488. // this class handles integrating the registration with CComModule
  489. class _CAtlPerfSetFuncPtr
  490. {
  491. public:
  492. _CAtlPerfSetFuncPtr()
  493. {
  494. _pPerfRegFunc = RegisterPerfMon;
  495. _pPerfUnRegFunc = UnregisterPerfMon;
  496. }
  497. };
  498. extern "C" { __declspec(selectany) _CAtlPerfSetFuncPtr g_atlperfinit; }
  499. #pragma comment(linker, "/INCLUDE:_g_atlperfinit")
  500. #if defined(_M_IX86)
  501. #define PERF_ENTRY_PRAGMA(class) __pragma(comment(linker, "/include:___pperf_" #class))
  502. #elif defined(_M_IA64)
  503. #define PERF_ENTRY_PRAGMA(class) __pragma(comment(linker, "/include:__pperf_" #class))
  504. #else
  505. #error Unknown Platform. define PERF_ENTRY_PRAGMA
  506. #endif
  507. #define PERFREG_ENTRY(className) \
  508. className __perf_##className; \
  509. extern "C" __declspec(allocate("ATLP$C")) CPerfMon * __pperf_##className = \
  510. static_cast<CPerfMon*>(&__perf_##className); \
  511. PERF_ENTRY_PRAGMA(className)
  512. #endif // _ATL_PERF_NOEXPORT
  513. #else // _ATL_PERF_REGISTER
  514. #define BEGIN_PERF_MAP(AppName) \
  515. private: \
  516. LPCTSTR GetAppName() const throw() { return AppName; }
  517. #define BEGIN_COUNTER_MAP(objectclass)
  518. #define DECLARE_PERF_OBJECT_EX(dwObjectId, namestring, helpstring, detail, instanceless, structsize, maxinstnamelen, defcounter) \
  519. /* NOTE: put a semicolon after your call to DECLARE_PERF_OBJECT*(...) */ \
  520. /* this is needed for the code wizards to parse things properly */ \
  521. static const DWORD kObjectId = dwObjectId
  522. #define CHAIN_PERF_OBJECT(objectclass)
  523. #define DEFINE_COUNTER_EX(member, dwCounterId, namestring, helpstring, detail, countertype, maxcountersize, defscale)
  524. #define END_PERF_MAP()
  525. #define END_COUNTER_MAP()
  526. #endif // _ATL_PERF_REGISTER
  527. #define DECLARE_PERF_OBJECT(objectclass, dwObjectId, namestring, helpstring, defcounter) \
  528. DECLARE_PERF_OBJECT_EX(dwObjectId, namestring, helpstring, PERF_DETAIL_NOVICE, 0, sizeof(objectclass), ATLPERF_DEFAULT_MAXINSTNAMELENGTH, defcounter)
  529. #define DECLARE_PERF_OBJECT_NO_INSTANCES(objectclass, dwObjectId, namestring, helpstring, defcounter) \
  530. DECLARE_PERF_OBJECT_EX(dwObjectId, namestring, helpstring, PERF_DETAIL_NOVICE, PERF_NO_INSTANCES, sizeof(objectclass), 0, defcounter)
  531. #define DEFINE_COUNTER(member, namestring, helpstring, countertype, defscale) \
  532. DEFINE_COUNTER_EX(member, 0, namestring, helpstring, PERF_DETAIL_NOVICE, countertype, 0, defscale)
  533. } // namespace ATL
  534. #include <atlperf.inl>
  535. #endif // __ATLPERF_H__