Leaked source code of windows server 2003
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.

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