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.

749 lines
18 KiB

  1. //
  2. // Driver Verifier UI
  3. // Copyright (c) Microsoft Corporation, 1999
  4. //
  5. //
  6. //
  7. // module: GCntPage.cpp
  8. // author: DMihai
  9. // created: 11/1/00
  10. //
  11. // Description:
  12. //
  13. #include "stdafx.h"
  14. #include "verifier.h"
  15. #include "GCntPage.h"
  16. #include "VrfUtil.h"
  17. #include "VGlobal.h"
  18. #ifdef _DEBUG
  19. #define new DEBUG_NEW
  20. #undef THIS_FILE
  21. static char THIS_FILE[] = __FILE__;
  22. #endif
  23. //
  24. // Timer ID
  25. //
  26. #define REFRESH_TIMER_ID 0x1234
  27. //
  28. // Help IDs
  29. //
  30. static DWORD MyHelpIds[] =
  31. {
  32. IDC_GLOBC_LIST, IDH_DV_GlobalCounters,
  33. 0, 0
  34. };
  35. /////////////////////////////////////////////////////////////////////////////
  36. // CGlobalCountPage property page
  37. IMPLEMENT_DYNCREATE(CGlobalCountPage, CVerifierPropertyPage)
  38. CGlobalCountPage::CGlobalCountPage() : CVerifierPropertyPage(CGlobalCountPage::IDD)
  39. {
  40. //{{AFX_DATA_INIT(CGlobalCountPage)
  41. //}}AFX_DATA_INIT
  42. m_nSortColumnIndex = 0;
  43. m_bAscendSortName = FALSE;
  44. m_bAscendSortValue = FALSE;
  45. m_uTimerHandler = 0;
  46. m_pParentSheet = NULL;
  47. }
  48. CGlobalCountPage::~CGlobalCountPage()
  49. {
  50. }
  51. void CGlobalCountPage::DoDataExchange(CDataExchange* pDX)
  52. {
  53. static BOOL bShownPoolCoverageWarning = FALSE;
  54. if( ! pDX->m_bSaveAndValidate )
  55. {
  56. //
  57. // Query the kernel
  58. //
  59. VrfGetRuntimeVerifierData( &m_RuntimeVerifierData );
  60. if( FALSE == bShownPoolCoverageWarning )
  61. {
  62. bShownPoolCoverageWarning = CheckAndShowPoolCoverageWarning();
  63. }
  64. }
  65. CVerifierPropertyPage::DoDataExchange(pDX);
  66. //{{AFX_DATA_MAP(CGlobalCountPage)
  67. DDX_Control(pDX, IDC_GLOBC_LIST, m_CountersList);
  68. DDX_Control(pDX, IDC_GLOBC_NEXT_DESCR_STATIC, m_NextDescription);
  69. //}}AFX_DATA_MAP
  70. }
  71. BEGIN_MESSAGE_MAP(CGlobalCountPage, CVerifierPropertyPage)
  72. //{{AFX_MSG_MAP(CGlobalCountPage)
  73. ON_WM_TIMER()
  74. ON_NOTIFY(LVN_COLUMNCLICK, IDC_GLOBC_LIST, OnColumnclickGlobcList)
  75. ON_WM_CONTEXTMENU()
  76. ON_MESSAGE( WM_HELP, OnHelp )
  77. //}}AFX_MSG_MAP
  78. END_MESSAGE_MAP()
  79. /////////////////////////////////////////////////////////////
  80. VOID CGlobalCountPage::SetupListHeader()
  81. {
  82. LVCOLUMN lvColumn;
  83. CRect rectWnd;
  84. CString strCounter, strValue;
  85. VERIFY( strCounter.LoadString( IDS_COUNTER ) );
  86. VERIFY( strValue.LoadString( IDS_VALUE ) );
  87. //
  88. // List's regtangle
  89. //
  90. m_CountersList.GetClientRect( &rectWnd );
  91. //
  92. // Column 0 - counter
  93. //
  94. ZeroMemory( &lvColumn, sizeof( lvColumn ) );
  95. lvColumn.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH;
  96. lvColumn.fmt = LVCFMT_LEFT;
  97. lvColumn.iSubItem = 0;
  98. lvColumn.pszText = strCounter.GetBuffer( strCounter.GetLength() + 1 );
  99. lvColumn.cx = (int)( rectWnd.Width() * 0.50 );
  100. VERIFY( m_CountersList.InsertColumn( 0, &lvColumn ) != -1 );
  101. strCounter.ReleaseBuffer();
  102. //
  103. // Column 1
  104. //
  105. lvColumn.iSubItem = 1;
  106. lvColumn.pszText = strValue.GetBuffer( strValue.GetLength() + 1 );
  107. lvColumn.cx = (int)( rectWnd.Width() * 0.47 );
  108. VERIFY( m_CountersList.InsertColumn( 1, &lvColumn ) != -1 );
  109. strValue.ReleaseBuffer();
  110. }
  111. /////////////////////////////////////////////////////////////
  112. VOID CGlobalCountPage::FillTheList()
  113. {
  114. //
  115. // N.B.
  116. //
  117. // If you change the first parameter (index - stored in the item's data)
  118. // you need to change the switch statement in GetCounterValue as well
  119. //
  120. AddCounterInList( 0, IDS_ALLOCATIONSATTEMPTED_LIST, m_RuntimeVerifierData.AllocationsAttempted );
  121. AddCounterInList( 1, IDS_ALLOCATIONSSUCCEEDED_LIST, m_RuntimeVerifierData.AllocationsSucceeded );
  122. AddCounterInList( 2, IDS_ALLOCATIONSSUCCEEDEDSPECIALPOOL_LIST, m_RuntimeVerifierData.AllocationsSucceededSpecialPool );
  123. AddCounterInList( 3, IDS_ALLOCATIONSWITHNOTAG_LIST, m_RuntimeVerifierData.AllocationsWithNoTag );
  124. AddCounterInList( 4, IDS_UNTRACKEDPOOL_LIST, m_RuntimeVerifierData.UnTrackedPool );
  125. AddCounterInList( 5, IDS_ALLOCATIONSFAILED_LIST, m_RuntimeVerifierData.AllocationsFailed );
  126. AddCounterInList( 6, IDS_ALLOCATIONSFAILEDDELIBERATELY_LIST, m_RuntimeVerifierData.AllocationsFailedDeliberately );
  127. AddCounterInList( 7, IDS_RAISEIRQLS_LIST, m_RuntimeVerifierData.RaiseIrqls );
  128. AddCounterInList( 8, IDS_ACQUIRESPINLOCKS_LIST, m_RuntimeVerifierData.AcquireSpinLocks );
  129. AddCounterInList( 9, IDS_SYNCHRONIZEEXECUTIONS_LIST, m_RuntimeVerifierData.SynchronizeExecutions );
  130. AddCounterInList( 10, IDS_TRIMS_LIST, m_RuntimeVerifierData.Trims );
  131. }
  132. /////////////////////////////////////////////////////////////
  133. VOID CGlobalCountPage::RefreshTheList()
  134. {
  135. INT nListItems;
  136. INT nCrtListItem;
  137. INT_PTR nCrtCounterIndex;
  138. SIZE_T sizeValue;
  139. nListItems = m_CountersList.GetItemCount();
  140. for( nCrtListItem = 0; nCrtListItem < nListItems; nCrtListItem += 1 )
  141. {
  142. nCrtCounterIndex = m_CountersList.GetItemData( nCrtListItem );
  143. sizeValue = GetCounterValue( nCrtCounterIndex );
  144. UpdateCounterValueInList( nCrtListItem, sizeValue );
  145. }
  146. }
  147. /////////////////////////////////////////////////////////////
  148. VOID CGlobalCountPage::SortTheList()
  149. {
  150. if( 0 != m_nSortColumnIndex )
  151. {
  152. //
  153. // Sort by counter value - this is probably not very useful
  154. // but we are providing it to be consistent with all
  155. // the lists being sortable by any column
  156. //
  157. m_CountersList.SortItems( CounterValueCmpFunc, (LPARAM)this );
  158. }
  159. else
  160. {
  161. //
  162. // Sort by driver name
  163. //
  164. m_CountersList.SortItems( CounterNameCmpFunc, (LPARAM)this );
  165. }
  166. }
  167. /////////////////////////////////////////////////////////////
  168. SIZE_T CGlobalCountPage::GetCounterValue( INT_PTR nCounterIndex )
  169. {
  170. SIZE_T sizeValue;
  171. //
  172. // N.B.
  173. //
  174. // If you change this switch statement you need to change FillTheList as well
  175. //
  176. switch( nCounterIndex )
  177. {
  178. case 0:
  179. sizeValue = m_RuntimeVerifierData.AllocationsAttempted;
  180. break;
  181. case 1:
  182. sizeValue = m_RuntimeVerifierData.AllocationsSucceeded;
  183. break;
  184. case 2:
  185. sizeValue = m_RuntimeVerifierData.AllocationsSucceededSpecialPool;
  186. break;
  187. case 3:
  188. sizeValue = m_RuntimeVerifierData.AllocationsWithNoTag;
  189. break;
  190. case 4:
  191. sizeValue = m_RuntimeVerifierData.UnTrackedPool;
  192. break;
  193. case 5:
  194. sizeValue = m_RuntimeVerifierData.AllocationsFailed;
  195. break;
  196. case 6:
  197. sizeValue = m_RuntimeVerifierData.AllocationsFailedDeliberately;
  198. break;
  199. case 7:
  200. sizeValue = m_RuntimeVerifierData.RaiseIrqls;
  201. break;
  202. case 8:
  203. sizeValue = m_RuntimeVerifierData.AcquireSpinLocks;
  204. break;
  205. case 9:
  206. sizeValue = m_RuntimeVerifierData.SynchronizeExecutions;
  207. break;
  208. case 10:
  209. sizeValue = m_RuntimeVerifierData.Trims;
  210. break;
  211. default:
  212. //
  213. // Oops, how did we get here ?!?
  214. //
  215. ASSERT( FALSE );
  216. sizeValue = 0;
  217. break;
  218. }
  219. return sizeValue;
  220. }
  221. /////////////////////////////////////////////////////////////
  222. BOOL CGlobalCountPage::GetCounterName( LPARAM lItemData,
  223. TCHAR *szCounterName,
  224. ULONG uCounterNameBufferLen )
  225. {
  226. INT nItemIndex;
  227. BOOL bResult;
  228. LVFINDINFO FindInfo;
  229. LVITEM lvItem;
  230. bResult = FALSE;
  231. ZeroMemory( &FindInfo, sizeof( FindInfo ) );
  232. FindInfo.flags = LVFI_PARAM;
  233. FindInfo.lParam = lItemData;
  234. nItemIndex = m_CountersList.FindItem( &FindInfo );
  235. if( nItemIndex < 0 || nItemIndex > 10 )
  236. {
  237. ASSERT( FALSE );
  238. }
  239. else
  240. {
  241. //
  242. // Found our item - get the name
  243. //
  244. ZeroMemory( &lvItem, sizeof( lvItem ) );
  245. lvItem.mask = LVIF_TEXT;
  246. lvItem.iItem = nItemIndex;
  247. lvItem.iSubItem = 0;
  248. lvItem.pszText = szCounterName;
  249. lvItem.cchTextMax = uCounterNameBufferLen;
  250. bResult = m_CountersList.GetItem( &lvItem );
  251. if( bResult == FALSE )
  252. {
  253. //
  254. // Could not get the current item's attributes?!?
  255. //
  256. ASSERT( FALSE );
  257. }
  258. }
  259. return bResult;
  260. }
  261. /////////////////////////////////////////////////////////////
  262. VOID CGlobalCountPage::AddCounterInList( INT nItemData,
  263. ULONG uIdResourceString,
  264. SIZE_T sizeValue )
  265. {
  266. INT nActualIndex;
  267. LVITEM lvItem;
  268. CString strName;
  269. VERIFY( strName.LoadString( uIdResourceString ) );
  270. ZeroMemory( &lvItem, sizeof( lvItem ) );
  271. //
  272. // LVITEM's member pszText is not a const pointer
  273. // so we need to GetBuffer here :-(
  274. //
  275. //
  276. // Sub-item 0 - counter's name
  277. //
  278. lvItem.pszText = strName.GetBuffer( strName.GetLength() + 1 );
  279. if( NULL == lvItem.pszText )
  280. {
  281. goto Done;
  282. }
  283. lvItem.mask = LVIF_TEXT | LVIF_PARAM;
  284. lvItem.lParam = nItemData;
  285. lvItem.iItem = m_CountersList.GetItemCount();
  286. nActualIndex = m_CountersList.InsertItem( &lvItem );
  287. if( nActualIndex < 0 )
  288. {
  289. //
  290. // Could not add an item in the list - give up
  291. //
  292. goto Done;
  293. }
  294. //
  295. // Sub-item 1 - counter's value
  296. //
  297. UpdateCounterValueInList( nActualIndex,
  298. sizeValue );
  299. Done:
  300. //
  301. // All done
  302. //
  303. NOTHING;
  304. }
  305. /////////////////////////////////////////////////////////////
  306. VOID CGlobalCountPage::RefreshInfo()
  307. {
  308. if( UpdateData( FALSE ) )
  309. {
  310. //
  311. // Refresh the settings bits list
  312. //
  313. RefreshTheList();
  314. }
  315. }
  316. /////////////////////////////////////////////////////////////
  317. VOID CGlobalCountPage::UpdateCounterValueInList( INT nItemIndex,
  318. SIZE_T sizeValue )
  319. {
  320. TCHAR szValue[ 32 ];
  321. LVITEM lvItem;
  322. #ifndef _WIN64
  323. //
  324. // 32 bit SIZE_T
  325. //
  326. _sntprintf( szValue,
  327. ARRAY_LENGTH( szValue ),
  328. _T( "%u" ),
  329. sizeValue );
  330. #else
  331. //
  332. // 64 bit SIZE_T
  333. //
  334. _sntprintf( szValue,
  335. ARRAY_LENGTH( szValue ),
  336. _T( "%I64u" ),
  337. sizeValue );
  338. #endif
  339. szValue[ ARRAY_LENGTH( szValue ) - 1 ] = 0;
  340. //
  341. // Update the list item
  342. //
  343. ZeroMemory( &lvItem, sizeof( lvItem ) );
  344. lvItem.mask = LVIF_TEXT;
  345. lvItem.iItem = nItemIndex;
  346. lvItem.iSubItem = 1;
  347. lvItem.pszText = szValue;
  348. VERIFY( m_CountersList.SetItem( &lvItem ) );
  349. }
  350. /////////////////////////////////////////////////////////////
  351. //
  352. // Other methods
  353. //
  354. /////////////////////////////////////////////////////////////
  355. #define MIN_MEM_SIZE_TO_DISABLE_WARNING 0x80000000 // 2 Gb
  356. #define MIN_ALLOCATIONS_SIGNIFICANT 100
  357. #define MIN_PERCENTAGE_AVOID_WARNING 95
  358. BOOL CGlobalCountPage::CheckAndShowPoolCoverageWarning()
  359. {
  360. BOOL bWarningDisplayed;
  361. ULONGLONG ullPercentageCoverage;
  362. TCHAR *szMessage;
  363. CString strMsgFormat;
  364. CString strWarnMsg;
  365. bWarningDisplayed = FALSE;
  366. if( m_RuntimeVerifierData.m_bSpecialPool &&
  367. m_RuntimeVerifierData.AllocationsSucceeded >= MIN_ALLOCATIONS_SIGNIFICANT )
  368. {
  369. //
  370. // Special pool verification is enabled &&
  371. // There is a significant number of allocations
  372. //
  373. ASSERT( m_RuntimeVerifierData.AllocationsSucceeded >= m_RuntimeVerifierData.AllocationsSucceededSpecialPool );
  374. //
  375. // The coverage percentage
  376. //
  377. ullPercentageCoverage =
  378. ( (ULONGLONG)m_RuntimeVerifierData.AllocationsSucceededSpecialPool * (ULONGLONG) 100 ) /
  379. (ULONGLONG)m_RuntimeVerifierData.AllocationsSucceeded;
  380. ASSERT( ullPercentageCoverage <= 100 );
  381. if( ullPercentageCoverage < MIN_PERCENTAGE_AVOID_WARNING )
  382. {
  383. //
  384. // Warn the user
  385. //
  386. if( strMsgFormat.LoadString( IDS_COVERAGE_WARNING_FORMAT ) )
  387. {
  388. szMessage = strWarnMsg.GetBuffer( strMsgFormat.GetLength() + 32 );
  389. if( szMessage != NULL )
  390. {
  391. _stprintf( szMessage, (LPCTSTR)strMsgFormat, ullPercentageCoverage );
  392. strWarnMsg.ReleaseBuffer();
  393. AfxMessageBox( strWarnMsg,
  394. MB_OK | MB_ICONINFORMATION );
  395. }
  396. }
  397. else
  398. {
  399. ASSERT( FALSE );
  400. }
  401. bWarningDisplayed = TRUE;
  402. }
  403. }
  404. return bWarningDisplayed;
  405. }
  406. /////////////////////////////////////////////////////////////
  407. int CALLBACK CGlobalCountPage::CounterValueCmpFunc( LPARAM lParam1,
  408. LPARAM lParam2,
  409. LPARAM lParamSort)
  410. {
  411. SIZE_T size1;
  412. SIZE_T size2;
  413. int nCmpRez = 0;
  414. CGlobalCountPage *pThis = (CGlobalCountPage *)lParamSort;
  415. ASSERT_VALID( pThis );
  416. size1 = pThis->GetCounterValue( (INT) lParam1 );
  417. size2 = pThis->GetCounterValue( (INT) lParam2 );
  418. if( size1 > size2 )
  419. {
  420. nCmpRez = 1;
  421. }
  422. else
  423. {
  424. if( size1 < size2 )
  425. {
  426. nCmpRez = -1;
  427. }
  428. }
  429. if( FALSE != pThis->m_bAscendSortValue )
  430. {
  431. nCmpRez *= -1;
  432. }
  433. return nCmpRez;
  434. }
  435. /////////////////////////////////////////////////////////////
  436. int CALLBACK CGlobalCountPage::CounterNameCmpFunc( LPARAM lParam1,
  437. LPARAM lParam2,
  438. LPARAM lParamSort)
  439. {
  440. int nCmpRez = 0;
  441. BOOL bSuccess;
  442. TCHAR szCounterName1[ _MAX_PATH ];
  443. TCHAR szCounterName2[ _MAX_PATH ];
  444. CGlobalCountPage *pThis = (CGlobalCountPage *)lParamSort;
  445. ASSERT_VALID( pThis );
  446. //
  447. // Get the first counter name
  448. //
  449. bSuccess = pThis->GetCounterName( lParam1,
  450. szCounterName1,
  451. ARRAY_LENGTH( szCounterName1 ) );
  452. if( FALSE == bSuccess )
  453. {
  454. goto Done;
  455. }
  456. //
  457. // Get the second counter name
  458. //
  459. bSuccess = pThis->GetCounterName( lParam2,
  460. szCounterName2,
  461. ARRAY_LENGTH( szCounterName2 ) );
  462. if( FALSE == bSuccess )
  463. {
  464. goto Done;
  465. }
  466. //
  467. // Compare the names
  468. //
  469. nCmpRez = _tcsicmp( szCounterName1, szCounterName2 );
  470. if( FALSE != pThis->m_bAscendSortName )
  471. {
  472. nCmpRez *= -1;
  473. }
  474. Done:
  475. return nCmpRez;
  476. }
  477. /////////////////////////////////////////////////////////////
  478. // CGlobalCountPage message handlers
  479. BOOL CGlobalCountPage::OnInitDialog()
  480. {
  481. CPropertyPage::OnInitDialog();
  482. //
  483. // Setup the settings bits list
  484. //
  485. m_CountersList.SetExtendedStyle(
  486. LVS_EX_FULLROWSELECT | m_CountersList.GetExtendedStyle() );
  487. m_CountersList.SetBkColor( ::GetSysColor( COLOR_3DFACE ) );
  488. m_CountersList.SetTextBkColor( ::GetSysColor( COLOR_3DFACE ) );
  489. SetupListHeader();
  490. FillTheList();
  491. SortTheList();
  492. VrfSetWindowText( m_NextDescription, IDS_GCNT_PAGE_NEXT_DESCR );
  493. VERIFY( m_uTimerHandler = SetTimer( REFRESH_TIMER_ID,
  494. 5000,
  495. NULL ) );
  496. return TRUE; // return TRUE unless you set the focus to a control
  497. // EXCEPTION: OCX Property Pages should return FALSE
  498. }
  499. /////////////////////////////////////////////////////////////
  500. VOID CGlobalCountPage::OnTimer(UINT nIDEvent)
  501. {
  502. if( nIDEvent == REFRESH_TIMER_ID )
  503. {
  504. ASSERT_VALID( m_pParentSheet );
  505. if( m_pParentSheet->GetActivePage() == this )
  506. {
  507. //
  508. // Refresh the displayed data
  509. //
  510. RefreshInfo();
  511. }
  512. }
  513. CPropertyPage::OnTimer(nIDEvent);
  514. }
  515. /////////////////////////////////////////////////////////////////////////////
  516. BOOL CGlobalCountPage::OnSetActive()
  517. {
  518. ASSERT_VALID( m_pParentSheet );
  519. m_pParentSheet->SetWizardButtons( PSWIZB_BACK |
  520. PSWIZB_NEXT );
  521. return CVerifierPropertyPage::OnSetActive();
  522. }
  523. /////////////////////////////////////////////////////////////////////////////
  524. LRESULT CGlobalCountPage::OnWizardNext()
  525. {
  526. GoingToNextPageNotify( IDD_PERDRIVER_COUNTERS_PAGE );
  527. return IDD_PERDRIVER_COUNTERS_PAGE;
  528. }
  529. /////////////////////////////////////////////////////////////////////////////
  530. void CGlobalCountPage::OnColumnclickGlobcList(NMHDR* pNMHDR, LRESULT* pResult)
  531. {
  532. NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
  533. if( 0 != pNMListView->iSubItem )
  534. {
  535. //
  536. // Clicked on the counter value column
  537. //
  538. if( m_nSortColumnIndex == pNMListView->iSubItem )
  539. {
  540. //
  541. // Change the current ascend/descend order for this column
  542. //
  543. m_bAscendSortValue = !m_bAscendSortValue;
  544. }
  545. }
  546. else
  547. {
  548. //
  549. // Clicked on the counter name column
  550. //
  551. if( m_nSortColumnIndex == pNMListView->iSubItem )
  552. {
  553. //
  554. // Change the current ascend/descend order for this column
  555. //
  556. m_bAscendSortName = !m_bAscendSortName;
  557. }
  558. }
  559. m_nSortColumnIndex = pNMListView->iSubItem;
  560. SortTheList();
  561. *pResult = 0;
  562. }
  563. /////////////////////////////////////////////////////////////
  564. LONG CGlobalCountPage::OnHelp( WPARAM wParam, LPARAM lParam )
  565. {
  566. LONG lResult = 0;
  567. LPHELPINFO lpHelpInfo = (LPHELPINFO)lParam;
  568. ::WinHelp(
  569. (HWND) lpHelpInfo->hItemHandle,
  570. g_szVerifierHelpFile,
  571. HELP_WM_HELP,
  572. (DWORD_PTR) MyHelpIds );
  573. return lResult;
  574. }
  575. /////////////////////////////////////////////////////////////////////////////
  576. void CGlobalCountPage::OnContextMenu(CWnd* pWnd, CPoint point)
  577. {
  578. ::WinHelp(
  579. pWnd->m_hWnd,
  580. g_szVerifierHelpFile,
  581. HELP_CONTEXTMENU,
  582. (DWORD_PTR) MyHelpIds );
  583. }