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.

565 lines
14 KiB

  1. // ShowPerfLibDlg.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "ShowPerfLib.h"
  5. #include "ShowPerfLibDlg.h"
  6. #include "PerfSelection.h"
  7. #include "ntreg.h"
  8. #include "listperf.h"
  9. #ifdef _DEBUG
  10. #define new DEBUG_NEW
  11. #undef THIS_FILE
  12. static char THIS_FILE[] = __FILE__;
  13. #endif
  14. /////////////////////////////////////////////////////////////////////////////
  15. // CShowPerfLibDlg dialog
  16. CShowPerfLibDlg::CShowPerfLibDlg(CWnd* pParent /*=NULL*/)
  17. : CDialog(CShowPerfLibDlg::IDD, pParent)
  18. {
  19. //{{AFX_DATA_INIT(CShowPerfLibDlg)
  20. m_strRequest = _T("");
  21. //}}AFX_DATA_INIT
  22. // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
  23. m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  24. m_strService = _T("");
  25. }
  26. CShowPerfLibDlg::CShowPerfLibDlg(CString strService, BOOL bRefCheck, CWnd* pParent /*=NULL*/)
  27. : m_strService( strService ), m_bRefCheck(bRefCheck), CDialog(CShowPerfLibDlg::IDD, pParent)
  28. {
  29. m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  30. }
  31. CShowPerfLibDlg::~CShowPerfLibDlg()
  32. {
  33. CloseLibrary();
  34. FreeLibrary( m_hLib );
  35. }
  36. void CShowPerfLibDlg::DoDataExchange(CDataExchange* pDX)
  37. {
  38. CDialog::DoDataExchange(pDX);
  39. //{{AFX_DATA_MAP(CShowPerfLibDlg)
  40. DDX_Control(pDX, IDC_GET_COUNTER, m_wndGetCounter);
  41. DDX_Control(pDX, IDC_ERRORS, m_wndErrorLog);
  42. DDX_Control(pDX, IDC_PERFTREE, m_wndPerfTree);
  43. DDX_Text(pDX, IDC_REQUEST, m_strRequest);
  44. //}}AFX_DATA_MAP
  45. }
  46. BEGIN_MESSAGE_MAP(CShowPerfLibDlg, CDialog)
  47. //{{AFX_MSG_MAP(CShowPerfLibDlg)
  48. ON_WM_PAINT()
  49. ON_WM_QUERYDRAGICON()
  50. ON_EN_CHANGE(IDC_REQUEST, OnChangeRequest)
  51. ON_BN_CLICKED(IDC_GET_COUNTER, OnGetCounter)
  52. //}}AFX_MSG_MAP
  53. END_MESSAGE_MAP()
  54. ///////////// ////////////////////////////////////////////////////////////////
  55. // CShowPerfLibDlg message handlers
  56. BOOL CShowPerfLibDlg::OnInitDialog()
  57. {
  58. CDialog::OnInitDialog();
  59. // Set the icon for this dialog. The framework does this automatically
  60. // when the application's main window is not a dialog
  61. // SetIcon(m_hIcon, TRUE); // Set big icon
  62. // SetIcon(m_hIcon, FALSE); // Set small icon
  63. SetWindowText( m_strService );
  64. int nCol;
  65. nCol = m_wndErrorLog.InsertColumn(0, "Type", LVCFMT_LEFT, 75 );
  66. nCol = m_wndErrorLog.InsertColumn(1, "Description", LVCFMT_LEFT, 500 );
  67. InitPerfLibTree();
  68. return TRUE; // return TRUE unless you set the focus to a control
  69. }
  70. // If you add a minimize button to your dialog, you will need the code below
  71. // to draw the icon. For MFC applications using the document/view model,
  72. // this is automatically done for you by the framework.
  73. void CShowPerfLibDlg::OnPaint()
  74. {
  75. if (IsIconic())
  76. {
  77. CPaintDC dc(this); // device context for painting
  78. SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
  79. // Center icon in client rectangle
  80. int cxIcon = GetSystemMetrics(SM_CXICON);
  81. int cyIcon = GetSystemMetrics(SM_CYICON);
  82. CRect rect;
  83. GetClientRect(&rect);
  84. int x = (rect.Width() - cxIcon + 1) / 2;
  85. int y = (rect.Height() - cyIcon + 1) / 2;
  86. // Draw the icon
  87. dc.DrawIcon(x, y, m_hIcon);
  88. }
  89. else
  90. {
  91. CDialog::OnPaint();
  92. }
  93. }
  94. // The system calls this to obtain the cursor to display while the user drags
  95. // the minimized window.
  96. HCURSOR CShowPerfLibDlg::OnQueryDragIcon()
  97. {
  98. return (HCURSOR) m_hIcon;
  99. }
  100. /////////////////////////////////////////////////////////////////////////////
  101. //
  102. // Perf Lib methods
  103. //
  104. /////////////////////////////////////////////////////////////////////////////
  105. BOOL CShowPerfLibDlg::InitPerfLibTree()
  106. {
  107. BOOL bRet = TRUE;
  108. CWaitCursor wc;
  109. if (InitService())
  110. {
  111. if ( OpenLibrary() )
  112. {
  113. bRet = GetData();
  114. }
  115. }
  116. return bRet;
  117. }
  118. BOOL CShowPerfLibDlg::InitService()
  119. {
  120. BOOL bRet = TRUE;
  121. CNTRegistry Reg;
  122. WCHAR wszKey[128];
  123. char szLog[256];
  124. swprintf(wszKey, L"SYSTEM\\CurrentControlSet\\Services\\%S\\Performance", m_strService);
  125. if ( CNTRegistry::no_error == Reg.Open( HKEY_LOCAL_MACHINE, wszKey ) )
  126. {
  127. WCHAR* wszTemp;
  128. Reg.GetStr(L"Library", &wszTemp);
  129. m_strPerfLib = wszTemp;
  130. delete [] wszTemp;
  131. sprintf(szLog, "Library Name: %s", m_strPerfLib);
  132. Log( PERF_INFO, szLog );
  133. Reg.GetStr(L"Open", &wszTemp);
  134. m_strOpen = wszTemp;
  135. delete [] wszTemp;
  136. sprintf(szLog, "Open Function Name: %s", m_strOpen);
  137. Log( PERF_INFO, szLog );
  138. Reg.GetStr(L"Collect", &wszTemp);
  139. m_strCollect = wszTemp;
  140. delete [] wszTemp;
  141. sprintf(szLog, "Collect Function Name: %s", m_strCollect);
  142. Log( PERF_INFO, szLog );
  143. Reg.GetStr(L"Close", &wszTemp);
  144. m_strClose = wszTemp;
  145. delete [] wszTemp;
  146. sprintf(szLog, "Close Function Name: %s", m_strClose);
  147. Log( PERF_INFO, szLog );
  148. }
  149. else
  150. {
  151. sprintf(szLog, "Counld not open the %S registry key", wszKey);
  152. Log( PERF_FAILURE, szLog );
  153. bRet = FALSE;
  154. }
  155. return bRet;
  156. }
  157. BOOL CShowPerfLibDlg::OpenLibrary()
  158. {
  159. BOOL bRet = TRUE;
  160. char szLog[256];
  161. m_hLib = LoadLibrary( (LPCSTR)m_strPerfLib );
  162. if ( NULL != m_hLib )
  163. {
  164. sprintf(szLog, "Loaded the %s Performance Library", m_strPerfLib);
  165. Log( PERF_SUCCESS, szLog );
  166. m_pfnOpenProc = (PM_OPEN_PROC*) GetProcAddress( m_hLib, m_strOpen );
  167. m_pfnCollectProc = (PM_COLLECT_PROC*) GetProcAddress( m_hLib, m_strCollect );
  168. m_pfnCloseProc = (PM_CLOSE_PROC*) GetProcAddress( m_hLib, m_strClose );
  169. bRet = ( ( NULL != m_pfnOpenProc ) &&
  170. ( NULL != m_pfnCollectProc ) &&
  171. ( NULL != m_pfnCloseProc ) );
  172. Log (( NULL != m_pfnOpenProc )?PERF_SUCCESS:PERF_FAILURE, "Get Open Procedure Address");
  173. Log (( NULL != m_pfnCollectProc )?PERF_SUCCESS:PERF_FAILURE, "Get Collect Procedure Address");
  174. Log (( NULL != m_pfnCloseProc )?PERF_SUCCESS:PERF_FAILURE, "Get Close Procedure Address");
  175. }
  176. else
  177. {
  178. sprintf(szLog, "Could not load the %s Performance Library", m_strPerfLib);
  179. Log( PERF_FAILURE, szLog );
  180. bRet = FALSE;
  181. }
  182. if ( bRet )
  183. {
  184. bRet = ( m_pfnOpenProc( NULL ) == ERROR_SUCCESS );
  185. Log( bRet?PERF_SUCCESS:PERF_FAILURE, "Opening Performance Library" );
  186. if ( bRet && m_bRefCheck )
  187. {
  188. bRet = ( m_pfnOpenProc( NULL ) == ERROR_SUCCESS );
  189. Log( bRet?PERF_SUCCESS:PERF_FAILURE, "Opening Performance Library" );
  190. if ( bRet )
  191. {
  192. bRet = ( m_pfnCloseProc() == ERROR_SUCCESS );
  193. Log( bRet?PERF_SUCCESS:PERF_FAILURE, "Closing Performance Library" );
  194. }
  195. }
  196. }
  197. return bRet;
  198. }
  199. BOOL CShowPerfLibDlg::Collect( CString strSpace )
  200. {
  201. BOOL bRet = TRUE;
  202. int nRet = ERROR_MORE_DATA;
  203. char szLog[256];
  204. DWORD dwGuardSize = 1024;
  205. DWORD dwSize = 64000;
  206. BOOL bValid = HeapValidate( GetProcessHeap(), NULL, NULL );
  207. BYTE* pSafeBuffer = new BYTE[dwSize + ( 2 * dwGuardSize )];
  208. memset( pSafeBuffer, 0xFFFFFFFF, dwSize + ( 2 * dwGuardSize ) );
  209. BYTE* pBuffer = pSafeBuffer + dwGuardSize;
  210. BYTE* pBufferPtr = NULL;
  211. DWORD dwNumClasses = 0;
  212. DWORD dwBufferSize = 0;
  213. WCHAR wszSpace[256];
  214. mbstowcs( wszSpace, (LPCSTR)strSpace, 256 );
  215. while (ERROR_MORE_DATA == nRet)
  216. {
  217. pBufferPtr = pBuffer;
  218. dwBufferSize = dwSize;
  219. nRet = m_pfnCollectProc( wszSpace, (LPVOID*)(&pBufferPtr), &dwBufferSize, &dwNumClasses );
  220. sprintf(szLog, "Collect function called using %S counters", wszSpace);
  221. Log((nRet==ERROR_SUCCESS)?PERF_SUCCESS:((nRet==ERROR_MORE_DATA)?PERF_MORE_DATA:PERF_FAILURE), szLog );
  222. if (ERROR_SUCCESS == nRet)
  223. {
  224. sprintf(szLog, "Required buffer size: %d bytes", dwBufferSize);
  225. Log( PERF_INFO, szLog );
  226. sprintf(szLog, "Number of objects returned: %d", dwNumClasses);
  227. Log( PERF_INFO, szLog );
  228. try
  229. {
  230. BuildSubTree( strSpace, pBuffer, dwNumClasses );
  231. }
  232. catch(...)
  233. {
  234. AfxMessageBox("Exception thrown while processing blob");
  235. }
  236. }
  237. else if ( ERROR_MORE_DATA == nRet )
  238. {
  239. dwSize += 8000;
  240. if ( NULL != pSafeBuffer )
  241. {
  242. delete [] pSafeBuffer;
  243. }
  244. pSafeBuffer = new BYTE[dwSize + ( 2 * dwGuardSize )];
  245. memset( pSafeBuffer, 0xFFFFFFFF, dwSize + ( 2 * dwGuardSize ) );
  246. }
  247. else
  248. {
  249. bRet = FALSE;
  250. }
  251. }
  252. if ( NULL != pBuffer )
  253. {
  254. delete [] pSafeBuffer;
  255. }
  256. return bRet;
  257. }
  258. BOOL CShowPerfLibDlg::GetData()
  259. {
  260. BOOL bRet = TRUE;
  261. char szSpace[16];
  262. for ( int i = 0; (i < 2) && bRet; i++ )
  263. {
  264. if ( 0 == i )
  265. {
  266. strcpy (szSpace, "Global");
  267. }
  268. else
  269. {
  270. strcpy (szSpace, "Costly");
  271. }
  272. bRet = Collect( szSpace );
  273. }
  274. return bRet;
  275. }
  276. BOOL CShowPerfLibDlg::BuildSubTree( CString strSpace, BYTE* pBlob, DWORD dwNumObjects)
  277. {
  278. BOOL bRet = TRUE;
  279. HTREEITEM hSpace = m_wndPerfTree.InsertItem( strSpace );
  280. // Object
  281. PERF_OBJECT_TYPE* pObj = (PERF_OBJECT_TYPE*)pBlob;
  282. for ( DWORD dwObj = 0; dwObj < dwNumObjects; dwObj++ )
  283. {
  284. CString str;
  285. char* szName;
  286. m_TitleLibrary.GetName(pObj->ObjectNameTitleIndex, &szName);
  287. char szClassName[256];
  288. sprintf(szClassName, "%s Class", szName );
  289. HTREEITEM hClass = m_wndPerfTree.InsertItem( szClassName, hSpace );
  290. str.Format("TotalByteLength: %d", pObj->TotalByteLength);
  291. m_wndPerfTree.InsertItem( str, hClass );
  292. str.Format("DefinitionLength: %d", pObj->DefinitionLength);
  293. m_wndPerfTree.InsertItem( str, hClass );
  294. str.Format("HeaderLength: %d", pObj->HeaderLength);
  295. m_wndPerfTree.InsertItem( str, hClass );
  296. str.Format("ObjectNameTitleIndex: %d", pObj->ObjectNameTitleIndex);
  297. m_wndPerfTree.InsertItem( str, hClass );
  298. str.Format("ObjectHelpTitleIndex: %d", pObj->ObjectHelpTitleIndex);
  299. m_wndPerfTree.InsertItem( str, hClass );
  300. str.Format("DetailLevel: %d", pObj->DetailLevel);
  301. m_wndPerfTree.InsertItem( str, hClass );
  302. str.Format("NumCounters: %d", pObj->NumCounters);
  303. m_wndPerfTree.InsertItem( str, hClass );
  304. str.Format("DefaultCounter: %d", pObj->DefaultCounter);
  305. m_wndPerfTree.InsertItem( str, hClass );
  306. str.Format("NumInstances: %d", pObj->NumInstances);
  307. m_wndPerfTree.InsertItem( str, hClass );
  308. str.Format("CodePage: %d", pObj->CodePage);
  309. m_wndPerfTree.InsertItem( str, hClass );
  310. str.Format("PerfTime: %d", pObj->PerfTime);
  311. m_wndPerfTree.InsertItem( str, hClass );
  312. str.Format("PerfFreq: %d", pObj->PerfFreq);
  313. m_wndPerfTree.InsertItem( str, hClass );
  314. // Counters
  315. PERF_COUNTER_DEFINITION* pCtrDef = (PERF_COUNTER_DEFINITION*)((DWORD)pObj + pObj->HeaderLength);
  316. for ( DWORD dwCtr = 0; dwCtr < pObj->NumCounters; dwCtr++ )
  317. {
  318. char szCounterName[256];
  319. m_TitleLibrary.GetName( pCtrDef->CounterNameTitleIndex, &szName );
  320. sprintf(szCounterName, "%s Counter", szName);
  321. HTREEITEM hCtr = m_wndPerfTree.InsertItem( szCounterName, hClass );
  322. str.Format("ByteLength: %d", pCtrDef->ByteLength);
  323. m_wndPerfTree.InsertItem( str, hCtr );
  324. str.Format("CounterNameTitleIndex: %d", pCtrDef->CounterNameTitleIndex);
  325. m_wndPerfTree.InsertItem( str, hCtr );
  326. str.Format("CounterHelpTitleIndex: %d", pCtrDef->CounterHelpTitleIndex);
  327. m_wndPerfTree.InsertItem( str, hCtr );
  328. str.Format("DefaultScale: %d", pCtrDef->DefaultScale);
  329. m_wndPerfTree.InsertItem( str, hCtr );
  330. str.Format("DetailLevel: %d", pCtrDef->DetailLevel);
  331. m_wndPerfTree.InsertItem( str, hCtr );
  332. str.Format("CounterType: 0x%X (%s Base)", pCtrDef->CounterType, ( PERF_COUNTER_BASE == (pCtrDef->CounterType & 0x00070000))?"Is a ":"Is not a ");
  333. m_wndPerfTree.InsertItem( str, hCtr );
  334. str.Format("CounterSize: %d", pCtrDef->CounterSize);
  335. m_wndPerfTree.InsertItem( str, hCtr );
  336. str.Format("CounterOffset: %d", pCtrDef->CounterOffset);
  337. m_wndPerfTree.InsertItem( str, hCtr );
  338. pCtrDef = (PERF_COUNTER_DEFINITION*)((DWORD)pCtrDef + pCtrDef->ByteLength);
  339. }
  340. // Instances
  341. PERF_INSTANCE_DEFINITION* pInstDef = (PERF_INSTANCE_DEFINITION*)((DWORD)pObj + pObj->DefinitionLength);
  342. for ( LONG lInstance = 0; lInstance < pObj->NumInstances; lInstance++ )
  343. {
  344. char szInstanceName[256];
  345. sprintf(szInstanceName, "%S Instance", (WCHAR*)((DWORD)pInstDef + pInstDef->NameOffset));
  346. HTREEITEM hInst = m_wndPerfTree.InsertItem( szInstanceName, hClass );
  347. str.Format("ByteLength: %d", pInstDef->ByteLength);
  348. m_wndPerfTree.InsertItem( str, hInst );
  349. str.Format("ParentObjectTitleIndex: %d", pInstDef->ParentObjectTitleIndex);
  350. m_wndPerfTree.InsertItem( str, hInst );
  351. str.Format("ParentObjectInstance: %d", pInstDef->ParentObjectInstance);
  352. m_wndPerfTree.InsertItem( str, hInst );
  353. str.Format("UniqueID: %d", pInstDef->UniqueID);
  354. m_wndPerfTree.InsertItem( str, hInst );
  355. str.Format("NameOffset: %d", pInstDef->NameOffset);
  356. m_wndPerfTree.InsertItem( str, hInst );
  357. str.Format("NameLength: %d", pInstDef->NameLength);
  358. m_wndPerfTree.InsertItem( str, hInst );
  359. // Instance Counter Data
  360. PERF_COUNTER_BLOCK* pCtrBlock = (PERF_COUNTER_BLOCK*)((DWORD)pInstDef + pInstDef->ByteLength);
  361. BYTE* pCurrCtr = (BYTE*)pCtrBlock;
  362. PERF_COUNTER_DEFINITION* pCtrDef = (PERF_COUNTER_DEFINITION*)((DWORD)pObj + pObj->HeaderLength);
  363. for ( DWORD dwCtr = 0; dwCtr < pObj->NumCounters; dwCtr++ )
  364. {
  365. char* szName;
  366. m_TitleLibrary.GetName( pCtrDef->CounterNameTitleIndex, &szName );
  367. switch (pCtrDef->CounterSize)
  368. {
  369. case 0:
  370. {
  371. str.Format("%s data: <zero length>", szName );
  372. m_wndPerfTree.InsertItem( str, hInst );
  373. }break;
  374. case 4:
  375. {
  376. str.Format("%s data: %d", szName, (DWORD)(*(pCurrCtr + pCtrDef->CounterOffset)));
  377. m_wndPerfTree.InsertItem( str, hInst );
  378. }break;
  379. case 8:
  380. {
  381. str.Format("%s data: %I64d", szName, (__int64)(*(pCurrCtr + pCtrDef->CounterOffset)));
  382. m_wndPerfTree.InsertItem( str, hInst );
  383. }break;
  384. default:
  385. {
  386. str.Format("%s data: <unhandled>", szName );
  387. m_wndPerfTree.InsertItem( str, hInst );
  388. }break;
  389. }
  390. pCtrDef = (PERF_COUNTER_DEFINITION*)((DWORD)pCtrDef + pCtrDef->ByteLength);
  391. }
  392. pInstDef = (PERF_INSTANCE_DEFINITION*)((DWORD)pCtrBlock + pCtrBlock->ByteLength);
  393. }
  394. pObj = (PERF_OBJECT_TYPE*)((DWORD)pObj + pObj->TotalByteLength);
  395. }
  396. return bRet;
  397. }
  398. BOOL CShowPerfLibDlg::CloseLibrary()
  399. {
  400. BOOL bRet = TRUE;
  401. DWORD dwRet = m_pfnCloseProc();
  402. /* if ( ERROR_SUCCESS != dwRet )
  403. bRet = FALSE;
  404. Log( bRet?PERF_SUCCESS:PERF_FAILURE, "Closing Performance Library" );
  405. */
  406. return bRet;
  407. }
  408. void CShowPerfLibDlg::Log( DWORD dwState, CString strDesc )
  409. {
  410. CString strState;
  411. int nIndex = -1;
  412. BOOL bErr;
  413. switch( dwState )
  414. {
  415. case PERF_SUCCESS:
  416. {
  417. strState = "Success";
  418. }break;
  419. case PERF_INFO:
  420. {
  421. strState = "Information";
  422. }break;
  423. case PERF_MORE_DATA:
  424. {
  425. strState = "More Data";
  426. }break;
  427. case PERF_WARNING:
  428. {
  429. strState = "Warning";
  430. }break;
  431. case PERF_FAILURE:
  432. {
  433. strState = "Failure";
  434. }break;
  435. default:
  436. {
  437. strState = "Unknown";
  438. }break;
  439. };
  440. nIndex = m_wndErrorLog.InsertItem( m_wndErrorLog.GetItemCount() , strState );
  441. bErr = m_wndErrorLog.SetItemText( nIndex, 1, strDesc );
  442. }
  443. void CShowPerfLibDlg::OnChangeRequest()
  444. {
  445. }
  446. void CShowPerfLibDlg::OnGetCounter()
  447. {
  448. UpdateData();
  449. Collect( m_strRequest );
  450. m_strRequest.Empty();
  451. UpdateData( FALSE );
  452. }