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.

1786 lines
43 KiB

  1. /*++
  2. Copyright (C) 1996-1999 Microsoft Corporation
  3. Module Name:
  4. ctrprop.cpp
  5. Abstract:
  6. This file contains the CCounterPropPage class and other routines
  7. to implement the counter property page.
  8. --*/
  9. #include <assert.h>
  10. #include <stdio.h>
  11. #include <math.h>
  12. #include <limits.h>
  13. #include "polyline.h"
  14. #include "ctrprop.h"
  15. #include "utils.h"
  16. #include "unihelpr.h"
  17. #include "winhelpr.h"
  18. #include "visuals.h"
  19. #include "strids.h"
  20. #include "winperf.h"
  21. #include "pdhmsg.h"
  22. #include "globals.h"
  23. #include "browser.h"
  24. #include "smonmsg.h"
  25. #define OWNER_DRAWN_ITEM 2
  26. #define OWNER_DRAW_FOCUS 1
  27. VOID static
  28. HandleSelectionState (
  29. IN LPDRAWITEMSTRUCT lpdis
  30. )
  31. /*++
  32. Routine Description:
  33. HandleSelectionState draws or erases a selection rectangle around an item
  34. in a combo box list.
  35. Arguments:
  36. lpdis - Pointer to DRAWITEMSTRUCT
  37. Return Value:
  38. None.
  39. --*/
  40. {
  41. HBRUSH hbr ;
  42. if ( NULL != lpdis ) {
  43. if (lpdis->itemState & ODS_SELECTED)
  44. hbr = (HBRUSH)GetStockObject(BLACK_BRUSH) ;
  45. else
  46. hbr = CreateSolidBrush(GetSysColor(COLOR_WINDOW)) ;
  47. if ( NULL != hbr ) {
  48. FrameRect(lpdis->hDC, (LPRECT)&lpdis->rcItem, hbr) ;
  49. DeleteObject (hbr) ;
  50. }
  51. }
  52. }
  53. //***************************************************************************
  54. // *
  55. // FUNCTION : HandleFocusState(LPDRAWITEMSTRUCT) *
  56. // *
  57. // PURPOSE : Handle a change in item focus state. If an item gains the *
  58. // input focus, a gray rectangular frame is drawn around that *
  59. // item; if an item loses the input focus, the gray frame is *
  60. // removed. *
  61. // *
  62. // COMMENT : The gray focus frame is slightly smaller than the black *
  63. // selection frame so they won't paint over each other. *
  64. // *
  65. //***************************************************************************
  66. VOID static
  67. HandleFocusState (
  68. IN LPDRAWITEMSTRUCT lpdis
  69. )
  70. /*++
  71. Routine Description:
  72. HandleFocusState draws or erases a focus rectangle around an item in
  73. the pulldown list of a combo box. The reactngle is indented to not
  74. interfere with the selection rectangle.
  75. Arguments:
  76. lpdis - Pointer to DRAWITEMSTRUCT
  77. Return Value:
  78. None.
  79. --*/
  80. {
  81. RECT rc ;
  82. HBRUSH hbr ;
  83. if ( NULL != lpdis ) {
  84. // Resize rectangle to place focus frame between the selection
  85. // frame and the item.
  86. CopyRect ((LPRECT)&rc, (LPRECT)&lpdis->rcItem) ;
  87. InflateRect ((LPRECT)&rc, -OWNER_DRAW_FOCUS, -OWNER_DRAW_FOCUS) ;
  88. // Gray if has focus, background color if not
  89. if (lpdis->itemState & ODS_FOCUS)
  90. hbr = (HBRUSH)GetStockObject(GRAY_BRUSH) ;
  91. else
  92. hbr = CreateSolidBrush(GetSysColor(COLOR_WINDOW)) ;
  93. if ( NULL != hbr ) {
  94. FrameRect(lpdis->hDC, (LPRECT)&rc, hbr) ;
  95. DeleteObject (hbr) ;
  96. }
  97. }
  98. }
  99. CCounterPropPage::CCounterPropPage ( void )
  100. : m_pInfoSel ( NULL ),
  101. m_pInfoDeleted ( NULL ),
  102. m_dwMaxHorizListExtent ( 0 ),
  103. m_bAreModSelectedVisuals ( FALSE ),
  104. m_fHashTableSetup ( FALSE )
  105. /*++
  106. Routine Description:
  107. Creation routine for counter property page. Initializes the instance
  108. variables.
  109. Arguments:
  110. None.
  111. Return Value:
  112. None.
  113. --*/
  114. {
  115. m_uIDDialog = IDD_CTR_PROPP_DLG;
  116. m_uIDTitle = IDS_CTR_PROPP_TITLE;
  117. return;
  118. }
  119. CCounterPropPage::~CCounterPropPage (
  120. VOID
  121. )
  122. /*++
  123. Routine Description:
  124. Destructor for counter property page.
  125. Arguments:
  126. None.
  127. Return Value:
  128. None.
  129. --*/
  130. {
  131. ClearCountersHashTable();
  132. return;
  133. }
  134. void
  135. CCounterPropPage::DeinitControls ( void )
  136. {
  137. ISystemMonitor *pObj = NULL;
  138. CImpISystemMonitor *pPrivObj = NULL;
  139. HWND hwndList = NULL;
  140. INT iIndex = 0;
  141. INT iItemCnt = 0;
  142. PItemInfo pInfo = NULL;
  143. // Write the current visuals back to the control
  144. // Must be at least one control object and only the first is used
  145. if (m_cObjects != 0) {
  146. pObj = m_ppISysmon[0];
  147. if ( NULL != pObj ) {
  148. pPrivObj = (CImpISystemMonitor*)pObj;
  149. }
  150. }
  151. if ( NULL != pPrivObj ) {
  152. if ( AreModifiedSelectedVisuals() ) {
  153. IncrementLocalVisuals();
  154. }
  155. pPrivObj->SetVisuals(m_props.rgbColor, m_props.iColorIndex, m_props.iWidthIndex, m_props.iStyleIndex);
  156. }
  157. hwndList = DialogControl(m_hDlg, IDC_CTRLIST);
  158. if ( NULL != hwndList ) {
  159. iItemCnt = LBNumItems(hwndList);
  160. for (iIndex = 0; iIndex < iItemCnt; iIndex++ ) {
  161. pInfo = (PItemInfo)LBData(hwndList,iIndex);
  162. if ( NULL != pInfo ) {
  163. DeleteInfo(pInfo);
  164. }
  165. }
  166. }
  167. return;
  168. }
  169. INT
  170. CCounterPropPage::SelectMatchingItem (
  171. INT iColorIndex,
  172. COLORREF rgbCustomColor,
  173. INT iWidthIndex,
  174. INT iStyleIndex)
  175. /*++
  176. Routine Description:
  177. GetMatchingIndex selects the first counter item that matches the
  178. specified visual characteristics.
  179. Arguments:
  180. None.
  181. Return Value:
  182. Returns the index of the selected item on match. If none match, then
  183. returns -1.
  184. --*/
  185. {
  186. INT iReturn = -1;
  187. // Get number of items in list box
  188. HWND hwndList = DialogControl(m_hDlg, IDC_CTRLIST);
  189. INT iItemCnt = LBNumItems(hwndList);
  190. INT i;
  191. bool bMatch = false;
  192. // For each item
  193. for (i=0; !bMatch && i<iItemCnt; i++){
  194. PItemInfo pInfo = (PItemInfo)LBData(hwndList,i);
  195. LoadItemProps ( pInfo );
  196. if ( pInfo->Props.iColorIndex == iColorIndex ) {
  197. if ( NumStandardColorIndices() > iColorIndex ) {
  198. bMatch = true;
  199. } else {
  200. if ( pInfo->Props.rgbColor == rgbCustomColor )
  201. bMatch = true;
  202. }
  203. if ( bMatch ) {
  204. if ( ( iWidthIndex != pInfo->Props.iWidthIndex )
  205. || ( iStyleIndex != pInfo->Props.iStyleIndex ) ){
  206. bMatch = false;
  207. }
  208. }
  209. }
  210. }
  211. if ( bMatch ) {
  212. iReturn = i - 1;
  213. SelectItem ( iReturn );
  214. }
  215. return iReturn;
  216. }
  217. BOOL
  218. CCounterPropPage::GetProperties (
  219. VOID
  220. )
  221. /*++
  222. Routine Description:
  223. GetProperties initializes the dialog box for the property page. It then
  224. fetches an ICounterItem interface for each counter of the control being
  225. edited. Each interface pointer is placed in an ItemInfo structure which is
  226. then added to the dialog list box.
  227. The counter properties are not fetched until they are needed for display.
  228. The first counter fetched is selected to display its properties in the
  229. dialog box.
  230. Arguments:
  231. None.
  232. Return Value:
  233. Boolean status - TRUE = success
  234. --*/
  235. {
  236. ISystemMonitor *pObj = NULL;
  237. CImpISystemMonitor *pPrivObj = NULL;
  238. ICounterItem *pItem;
  239. ICounterItem *pSelectedItem = NULL;
  240. PItemInfo pInfo;
  241. INT nCtr;
  242. INT nSelCtr = LB_ERR;
  243. INT iIndex;
  244. INT nChar;
  245. BOOL bStat = TRUE;
  246. BSTR bstrPath;
  247. HRESULT dwResult;
  248. PPDH_COUNTER_PATH_ELEMENTS pCounter;
  249. InitDialog();
  250. // Must be at least one control object and only the first is used
  251. if (m_cObjects == 0) {
  252. bStat = FALSE;
  253. } else {
  254. pObj = m_ppISysmon[0];
  255. if ( NULL != pObj ) {
  256. pPrivObj = (CImpISystemMonitor*)pObj;
  257. }
  258. }
  259. if ( bStat && NULL != pObj && NULL != pPrivObj ) {
  260. // Request each counter from the control, stopping on failure
  261. nCtr = 0;
  262. pPrivObj->GetSelectedCounter( &pSelectedItem );
  263. while (SUCCEEDED(pObj->Counter(nCtr, &pItem))) {
  264. // Create ItemInfo to hold the counter
  265. pInfo = new ItemInfo;
  266. if (pInfo == NULL) {
  267. bStat = FALSE;
  268. break;
  269. }
  270. ZeroMemory(pInfo, sizeof(ItemInfo));
  271. pInfo->pItem = pItem;
  272. pItem->get_Path( &bstrPath );
  273. if (bstrPath != NULL) {
  274. #if UNICODE
  275. nChar = lstrlen(bstrPath) + 1;
  276. #else
  277. nChar = (wcslen(bstrPath) + 1) * 2;
  278. #endif
  279. pInfo->pszPath = new TCHAR [nChar];
  280. if (pInfo->pszPath == NULL) {
  281. delete pInfo;
  282. pInfo = NULL;
  283. SysFreeString(bstrPath);
  284. bStat = FALSE;
  285. break;
  286. }
  287. #if UNICODE
  288. lstrcpy(pInfo->pszPath, bstrPath);
  289. #else
  290. WideCharToMultiByte(CP_ACP, 0, bstrPath, nChar,
  291. pInfo->pszPath, nChar, NULL, NULL);
  292. #endif
  293. SysFreeString(bstrPath);
  294. }
  295. dwResult = InsertCounterToHashTable(pInfo->pszPath, &pCounter);
  296. if (dwResult == ERROR_SUCCESS) {
  297. //
  298. // Add the counter to the list box
  299. //
  300. iIndex = AddItemToList(pInfo);
  301. if ( LB_ERR == iIndex ) {
  302. RemoveCounterFromHashTable(pInfo->pszPath, pCounter);
  303. bStat = FALSE;
  304. DeleteInfo(pInfo);
  305. pInfo = NULL;
  306. break;
  307. } else {
  308. pInfo->pCounter = pCounter;
  309. if ( pSelectedItem == pItem ) {
  310. nSelCtr = iIndex;
  311. }
  312. }
  313. }
  314. else {
  315. bStat = FALSE;
  316. DeleteInfo(pInfo);
  317. pInfo = NULL;
  318. break;
  319. }
  320. nCtr++;
  321. }
  322. if ( NULL != pSelectedItem ) {
  323. pSelectedItem->Release();
  324. }
  325. // Get the current visuals fron the control
  326. // and initialize the property dialog
  327. pPrivObj->GetVisuals(&m_props.rgbColor, &m_props.iColorIndex, &m_props.iWidthIndex, &m_props.iStyleIndex);
  328. // If a counter matches the selected counter, select that item.
  329. // Else if the visuals match an existing item, select that item.
  330. // Else if there is at least one counter in the control, select the first counter.
  331. // Otherwise, set the display properties to the first counter to be added.
  332. if ( LB_ERR != nSelCtr ) {
  333. SelectItem ( nSelCtr );
  334. } else {
  335. if ( LB_ERR == SelectMatchingItem (
  336. m_props.iColorIndex,
  337. m_props.rgbColor,
  338. m_props.iWidthIndex,
  339. m_props.iStyleIndex ) )
  340. {
  341. if ( 0 < nCtr ) {
  342. SelectItem ( 0 );
  343. } else {
  344. // Init the scale factor to the default
  345. m_props.iScaleIndex = 0;
  346. // If nothing selected, ensure that the color index is set to
  347. // a standard color.
  348. if ( m_props.iColorIndex == NumStandardColorIndices() ) {
  349. m_props.iColorIndex -= 1;
  350. }
  351. CBSetSelection(DialogControl(m_hDlg, IDC_LINECOLOR), m_props.iColorIndex);
  352. CBSetSelection(DialogControl(m_hDlg, IDC_LINEWIDTH), m_props.iWidthIndex);
  353. CBSetSelection(DialogControl(m_hDlg, IDC_LINESTYLE), m_props.iStyleIndex);
  354. CBSetSelection(DialogControl(m_hDlg, IDC_LINESCALE), m_props.iScaleIndex);
  355. SetStyleComboEnable();
  356. }
  357. }
  358. }
  359. }
  360. return bStat;
  361. }
  362. INT
  363. CCounterPropPage::AddItemToList (
  364. IN PItemInfo pInfo
  365. )
  366. /*++
  367. Routine Description:
  368. AddItemToList adds a counter's path name to the dialog list box and
  369. attaches a pointer to the counter's ItemInfo structure as item data.
  370. It also adjusts the horizontal scroll of the list box.
  371. Arguments:
  372. pInfo - Pointer to counter's ItemInfo structure
  373. Return Value:
  374. List box index of added counter (LB_ERR on failure)
  375. --*/
  376. {
  377. INT iIndex;
  378. HWND hwndList = DialogControl(m_hDlg, IDC_CTRLIST);
  379. DWORD dwItemExtent = 0;
  380. HDC hDC = NULL;
  381. iIndex = (INT)LBAdd(hwndList, pInfo->pszPath);
  382. if ( LB_ERR != iIndex && LB_ERRSPACE != iIndex ) {
  383. LBSetData(hwndList, iIndex, pInfo);
  384. hDC = GetDC ( hwndList );
  385. if ( NULL != hDC ) {
  386. dwItemExtent = (DWORD)TextWidth ( hDC, pInfo->pszPath );
  387. if (dwItemExtent > m_dwMaxHorizListExtent) {
  388. m_dwMaxHorizListExtent = dwItemExtent;
  389. LBSetHorzExtent ( hwndList, dwItemExtent );
  390. }
  391. ReleaseDC (hwndList, hDC) ;
  392. }
  393. } else {
  394. iIndex = LB_ERR ;
  395. }
  396. return iIndex;
  397. }
  398. VOID
  399. CCounterPropPage::LoadItemProps (
  400. IN PItemInfo pInfo
  401. )
  402. /*++
  403. Routine Description:
  404. LoadItemProps loads the properties of the selected counter through the
  405. counter's interface into the ItemInfo structure, if not already loaded.
  406. Arguments:
  407. pInfo - pointer to item info
  408. Return Value:
  409. None.
  410. --*/
  411. {
  412. // If properties not loaded for this item, get them now
  413. if (pInfo->pItem && !pInfo->fLoaded) {
  414. INT iScaleFactor;
  415. INT iStyle;
  416. INT iWidth;
  417. pInfo->pItem->get_Color ( &pInfo->Props.rgbColor );
  418. pInfo->pItem->get_ScaleFactor ( &iScaleFactor );
  419. pInfo->pItem->get_Width ( &iWidth );
  420. pInfo->pItem->get_LineStyle ( &iStyle );
  421. // Translate to combo box indices
  422. pInfo->Props.iColorIndex = ColorToIndex ( pInfo->Props.rgbColor );
  423. pInfo->Props.iStyleIndex = StyleToIndex ( iStyle );
  424. pInfo->Props.iWidthIndex = WidthToIndex ( iWidth );
  425. pInfo->Props.iScaleIndex = ScaleFactorToIndex ( iScaleFactor );
  426. pInfo->fLoaded = TRUE;
  427. }
  428. return;
  429. }
  430. VOID
  431. CCounterPropPage::DisplayItemProps (
  432. IN PItemInfo pInfo
  433. )
  434. /*++
  435. Routine Description:
  436. DisplayItemProps displays the properties of the selected counter on the
  437. property page dialog. If the counter is being displayed for the first time
  438. the properties are obtained through the counter's interface and are loaded
  439. into the ItemInfo structure.
  440. Arguments:
  441. pInfo - pointer to item info
  442. Return Value:
  443. None.
  444. --*/
  445. {
  446. // Get number of items in color combo box
  447. HWND hWndColor = DialogControl(m_hDlg, IDC_LINECOLOR);
  448. INT iCurrentColorCnt = CBNumItems(hWndColor);
  449. // If properties not loaded for this item, get them now
  450. LoadItemProps ( pInfo );
  451. // Display the properties
  452. m_props = pInfo->Props;
  453. // Handle custom color
  454. if ( iCurrentColorCnt > NumStandardColorIndices() ) {
  455. // Delete the custom color item. It is stored at
  456. // the end of the list.
  457. CBDelete(hWndColor, iCurrentColorCnt - 1);
  458. }
  459. // If new custom color, add it at the end of the list.
  460. if ( NumStandardColorIndices() == m_props.iColorIndex )
  461. CBAdd( hWndColor, (INT_PTR)m_props.iColorIndex );
  462. CBSetSelection(hWndColor, m_props.iColorIndex);
  463. CBSetSelection(DialogControl(m_hDlg, IDC_LINEWIDTH), m_props.iWidthIndex);
  464. CBSetSelection(DialogControl(m_hDlg, IDC_LINESTYLE), m_props.iStyleIndex);
  465. CBSetSelection(DialogControl(m_hDlg, IDC_LINESCALE), m_props.iScaleIndex);
  466. SetStyleComboEnable();
  467. }
  468. BOOL
  469. CCounterPropPage::SetProperties (
  470. VOID
  471. )
  472. /*++
  473. Routine Description:
  474. SetProperties applies the counter changes the user has made. It calls the
  475. control's AddCounter and DeleteCounter to adjust the counter set. It calls
  476. the counter's property functions for all new and changed counters.
  477. The counters to be deleted are in the pInfoDeleted linked list. The other
  478. counters are obtained from the dialog list box.
  479. Arguments:
  480. None.
  481. Return Value:
  482. Boolean status - TRUE = success
  483. --*/
  484. {
  485. HWND hwndList;
  486. INT iItemCnt;
  487. INT i;
  488. PItemInfo pInfo, pInfoNext;
  489. ISystemMonitor *pObj;
  490. CImpISystemMonitor *pPrivObj;
  491. // Apply changes to first control
  492. pObj = m_ppISysmon[0];
  493. if ( NULL != pObj ) {
  494. // For all items in the delete list
  495. pInfo = m_pInfoDeleted;
  496. while (pInfo) {
  497. // If this counter exists in the control
  498. if (pInfo->pItem != NULL) {
  499. // Tell control to remove it
  500. pObj->DeleteCounter(pInfo->pItem);
  501. }
  502. // Delete the Info structure and point to the next one
  503. pInfoNext = pInfo->pNextInfo;
  504. DeleteInfo(pInfo);
  505. pInfo = pInfoNext;
  506. }
  507. m_pInfoDeleted = NULL;
  508. // Get number of items in list box
  509. hwndList = DialogControl(m_hDlg, IDC_CTRLIST);
  510. iItemCnt = LBNumItems(hwndList);
  511. //assert( IsWindowUnicode(hwndList) );
  512. // For each item
  513. for (i=0; i<iItemCnt; i++) {
  514. pInfo = (PItemInfo)LBData(hwndList,i);
  515. // If new item, create it now
  516. if (pInfo->pItem == NULL) {
  517. #if UNICODE
  518. pObj->AddCounter(pInfo->pszPath, &pInfo->pItem);
  519. #else
  520. INT nChar = lstrlen(pInfo->pszPath);
  521. LPWSTR pszPathW = new WCHAR [nChar + 1];
  522. if (pszPathW) {
  523. MultiByteToWideChar(CP_ACP, 0, pInfo->pszPath, nChar+1, pszPathW, nChar+1);
  524. pObj->AddCounter(pszPathW, &pInfo->pItem);
  525. delete pszPathW;
  526. }
  527. #endif
  528. }
  529. // If item has changed, put the new properties
  530. if (pInfo->pItem != NULL && pInfo->fChanged) {
  531. // iColorIndex is used to determine standard colors.
  532. if ( pInfo->Props.iColorIndex < NumStandardColorIndices() ) {
  533. pInfo->pItem->put_Color(IndexToStandardColor( pInfo->Props.iColorIndex) );
  534. } else {
  535. pInfo->pItem->put_Color(pInfo->Props.rgbColor);
  536. }
  537. pInfo->pItem->put_Width(IndexToWidth(pInfo->Props.iWidthIndex));
  538. pInfo->pItem->put_LineStyle(IndexToStyle(pInfo->Props.iStyleIndex));
  539. pInfo->pItem->put_ScaleFactor(IndexToScaleFactor( pInfo->Props.iScaleIndex ) );
  540. pInfo->fChanged = FALSE;
  541. }
  542. }
  543. // Tell graph to redraw itself
  544. pObj->UpdateGraph();
  545. } // else report internal error
  546. return TRUE;
  547. }
  548. VOID
  549. CCounterPropPage::InitDialog (
  550. VOID
  551. )
  552. /*++
  553. Routine Description:
  554. InitDialog loads each attribute combo box with its list of choices and
  555. selects the default choice. The graphical attributes are owner drawn, so
  556. their list items are just set to numerical indices. The scale attribute
  557. list is filled with numeric strings representing scale factors plus a
  558. default selection.
  559. Arguments:
  560. None.
  561. Return Value:
  562. None.
  563. --*/
  564. {
  565. HWND hWndColors;
  566. HWND hWndWidths;
  567. HWND hWndStyles;
  568. HWND hWndScales;
  569. INT i ;
  570. double ScaleFactor ;
  571. TCHAR tempBuff[30] ;
  572. if (m_hDlg == NULL)
  573. return;
  574. //assert( IsWindowUnicode( m_hDlg ) );
  575. // Load the colors combobox, select the default color.
  576. hWndColors = DialogControl (m_hDlg, IDC_LINECOLOR) ;
  577. for (i = 0 ; i < NumStandardColorIndices () ; i++)
  578. CBAdd (hWndColors, (INT_PTR)1); // string pointer is unused. Fill with
  579. // arbitrary value.
  580. CBSetSelection (hWndColors, 0) ;
  581. // Load the widths combo box, select the default width.
  582. hWndWidths = DialogControl (m_hDlg, IDC_LINEWIDTH) ;
  583. for (i = 0 ; i < NumWidthIndices () ; i++)
  584. CBAdd (hWndWidths, (INT_PTR)1) ;
  585. CBSetSelection (hWndWidths, 0) ;
  586. // Load the styles combo box, select the default style.
  587. hWndStyles = DialogControl (m_hDlg, IDC_LINESTYLE) ;
  588. for (i = 0 ; i < NumStyleIndices () ; i++)
  589. CBAdd (hWndStyles, (INT_PTR)1) ;
  590. CBSetSelection (hWndStyles, 0) ;
  591. // Init the scale combo box.
  592. hWndScales = DialogControl (m_hDlg, IDC_LINESCALE) ;
  593. CBAdd (hWndScales, ResourceString(IDS_DEFAULT)) ;
  594. // Generate power of 10 scale factors
  595. ScaleFactor = pow (10.0f, (double)PDH_MIN_SCALE);
  596. for (i = PDH_MIN_SCALE ; i <= PDH_MAX_SCALE ; i++) {
  597. FormatNumber (
  598. ScaleFactor,
  599. tempBuff,
  600. 30,
  601. (i <= 0 ? (-1 * i) + 1 : i + 1),
  602. (i < 0 ? (-1 * i) : 1) );
  603. CBAdd (hWndScales, tempBuff) ;
  604. ScaleFactor *= (double) 10.0f ;
  605. }
  606. CBSetSelection (hWndScales, 0) ;
  607. ClearCountersHashTable();
  608. }
  609. void
  610. CCounterPropPage::IncrementLocalVisuals (
  611. void
  612. )
  613. {
  614. // Increment the visual indices in color, width, style order
  615. if (++m_props.iColorIndex >= NumStandardColorIndices()) {
  616. m_props.iColorIndex = 0;
  617. if (++m_props.iWidthIndex >= NumWidthIndices()) {
  618. m_props.iWidthIndex = 0;
  619. if (++m_props.iStyleIndex < NumStyleIndices()) {
  620. m_props.iStyleIndex = 0;
  621. }
  622. }
  623. }
  624. SetModifiedSelectedVisuals ( FALSE );
  625. return;
  626. }
  627. HRESULT
  628. CCounterPropPage::NewItem (
  629. IN LPTSTR pszPath,
  630. IN DWORD /* dwFlags */
  631. )
  632. /*++
  633. Routine Description:
  634. NewItem adds a new counter to the dialog's counter list box. It first
  635. creates a new ItemInfo structure and loads it with the counter pathname
  636. string. Then the ItemInfo is added to the dialog list box.
  637. Arguments:
  638. pszPath - Pointer to counter pathname string
  639. fGenerated - TRUE if path was generated from a wildcard path
  640. Return Value:
  641. Index of new item in counter list (-1 if failed to add)
  642. --*/
  643. {
  644. PItemInfo pInfo;
  645. INT i;
  646. HWND hwndList = DialogControl(m_hDlg, IDC_CTRLIST);
  647. HRESULT dwResult;
  648. BOOL bRet;
  649. PPDH_COUNTER_PATH_ELEMENTS pCounter;
  650. dwResult = InsertCounterToHashTable(pszPath, &pCounter);
  651. if (dwResult != ERROR_SUCCESS) {
  652. return dwResult;
  653. }
  654. // Allocate ItemInfo structure
  655. pInfo = NULL;
  656. pInfo = new ItemInfo;
  657. if (pInfo == NULL) {
  658. bRet = RemoveCounterFromHashTable(pszPath, pCounter);
  659. assert(bRet);
  660. return E_OUTOFMEMORY;
  661. }
  662. // Mark as loaded to prevent requesting attributes from control
  663. // Mark as changed so sttribute will be written
  664. pInfo->fLoaded = TRUE;
  665. pInfo->fChanged = TRUE;
  666. // Actual counter doesn't exist yet
  667. pInfo->pItem = NULL;
  668. // If a counter is selected, we're showing its visuals
  669. // so increment them for the new counter
  670. if (m_pInfoSel != NULL) {
  671. IncrementLocalVisuals();
  672. }
  673. else {
  674. // Point to the new item so the visuals are incremented
  675. // for the next one
  676. m_pInfoSel = pInfo;
  677. }
  678. // Set default scaling
  679. m_props.iScaleIndex = 0;
  680. // Color is non-standard only if user is able to build a color.
  681. if( m_props.iColorIndex < NumStandardColorIndices() )
  682. m_props.rgbColor = IndexToStandardColor( m_props.iColorIndex );
  683. else
  684. m_props.rgbColor = pInfo->Props.rgbColor;
  685. // Copy properties to new counter
  686. pInfo->Props = m_props;
  687. // Make own copy of path name string
  688. pInfo->pszPath = new TCHAR [lstrlen(pszPath) + 1];
  689. if (pInfo->pszPath == NULL)
  690. {
  691. bRet = RemoveCounterFromHashTable(pszPath, pCounter);
  692. assert(bRet);
  693. delete pInfo;
  694. return E_OUTOFMEMORY;
  695. }
  696. lstrcpy(pInfo->pszPath, pszPath);
  697. // Add to dialog's counter list
  698. pInfo->pCounter = pCounter;
  699. m_iAddIndex = AddItemToList(pInfo);
  700. return S_OK;
  701. }
  702. VOID
  703. CCounterPropPage::SelectItem (
  704. IN INT iItem
  705. )
  706. /*++
  707. Routine Description:
  708. SelectItem selects a specified counter item in the dialog counter list.
  709. It then displays the selected counter's properties and enables the
  710. "Delete Counter" button.
  711. SelectItem can be called with a -1 to deselect all counters and disable
  712. the delete button.
  713. The member variable, m_pInfoSel, is updated to point to the selected
  714. counter info.
  715. Arguments:
  716. iItem - List index of counter item to select, or -1 to deselect all
  717. Return Value:
  718. None.
  719. --*/
  720. {
  721. HWND hWnd;
  722. hWnd = DialogControl(m_hDlg, IDC_CTRLIST);
  723. // Translate index into item pointer
  724. if (iItem == -1) {
  725. m_pInfoSel = NULL;
  726. }
  727. else {
  728. m_pInfoSel = (PItemInfo)LBData(hWnd, iItem);
  729. if ((INT_PTR)m_pInfoSel == LB_ERR)
  730. m_pInfoSel = NULL;
  731. }
  732. // Select the item, display properties, and enable delete button
  733. if (m_pInfoSel != NULL) {
  734. LBSetSelection(hWnd, iItem);
  735. DisplayItemProps(m_pInfoSel);
  736. DialogEnable(m_hDlg,IDC_DELCTR,1);
  737. }
  738. else {
  739. LBSetSelection(hWnd, (WPARAM)-1);
  740. DialogEnable(m_hDlg,IDC_DELCTR,0);
  741. }
  742. }
  743. VOID
  744. CCounterPropPage::DeleteItem (
  745. VOID
  746. )
  747. /*++
  748. Routine Description:
  749. DeleteItem removes the currently selected counter from the dialog's counter
  750. listbox. It adds the item to the deletion list, so the actual counter can
  751. be deleted from the control when (and if) the changes are applied.
  752. The routine selects selects the next counter in the listbox if there is one.
  753. Arguments:
  754. None.
  755. Return Value:
  756. None.
  757. --*/
  758. {
  759. HWND hWnd;
  760. INT iIndex;
  761. PItemInfo pInfo;
  762. DWORD dwItemExtent = 0;
  763. HDC hDC = NULL;
  764. // Get selected index
  765. hWnd = DialogControl(m_hDlg, IDC_CTRLIST);
  766. iIndex = LBSelection(hWnd);
  767. if (iIndex == LB_ERR)
  768. return;
  769. // Get selected item info
  770. pInfo = (PItemInfo)LBData(hWnd, iIndex);
  771. // Move it to the "Deleted" list.
  772. pInfo->pNextInfo = m_pInfoDeleted;
  773. m_pInfoDeleted = pInfo;
  774. // Remove the string from the list box.
  775. LBDelete(hWnd, iIndex);
  776. // Remove the counter from hash table
  777. RemoveCounterFromHashTable(pInfo->pszPath, pInfo->pCounter);
  778. // Select next item if possible, else the previous
  779. if (iIndex == LBNumItems(hWnd))
  780. iIndex--;
  781. SelectItem(iIndex);
  782. // Clear the max horizontal extent and recalculate
  783. m_dwMaxHorizListExtent = 0;
  784. hDC = GetDC ( hWnd );
  785. if ( NULL != hDC ) {
  786. for ( iIndex = 0; iIndex < (INT)LBNumItems ( hWnd ); iIndex++ ) {
  787. pInfo = (PItemInfo)LBData(hWnd, iIndex);
  788. dwItemExtent = (DWORD)TextWidth ( hDC, pInfo->pszPath );
  789. if (dwItemExtent > m_dwMaxHorizListExtent) {
  790. m_dwMaxHorizListExtent = dwItemExtent;
  791. }
  792. }
  793. ReleaseDC (hWnd, hDC) ;
  794. }
  795. LBSetHorzExtent ( hWnd, m_dwMaxHorizListExtent );
  796. // Set change flag to enable "Apply" button
  797. SetChange();
  798. }
  799. static HRESULT
  800. AddCallback (
  801. LPTSTR pszPathName,
  802. DWORD_PTR lpUserData,
  803. DWORD dwFlags
  804. )
  805. {
  806. CCounterPropPage* pObj = (CCounterPropPage*)lpUserData;
  807. return pObj->NewItem(pszPathName, dwFlags);
  808. }
  809. VOID
  810. CCounterPropPage::AddCounters (
  811. VOID
  812. )
  813. /*++
  814. Routine Description:
  815. AddCounters invokes the counter browser to select new counters.
  816. The browser calls the AddCallback function for each new counter.
  817. AddCallback passes the counter path on to the NewItem method.
  818. Arguments:
  819. None.
  820. Return Value:
  821. None.
  822. --*/
  823. {
  824. HRESULT hr = NOERROR;
  825. HLOG hDataSource;
  826. VARIANT_BOOL bMonitorDuplicateInstances = FALSE;
  827. ISystemMonitor *pObj = m_ppISysmon[0];
  828. CImpISystemMonitor *pPrivObj;
  829. eDataSourceTypeConstant eDataSource = sysmonNullDataSource;
  830. USES_CONVERSION
  831. pPrivObj = (CImpISystemMonitor*)pObj;
  832. m_iAddIndex = -1;
  833. // Browse counters (calling AddCallack for each selected counter)
  834. hr = pObj->get_MonitorDuplicateInstances(&bMonitorDuplicateInstances);
  835. if (SUCCEEDED(hr)) {
  836. hr = pObj->get_DataSourceType(& eDataSource);
  837. }
  838. if (SUCCEEDED(hr)) {
  839. // Cannot call pObj->BrowseCounter() because using callback method
  840. // private to this file.
  841. if ( sysmonLogFiles == eDataSource
  842. || sysmonSqlLog == eDataSource ) {
  843. hDataSource = pPrivObj->GetDataSourceHandle();
  844. assert ( NULL != hDataSource );
  845. } else {
  846. hDataSource = H_REALTIME_DATASOURCE;
  847. }
  848. if (SUCCEEDED(hr)) {
  849. BrowseCounters(
  850. hDataSource,
  851. PERF_DETAIL_WIZARD,
  852. m_hDlg,
  853. AddCallback,
  854. (LPVOID) this,
  855. (BOOL) bMonitorDuplicateInstances);
  856. }
  857. } else {
  858. // Todo: Error message
  859. }
  860. // if any items added, select the last one
  861. if (m_iAddIndex != -1) {
  862. SelectItem(m_iAddIndex);
  863. m_iAddIndex = -1;
  864. // Set change to enable "Apply" button
  865. SetChange();
  866. }
  867. return;
  868. }
  869. VOID
  870. CCounterPropPage::DialogItemChange (
  871. IN WORD wId,
  872. IN WORD wMsg
  873. )
  874. /*++
  875. Routine Description:
  876. DialogItemChange processes window messages sent to any of the property
  877. page dialog controls. When the counter listbox selection changes, it
  878. selects the new counter item and displays its properties. When a change is
  879. made to a property combo box, it updates the property for the currently
  880. selected counter item. When the add or delete counter button is pressed,
  881. it calls the appropriate property page functions.
  882. Arguments:
  883. wID - Dialog control ID
  884. wMsg - Notification code
  885. Return Value:
  886. None.
  887. --*/
  888. {
  889. INT iIndex;
  890. INT iNewProp;
  891. HWND hWnd;
  892. // Case on control ID
  893. switch (wId) {
  894. case IDC_CTRLIST:
  895. // If selection changed
  896. if (wMsg == LBN_SELCHANGE) {
  897. // Get selected index
  898. hWnd = DialogControl(m_hDlg, IDC_CTRLIST);
  899. iIndex = LBSelection(hWnd);
  900. // Select the counter item
  901. if (iIndex != LB_ERR) {
  902. m_pInfoSel = (PItemInfo)LBData(hWnd, iIndex);
  903. DisplayItemProps(m_pInfoSel);
  904. DialogEnable(m_hDlg, IDC_DELCTR, 1);
  905. }
  906. }
  907. break;
  908. case IDC_LINECOLOR:
  909. case IDC_LINEWIDTH:
  910. case IDC_LINESTYLE:
  911. case IDC_LINESCALE:
  912. // If selection changed and a counter is selected
  913. if (wMsg == CBN_SELCHANGE) {
  914. hWnd = DialogControl(m_hDlg, wId);
  915. iNewProp = (INT)CBSelection(hWnd);
  916. // Store the new property selection
  917. switch (wId) {
  918. case IDC_LINECOLOR:
  919. m_props.iColorIndex = iNewProp;
  920. // If iColorIndex is for the custom color, the
  921. // custom color is already set in the properties.
  922. break;
  923. case IDC_LINEWIDTH:
  924. m_props.iWidthIndex = iNewProp;
  925. SetStyleComboEnable();
  926. break;
  927. case IDC_LINESTYLE:
  928. m_props.iStyleIndex = iNewProp;
  929. break;
  930. case IDC_LINESCALE:
  931. m_props.iScaleIndex = iNewProp;
  932. break;
  933. }
  934. // If counter is selected, update its properties
  935. if (m_pInfoSel != NULL) {
  936. m_pInfoSel->Props = m_props;
  937. // mark the counter as changed
  938. m_pInfoSel->fChanged = TRUE;
  939. SetChange();
  940. SetModifiedSelectedVisuals( TRUE );
  941. }
  942. }
  943. break;
  944. case IDC_ADDCTR:
  945. // Invoke counter browser to add to counter
  946. AddCounters();
  947. break;
  948. case IDC_DELCTR:
  949. // Delete the currently selected counter
  950. DeleteItem();
  951. break;
  952. }
  953. }
  954. VOID
  955. CCounterPropPage::MeasureItem (
  956. OUT PMEASUREITEMSTRUCT pMI
  957. )
  958. {
  959. pMI->CtlType = ODT_COMBOBOX ;
  960. pMI->CtlID = IDC_LINECOLOR ;
  961. pMI->itemData = 0 ;
  962. pMI->itemWidth = 0 ;
  963. pMI->itemHeight = 14 ;
  964. }
  965. VOID
  966. CCounterPropPage::DrawItem (
  967. IN PDRAWITEMSTRUCT pDI
  968. )
  969. /*++
  970. Routine Description:
  971. DrawItem draws a specified item in one of the graphical property combo
  972. boxes. It is called to process WM_DRAWITEM messages.
  973. Arguments:
  974. pDI - Pointer to DRAWITEMSTRUCT
  975. Return Value:
  976. None.
  977. --*/
  978. {
  979. HDC hDC ;
  980. PRECT prect ;
  981. INT itemID,
  982. CtlID,
  983. itemAction ;
  984. HPEN hPen;
  985. COLORREF rgbBk, rgbOldBk;
  986. if ( NULL != pDI ) {
  987. hDC = pDI->hDC ;
  988. CtlID = pDI->CtlID ;
  989. prect = &pDI->rcItem ;
  990. itemID = pDI->itemID ;
  991. itemAction = pDI->itemAction ;
  992. // Case on drawing request
  993. switch (itemAction) {
  994. case ODA_SELECT:
  995. // Draw/erase selection rect
  996. HandleSelectionState(pDI);
  997. break;
  998. case ODA_FOCUS:
  999. // Draw/erase focus rect
  1000. HandleFocusState (pDI);
  1001. break;
  1002. case ODA_DRAWENTIRE:
  1003. // Leave border space for focus rectangle
  1004. InflateRect (prect, -OWNER_DRAWN_ITEM, -OWNER_DRAWN_ITEM) ;
  1005. // Case on Control ID
  1006. switch (CtlID) {
  1007. case IDC_LINECOLOR:
  1008. // Draw filled rect of item's color
  1009. if ( itemID < NumStandardColorIndices() )
  1010. Fill(hDC, IndexToStandardColor(itemID), prect);
  1011. else
  1012. // Custom color item only exists if the currently
  1013. // selected item has a custom color defined.
  1014. Fill(hDC, m_pInfoSel->Props.rgbColor, prect);
  1015. break ;
  1016. case IDC_LINEWIDTH:
  1017. case IDC_LINESTYLE:
  1018. // Clear the item's area
  1019. rgbBk = GetSysColor(COLOR_WINDOW);
  1020. Fill(hDC, rgbBk, prect);
  1021. // Draw centered line showing item's width or style
  1022. if (CtlID == IDC_LINEWIDTH)
  1023. hPen = CreatePen (PS_SOLID, IndexToWidth(itemID), RGB (0,0,0));
  1024. else
  1025. hPen = CreatePen (IndexToStyle(itemID), 1, RGB (0,0,0));
  1026. if ( NULL != hPen ) {
  1027. // Set background to insure dashed lines show properly
  1028. rgbOldBk = SetBkColor (hDC, rgbBk) ;
  1029. if ( CLR_INVALID != rgbOldBk ) {
  1030. Line(hDC, (HPEN)hPen, prect->left + 8,
  1031. (prect->top + prect->bottom) / 2,
  1032. prect->right - 8,
  1033. (prect->top + prect->bottom) / 2);
  1034. SetBkColor (hDC, rgbOldBk) ;
  1035. }
  1036. DeleteObject (hPen) ;
  1037. }
  1038. break ;
  1039. }
  1040. // Restore original rect and draw focus/select rects
  1041. InflateRect (prect, OWNER_DRAWN_ITEM, OWNER_DRAWN_ITEM) ;
  1042. HandleSelectionState (pDI) ;
  1043. HandleFocusState (pDI) ;
  1044. }
  1045. }
  1046. }
  1047. INT
  1048. CCounterPropPage::ScaleFactorToIndex (
  1049. IN INT iScaleFactor
  1050. )
  1051. /*++
  1052. Routine Description:
  1053. ScaleFactorToIndex translates a CounterItem ScaleFactor value to
  1054. the appropriate scale factor combo box index.
  1055. Arguments:
  1056. iScaleFactor - CounterItem scale factor integer value.
  1057. Return Value:
  1058. Scale factor combo box index.
  1059. --*/
  1060. {
  1061. INT retValue;
  1062. if ( INT_MAX == iScaleFactor ) {
  1063. retValue = 0;
  1064. } else {
  1065. retValue = iScaleFactor - PDH_MIN_SCALE + 1;
  1066. }
  1067. return retValue;
  1068. }
  1069. INT
  1070. CCounterPropPage::IndexToScaleFactor (
  1071. IN INT iScaleIndex
  1072. )
  1073. /*++
  1074. Routine Description:
  1075. ScaleFactorToIndex translates a CounterItem ScaleFactor value to
  1076. the appropriate scale factor combo box index.
  1077. Arguments:
  1078. iScaleIndex - Scale factor combo box index.
  1079. Return Value:
  1080. CounterItem scale factor integer value.
  1081. --*/
  1082. {
  1083. INT retValue;
  1084. if ( 0 == iScaleIndex ) {
  1085. retValue = INT_MAX;
  1086. } else {
  1087. retValue = iScaleIndex - 1 + PDH_MIN_SCALE;
  1088. }
  1089. return retValue;
  1090. }
  1091. void
  1092. CCounterPropPage::SetStyleComboEnable (
  1093. )
  1094. /*++
  1095. Routine Description:
  1096. SetStyleComboEnable enables the style combo box if the width is 1,
  1097. disables it otherwise.
  1098. Arguments:
  1099. Return Value:
  1100. void
  1101. --*/
  1102. {
  1103. DialogEnable (m_hDlg, IDC_LABEL_LINESTYLE, (0 == m_props.iWidthIndex) );
  1104. DialogEnable (m_hDlg, IDC_LINESTYLE, (0 == m_props.iWidthIndex) );
  1105. }
  1106. HRESULT
  1107. CCounterPropPage::EditPropertyImpl( DISPID dispID )
  1108. {
  1109. HRESULT hr = E_NOTIMPL;
  1110. if ( DISPID_VALUE == dispID ) {
  1111. m_dwEditControl = IDC_ADDCTR;
  1112. hr = S_OK;
  1113. }
  1114. return hr;
  1115. }
  1116. ULONG
  1117. CCounterPropPage::HashCounter(
  1118. LPTSTR szCounterName
  1119. )
  1120. {
  1121. ULONG h = 0;
  1122. ULONG a = 31415; //a, b, k are primes
  1123. const ULONG k = 16381;
  1124. const ULONG b = 27183;
  1125. LPTSTR szThisChar;
  1126. TCHAR Char;
  1127. if (szCounterName) {
  1128. for (szThisChar = szCounterName; * szThisChar; szThisChar ++) {
  1129. Char = * szThisChar;
  1130. if (_istupper(Char) ) {
  1131. Char = _tolower(Char);
  1132. }
  1133. h = (a * h + ((ULONG) Char)) % k;
  1134. a = a * b % (k - 1);
  1135. }
  1136. }
  1137. return (h % eHashTableSize);
  1138. }
  1139. //++
  1140. // Description:
  1141. // Remove a counter path from hash table. One counter
  1142. // path must exactly match the given one in order to be
  1143. // removed, even it is one with wildcard
  1144. //
  1145. // Parameters:
  1146. // pItemInfo - Pointer to item info to be removed
  1147. //
  1148. // Return:
  1149. // Return TRUE if the counter path is removed, otherwis return FALSE
  1150. //--
  1151. BOOL
  1152. CCounterPropPage::RemoveCounterFromHashTable(
  1153. LPTSTR pszPath,
  1154. PPDH_COUNTER_PATH_ELEMENTS pCounter
  1155. )
  1156. {
  1157. ULONG lHashValue;
  1158. PHASH_ENTRY pEntry = NULL;
  1159. PHASH_ENTRY pPrev = NULL;
  1160. BOOL bReturn = FALSE;
  1161. LPTSTR pszFullPath = NULL;
  1162. SetLastError(ERROR_SUCCESS);
  1163. if (pszPath == NULL || pCounter == NULL) {
  1164. SetLastError(ERROR_INVALID_PARAMETER);
  1165. goto ErrorOut;
  1166. }
  1167. //
  1168. // If the counter path does not have machine name,
  1169. // add the machine name to compose a full path
  1170. //
  1171. if (*pszPath == TEXT('\\') && (*(pszPath+1) == TEXT('\\')) ) {
  1172. lHashValue = HashCounter(pszPath);
  1173. }
  1174. else {
  1175. if (pCounter->szMachineName == NULL) {
  1176. SetLastError(ERROR_INVALID_PARAMETER);
  1177. goto ErrorOut;
  1178. }
  1179. pszFullPath = new TCHAR [ lstrlen(pCounter->szMachineName) + lstrlen(pszPath) + 1 ];
  1180. if (pszFullPath == NULL) {
  1181. SetLastError(ERROR_OUTOFMEMORY);
  1182. goto ErrorOut;
  1183. }
  1184. lstrcpy(pszFullPath, pCounter->szMachineName);
  1185. lstrcat(pszFullPath, pszPath);
  1186. lHashValue = HashCounter(pszFullPath);
  1187. }
  1188. pEntry = m_HashTable[lHashValue];
  1189. //
  1190. // Check if there is a counter path which is exactly the same
  1191. // as the given one
  1192. //
  1193. while (pEntry) {
  1194. if (pEntry->pCounter == pCounter)
  1195. break;
  1196. pPrev = pEntry;
  1197. pEntry = pEntry->pNext;
  1198. }
  1199. //
  1200. // If we found it, remove it
  1201. //
  1202. if (pEntry) {
  1203. if (pPrev == NULL) {
  1204. m_HashTable[lHashValue] = pEntry->pNext;
  1205. }
  1206. else {
  1207. pPrev->pNext = pEntry->pNext;
  1208. }
  1209. assert (pEntry->pCounter);
  1210. delete(pEntry->pCounter);
  1211. delete(pEntry);
  1212. bReturn = TRUE;
  1213. }
  1214. ErrorOut:
  1215. if (pszFullPath != NULL) {
  1216. delete(pszFullPath);
  1217. }
  1218. return bReturn;
  1219. }
  1220. //++
  1221. // Description:
  1222. // Insert a counter path into hash table.
  1223. //
  1224. // Parameters:
  1225. // PItemInfo - Pointer to the counter item info
  1226. //
  1227. // Return:
  1228. // Return the pointer to new inserted PDH_COUNTER_PATH_ELEMENTS structure
  1229. //--
  1230. DWORD
  1231. CCounterPropPage::InsertCounterToHashTable(
  1232. LPTSTR pszPath,
  1233. PPDH_COUNTER_PATH_ELEMENTS* ppCounter
  1234. )
  1235. {
  1236. ULONG lHashValue;
  1237. PHASH_ENTRY pEntry = NULL;
  1238. PHASH_ENTRY pPrev = NULL;
  1239. PDH_STATUS pdhStatus;
  1240. ULONG ulBufSize;
  1241. PPDH_COUNTER_PATH_ELEMENTS pCounter = NULL;
  1242. LPTSTR pszFullPath = NULL;
  1243. BOOL bExisted = FALSE;
  1244. DWORD dwResult;
  1245. dwResult = ERROR_SUCCESS;
  1246. if (pszPath == NULL || ppCounter == NULL) {
  1247. dwResult = ERROR_INVALID_PARAMETER;
  1248. goto ErrorOut;
  1249. }
  1250. *ppCounter = NULL;
  1251. //
  1252. // Parse the counter path
  1253. //
  1254. ulBufSize = sizeof(PDH_COUNTER_PATH_ELEMENTS) + sizeof(TCHAR) * MAX_PATH * 5;
  1255. pCounter = (PPDH_COUNTER_PATH_ELEMENTS) new char [ ulBufSize ];
  1256. if (pCounter == NULL) {
  1257. dwResult = ERROR_OUTOFMEMORY;
  1258. goto ErrorOut;
  1259. }
  1260. pdhStatus = PdhParseCounterPath( pszPath, pCounter, & ulBufSize, 0);
  1261. if (pdhStatus != ERROR_SUCCESS) {
  1262. dwResult = pdhStatus;
  1263. goto ErrorOut;
  1264. }
  1265. //
  1266. // If the counter path does not have machine name,
  1267. // add the machine name to compose a full path
  1268. //
  1269. if (*pszPath == TEXT('\\') && (*(pszPath+1) == TEXT('\\')) ) {
  1270. lHashValue = HashCounter(pszPath);
  1271. }
  1272. else {
  1273. pszFullPath = new TCHAR [ lstrlen(pCounter->szMachineName) + lstrlen(pszPath) + 1];
  1274. if (pszFullPath == NULL) {
  1275. dwResult = ERROR_OUTOFMEMORY;
  1276. goto ErrorOut;
  1277. }
  1278. lstrcpy(pszFullPath, pCounter->szMachineName);
  1279. lstrcat(pszFullPath, pszPath);
  1280. lHashValue = HashCounter(pszFullPath);
  1281. }
  1282. //
  1283. // Check if there is a counter path which is exactly the same
  1284. // as the given one
  1285. //
  1286. pEntry = m_HashTable[lHashValue];
  1287. while (pEntry) {
  1288. if ( AreSameCounterPath ( pEntry->pCounter, pCounter ) ) {
  1289. dwResult = SMON_STATUS_DUPL_COUNTER_PATH;
  1290. bExisted = TRUE;
  1291. *ppCounter = pEntry->pCounter;
  1292. break;
  1293. }
  1294. pPrev = pEntry;
  1295. pEntry = pEntry->pNext;
  1296. }
  1297. //
  1298. // Add the new counter path
  1299. //
  1300. if (bExisted == FALSE) {
  1301. pEntry = (PHASH_ENTRY) new HASH_ENTRY;
  1302. if (pEntry == NULL) {
  1303. dwResult = ERROR_OUTOFMEMORY;
  1304. goto ErrorOut;
  1305. }
  1306. pEntry->pCounter = pCounter;
  1307. pEntry->pNext = m_HashTable[lHashValue];
  1308. m_HashTable[lHashValue] = pEntry;
  1309. *ppCounter = pCounter;
  1310. }
  1311. if (pszFullPath != NULL) {
  1312. delete(pszFullPath);
  1313. }
  1314. return dwResult;
  1315. ErrorOut:
  1316. if (pszFullPath != NULL) {
  1317. delete(pszFullPath);
  1318. }
  1319. if (pCounter != NULL) {
  1320. delete ((char*) pCounter);
  1321. }
  1322. return dwResult;
  1323. }
  1324. //++
  1325. // Description:
  1326. // The function clears all the entries in hash table
  1327. // and set hash-table-not-set-up flag
  1328. //
  1329. // Parameters:
  1330. // None
  1331. //
  1332. // Return:
  1333. // None
  1334. //--
  1335. void
  1336. CCounterPropPage::ClearCountersHashTable( void )
  1337. {
  1338. ULONG i;
  1339. PHASH_ENTRY pEntry;
  1340. PHASH_ENTRY pNext;
  1341. if (m_fHashTableSetup) {
  1342. for (i = 0; i < eHashTableSize; i ++) {
  1343. pNext = m_HashTable[i];
  1344. while (pNext != NULL) {
  1345. pEntry = pNext;
  1346. pNext = pEntry->pNext;
  1347. assert( pEntry->pCounter);
  1348. delete pEntry->pCounter;
  1349. delete (pEntry);
  1350. }
  1351. }
  1352. }
  1353. else {
  1354. memset(&m_HashTable, 0, sizeof(m_HashTable));
  1355. }
  1356. m_fHashTableSetup = FALSE;
  1357. }
  1358. void CCounterPropPage::DeleteInfo(PItemInfo pInfo)
  1359. {
  1360. if (pInfo == NULL) {
  1361. return;
  1362. }
  1363. if (pInfo->pszPath != NULL) {
  1364. delete (pInfo->pszPath);
  1365. }
  1366. if ( pInfo->pItem != NULL ) {
  1367. pInfo->pItem->Release();
  1368. }
  1369. delete pInfo;
  1370. }