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.

1093 lines
31 KiB

  1. // SettingsPage.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "pdlcnfig.h"
  5. #include "SetPage.h"
  6. #ifdef _DEBUG
  7. #define new DEBUG_NEW
  8. #undef THIS_FILE
  9. static char THIS_FILE[] = __FILE__;
  10. #endif
  11. /////////////////////////////////////////////////////////////////////////////
  12. // CSettingsPropPage property page
  13. IMPLEMENT_DYNCREATE(CSettingsPropPage, CPropertyPage)
  14. CSettingsPropPage::CSettingsPropPage() : CPropertyPage(CSettingsPropPage::IDD)
  15. {
  16. //{{AFX_DATA_INIT(CSettingsPropPage)
  17. m_IntervalTime = 0;
  18. m_SettingsFile = _T("");
  19. m_IntervalUnitsIndex = -1;
  20. //}}AFX_DATA_INIT
  21. m_hKeyLogSettingsDefault = NULL;
  22. m_hKeyLogService = NULL;
  23. // counter buffer
  24. m_szCounterListBuffer = NULL;
  25. m_dwCounterListBufferSize = 0;
  26. // list box information
  27. m_dwMaxHorizListExtent = 0;
  28. m_lCounterListHasStars = PDLCNFIG_LISTBOX_STARS_DONT_KNOW;
  29. // prototype use only
  30. bServiceStopped = TRUE;
  31. bServicePaused = FALSE;
  32. m_bInitialized = FALSE;
  33. }
  34. CSettingsPropPage::~CSettingsPropPage()
  35. {
  36. if (m_hKeyLogSettingsDefault != NULL) RegCloseKey(m_hKeyLogSettingsDefault);
  37. if (m_hKeyLogService != NULL) RegCloseKey(m_hKeyLogService);
  38. }
  39. void CSettingsPropPage::DoDataExchange(CDataExchange* pDX)
  40. {
  41. CPropertyPage::DoDataExchange(pDX);
  42. //{{AFX_DATA_MAP(CSettingsPropPage)
  43. DDX_Text(pDX, IDC_INTERVAL_TIME, m_IntervalTime);
  44. DDX_CBIndex(pDX, IDC_INTERVAL_UNITS, m_IntervalUnitsIndex);
  45. //}}AFX_DATA_MAP
  46. }
  47. BEGIN_MESSAGE_MAP(CSettingsPropPage, CPropertyPage)
  48. //{{AFX_MSG_MAP(CSettingsPropPage)
  49. ON_BN_CLICKED(IDC_BROWSE_COUNTERS, OnBrowseCounters)
  50. ON_BN_CLICKED(IDC_MAN_START, OnManStart)
  51. ON_BN_CLICKED(IDC_MAN_STOP, OnManStop)
  52. ON_BN_CLICKED(IDC_REMOVE, OnRemove)
  53. ON_BN_CLICKED(IDC_SERVICE_AUTO, OnServiceAuto)
  54. ON_BN_CLICKED(IDC_SERVICE_MAN, OnServiceMan)
  55. ON_NOTIFY(UDN_DELTAPOS, IDC_INTERVAL_SPIN, OnDeltaposIntervalSpin)
  56. ON_CBN_SELCHANGE(IDC_INTERVAL_UNITS, OnSelchangeIntervalUnits)
  57. ON_BN_CLICKED(IDC_REMOVE_SERVICE, OnRemoveService)
  58. ON_EN_CHANGE(IDC_INTERVAL_TIME, OnChangeIntervalTime)
  59. //}}AFX_MSG_MAP
  60. ON_MESSAGE (PSM_QUERYSIBLINGS, OnQuerySiblings)
  61. END_MESSAGE_MAP()
  62. /////////////////////////////////////////////////////////////////////////////
  63. // CSettingsPropPage Helper Functions
  64. void CSettingsPropPage::InitDialogData (void)
  65. {
  66. LONG lStatus = ERROR_INVALID_FUNCTION;
  67. DWORD dwRegValType;
  68. DWORD dwRegValue;
  69. DWORD dwRegValueSize;
  70. DWORD dwIndex;
  71. if (m_bInitialized) return;
  72. if (m_hKeyLogService == NULL) {
  73. // open registry key to service
  74. lStatus = RegOpenKeyEx (
  75. HKEY_LOCAL_MACHINE,
  76. TEXT("SYSTEM\\CurrentControlSet\\Services\\PerfDataLog"),
  77. 0,
  78. KEY_READ | KEY_WRITE,
  79. &m_hKeyLogService);
  80. }
  81. if ((m_hKeyLogSettingsDefault == NULL) &&
  82. (m_hKeyLogService != NULL)) {
  83. // open registry to default log query
  84. lStatus = RegOpenKeyEx (
  85. m_hKeyLogService,
  86. TEXT("Log Queries\\Default"),
  87. 0,
  88. KEY_READ | KEY_WRITE,
  89. &m_hKeyLogSettingsDefault);
  90. }
  91. if (lStatus != ERROR_SUCCESS) {
  92. return;
  93. // display error, close dialog and exit
  94. }
  95. // continue
  96. // set sample time
  97. if (m_IntervalTime == 0) {
  98. dwRegValType = 0;
  99. dwRegValue = 0;
  100. dwRegValueSize = sizeof(DWORD);
  101. lStatus = RegQueryValueEx (
  102. m_hKeyLogSettingsDefault,
  103. TEXT("Sample Interval"),
  104. NULL,
  105. &dwRegValType,
  106. (LPBYTE)&dwRegValue,
  107. &dwRegValueSize);
  108. if ((lStatus == ERROR_SUCCESS) &&
  109. (dwRegValType == REG_DWORD)) {
  110. if ((dwRegValue % SECONDS_IN_DAY) == 0) {
  111. // then this is in days so scale
  112. dwRegValue /= SECONDS_IN_DAY;
  113. dwIndex = SIU_DAYS;
  114. } else if ((dwRegValue % SECONDS_IN_HOUR) == 0) {
  115. // scale to hours
  116. dwRegValue /= SECONDS_IN_HOUR;
  117. dwIndex = SIU_HOURS;
  118. } else if ((dwRegValue % SECONDS_IN_MINUTE) == 0) {
  119. // scale to minutes
  120. dwRegValue /= SECONDS_IN_MINUTE;
  121. dwIndex = SIU_MINUTES;
  122. } else {
  123. // use as seconds
  124. dwIndex = SIU_SECONDS;
  125. }
  126. // check for zero values & apply default if found
  127. if (dwRegValue == 0) {
  128. dwRegValue = 15; // default is 15 sec.
  129. dwIndex = SIU_SECONDS;
  130. }
  131. } else {
  132. // load default values
  133. dwRegValue = 15;
  134. dwIndex = SIU_SECONDS;
  135. }
  136. m_IntervalTime = dwRegValue;
  137. m_IntervalUnitsIndex = dwIndex;
  138. }
  139. return;
  140. }
  141. afx_msg LRESULT CSettingsPropPage::OnQuerySiblings (WPARAM wParam, LPARAM lParam)
  142. {
  143. switch (wParam) {
  144. case PDLCNFIG_PSM_QS_LISTBOX_STARS:
  145. return m_lCounterListHasStars;
  146. case PDLCNFIG_PSM_QS_ARE_YOU_READY:
  147. if (!m_bInitialized) {
  148. InitDialogData();
  149. }
  150. return 0;
  151. default:
  152. return 0; // to pass to the next property page
  153. }
  154. }
  155. LONG CSettingsPropPage::GetCounterListStarInfo (void)
  156. {
  157. return m_lCounterListHasStars;
  158. }
  159. LONG CSettingsPropPage::SetCurrentServiceState (DWORD dwNewState)
  160. {
  161. SC_HANDLE hSC = NULL;
  162. SC_HANDLE hService = NULL;
  163. SERVICE_STATUS ssData;
  164. DWORD dwTimeout = 20;
  165. BOOL bStopped, bPaused;
  166. LONG lStatus;
  167. HCURSOR hOrigCursor;
  168. hOrigCursor = ::SetCursor(::LoadCursor(NULL, IDC_WAIT));
  169. // open SC database
  170. hSC = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS);
  171. if (hSC == NULL) {
  172. lStatus = GetLastError();
  173. ASSERT (lStatus != ERROR_SUCCESS);
  174. }
  175. // open service
  176. hService = OpenService (hSC, TEXT("PerfDataLog"),
  177. SERVICE_START | SERVICE_STOP | SERVICE_PAUSE_CONTINUE);
  178. if (hService != NULL) {
  179. switch (dwNewState) {
  180. case LOG_SERV_START:
  181. StartService (hService, 0, NULL);
  182. // wait for the service to start before returning
  183. while (--dwTimeout) {
  184. GetCurrentServiceState (&bStopped, &bPaused);
  185. if (bStopped) {
  186. Sleep(500);
  187. } else {
  188. break;
  189. }
  190. }
  191. break;
  192. case LOG_SERV_STOP:
  193. ControlService (hService, SERVICE_CONTROL_STOP, &ssData);
  194. // wait for the service to stop before returning
  195. while (--dwTimeout) {
  196. GetCurrentServiceState (&bStopped, &bPaused);
  197. if (!bStopped) {
  198. Sleep(500);
  199. } else {
  200. break;
  201. }
  202. }
  203. break;
  204. case LOG_SERV_PAUSE:
  205. ControlService (hService, SERVICE_CONTROL_PAUSE, &ssData);
  206. // wait for the service to start pause returning
  207. while (--dwTimeout) {
  208. GetCurrentServiceState (&bStopped, &bPaused);
  209. if (!bPaused) {
  210. Sleep(500);
  211. } else {
  212. break;
  213. }
  214. }
  215. break;
  216. case LOG_SERV_RESUME:
  217. ControlService (hService, SERVICE_CONTROL_CONTINUE, &ssData);
  218. // wait for the service to start before returning
  219. while (--dwTimeout) {
  220. GetCurrentServiceState (&bStopped, &bPaused);
  221. if (bPaused) {
  222. Sleep(500);
  223. } else {
  224. break;
  225. }
  226. }
  227. break;
  228. default:
  229. // no change if not recognized
  230. break;
  231. }
  232. CloseServiceHandle (hService);
  233. } else {
  234. lStatus = GetLastError();
  235. ASSERT (lStatus != 0);
  236. }
  237. // close handles
  238. if (hSC != NULL) CloseServiceHandle (hSC);
  239. ::SetCursor (hOrigCursor);
  240. return ERROR_SUCCESS;
  241. }
  242. LONG CSettingsPropPage::GetCurrentServiceState (BOOL * bStopped, BOOL * bPaused)
  243. {
  244. SC_HANDLE hSC = NULL;
  245. SC_HANDLE hService = NULL;
  246. SERVICE_STATUS ssData;
  247. LONG lStatus;
  248. HCURSOR hOrigCursor;
  249. BOOL bServiceStopped, bServicePaused;
  250. hOrigCursor = ::SetCursor(::LoadCursor(NULL, IDC_WAIT));
  251. bServiceStopped = TRUE;
  252. bServicePaused = TRUE;
  253. // open SC database
  254. hSC = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS);
  255. if (hSC == NULL) {
  256. lStatus = GetLastError();
  257. ASSERT (lStatus != ERROR_SUCCESS);
  258. }
  259. // open service
  260. hService = OpenService (hSC, TEXT("PerfDataLog"), SERVICE_INTERROGATE);
  261. // get service status
  262. if (hService != NULL) {
  263. if (ControlService (
  264. hService, SERVICE_CONTROL_INTERROGATE,
  265. &ssData)) {
  266. switch (ssData.dwCurrentState) {
  267. case SERVICE_STOPPED:
  268. bServiceStopped = TRUE;
  269. bServicePaused = FALSE;
  270. break;
  271. case SERVICE_START_PENDING:
  272. bServiceStopped = TRUE;
  273. bServicePaused = FALSE;
  274. break;
  275. case SERVICE_STOP_PENDING:
  276. bServiceStopped = FALSE;
  277. bServicePaused = FALSE;
  278. break;
  279. case SERVICE_RUNNING:
  280. bServiceStopped = FALSE;
  281. bServicePaused = FALSE;
  282. break;
  283. case SERVICE_CONTINUE_PENDING:
  284. bServiceStopped = FALSE;
  285. bServicePaused = FALSE;
  286. break;
  287. case SERVICE_PAUSE_PENDING:
  288. bServiceStopped = FALSE;
  289. bServicePaused = FALSE;
  290. break;
  291. case SERVICE_PAUSED:
  292. bServiceStopped = FALSE;
  293. bServicePaused = TRUE;
  294. break;
  295. default:
  296. bServiceStopped = TRUE;
  297. bServicePaused = TRUE;
  298. ;// no op
  299. }
  300. } else {
  301. bServiceStopped = TRUE;
  302. bServicePaused = TRUE;
  303. }
  304. CloseServiceHandle (hService);
  305. } else {
  306. lStatus = GetLastError();
  307. ASSERT (lStatus != 0);
  308. }
  309. *bStopped = bServiceStopped;
  310. *bPaused = bServicePaused;
  311. // close handles
  312. if (hSC != NULL) CloseServiceHandle (hSC);
  313. ::SetCursor (hOrigCursor);
  314. return ERROR_SUCCESS;
  315. }
  316. UINT
  317. ConnectMachineThreadProc (LPVOID lpArg)
  318. {
  319. return PdhConnectMachine (NULL);
  320. }
  321. LONG CSettingsPropPage::SyncServiceStartWithButtons(void)
  322. {
  323. SC_HANDLE hSC = NULL;
  324. SC_HANDLE hService = NULL;
  325. DWORD dwMoreBytes = 0;
  326. BOOL bManualEnabled = FALSE;
  327. BOOL bUpdate = FALSE;
  328. LONG lStatus;
  329. QUERY_SERVICE_CONFIG qsConfig;
  330. HCURSOR hOrigCursor;
  331. hOrigCursor = ::SetCursor(LoadCursor(NULL, IDC_WAIT));
  332. // get button state
  333. if (IsDlgButtonChecked(IDC_SERVICE_MAN)) {
  334. bManualEnabled = TRUE;
  335. }
  336. // open SC database
  337. hSC = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS);
  338. if (hSC == NULL) {
  339. lStatus = GetLastError();
  340. ASSERT (lStatus != ERROR_SUCCESS);
  341. }
  342. // open service
  343. hService = OpenService (hSC, TEXT("PerfDataLog"),
  344. SERVICE_CHANGE_CONFIG | SERVICE_QUERY_CONFIG);
  345. if (hService != NULL) {
  346. // get current config
  347. memset (&qsConfig, 0, sizeof(qsConfig));
  348. if (QueryServiceConfig (hService, &qsConfig,
  349. sizeof(qsConfig), &dwMoreBytes)) {
  350. // see if the current status is different
  351. // from the selection. if it is, then change
  352. // the current mode.
  353. if (bManualEnabled) {
  354. if (qsConfig.dwStartType == SERVICE_AUTO_START) {
  355. bUpdate = TRUE;
  356. }
  357. } else {
  358. // auto start selected
  359. if (qsConfig.dwStartType == SERVICE_DEMAND_START) {
  360. bUpdate = TRUE;
  361. }
  362. }
  363. } else {
  364. // else unable to read the current status so update anyway
  365. bUpdate = TRUE;
  366. }
  367. if (bUpdate) {
  368. ChangeServiceConfig (
  369. hService,
  370. SERVICE_NO_CHANGE,
  371. (bManualEnabled ? SERVICE_DEMAND_START : SERVICE_AUTO_START),
  372. SERVICE_NO_CHANGE,
  373. NULL,
  374. NULL,
  375. NULL,
  376. NULL,
  377. NULL,
  378. NULL,
  379. NULL);
  380. }
  381. CloseServiceHandle (hService);
  382. } else {
  383. lStatus = GetLastError();
  384. ASSERT (lStatus != 0);
  385. }
  386. // close handles
  387. if (hSC != NULL) CloseServiceHandle (hSC);
  388. ::SetCursor (hOrigCursor);
  389. return ERROR_SUCCESS;
  390. }
  391. void CSettingsPropPage::UpdateManualButtonsState()
  392. {
  393. BOOL bServiceIsStopped;
  394. BOOL bServiceIsPaused;
  395. LONG lStatus;
  396. BOOL bManualEnabled;
  397. if (IsDlgButtonChecked(IDC_SERVICE_AUTO)) {
  398. bManualEnabled = FALSE;
  399. } else if (IsDlgButtonChecked(IDC_SERVICE_MAN)) {
  400. bManualEnabled = TRUE;
  401. } else {
  402. // if no button is checked, then check the auto
  403. // button and continue
  404. CheckRadioButton (IDC_SERVICE_AUTO, IDC_SERVICE_MAN, IDC_SERVICE_AUTO);
  405. bManualEnabled = FALSE;
  406. }
  407. GetDlgItem(IDC_MAN_START)->EnableWindow(bManualEnabled);
  408. GetDlgItem(IDC_MAN_STOP)->EnableWindow(bManualEnabled);
  409. if (bManualEnabled) {
  410. // check with service controller to get the current state of the service
  411. lStatus = GetCurrentServiceState (&bServiceIsStopped, &bServiceIsPaused);
  412. GetDlgItem(IDC_MAN_START)->EnableWindow(bServiceIsStopped);
  413. GetDlgItem(IDC_MAN_STOP)->EnableWindow(!bServiceIsStopped);
  414. }
  415. }
  416. static void DialogCallBack(CSettingsPropPage *pDlg)
  417. {
  418. // add strings in buffer to list box
  419. LPTSTR NewCounterName;
  420. LRESULT lIndex;
  421. PDH_STATUS pdhStatus;
  422. CListBox *cCounterList;
  423. DWORD dwItemExtent;
  424. cCounterList = (CListBox *)pDlg->GetDlgItem(IDC_COUNTER_LIST);
  425. for (NewCounterName = pDlg->m_szCounterListBuffer;
  426. *NewCounterName != 0;
  427. NewCounterName += (lstrlen(NewCounterName) + 1)) {
  428. pdhStatus = PdhValidatePath(NewCounterName);
  429. if (pdhStatus == ERROR_SUCCESS) {
  430. // this is a valid counter so add it to the list
  431. lIndex = cCounterList->AddString(NewCounterName);
  432. // select the current entry in the list box
  433. if (lIndex != LB_ERR) {
  434. if (pDlg->m_lCounterListHasStars != PDLCNFIG_LISTBOX_STARS_YES) {
  435. // save a string compare if this value is already set
  436. if (_tcsstr (NewCounterName, TEXT("*")) == NULL) {
  437. pDlg->m_lCounterListHasStars = PDLCNFIG_LISTBOX_STARS_YES;
  438. }
  439. }
  440. // update list box extent
  441. dwItemExtent = (DWORD)((cCounterList->GetDC())->GetTextExtent (NewCounterName)).cx;
  442. if (dwItemExtent > pDlg->m_dwMaxHorizListExtent) {\
  443. pDlg->m_dwMaxHorizListExtent = dwItemExtent;
  444. cCounterList->SetHorizontalExtent(dwItemExtent);
  445. }
  446. cCounterList->SetSel (-1, FALSE); // cancel existing selections
  447. cCounterList->SetSel ((int)lIndex);
  448. cCounterList->SetCaretIndex ((int)lIndex);
  449. }
  450. } else {
  451. MessageBeep (MB_ICONEXCLAMATION);
  452. }
  453. }
  454. // clear buffer
  455. memset (pDlg->m_szCounterListBuffer, 0, pDlg->m_dwCounterListBufferSize);
  456. }
  457. /////////////////////////////////////////////////////////////////////////////
  458. // CSettingsPropPage message handlers
  459. BOOL CSettingsPropPage::OnInitDialog()
  460. {
  461. LONG lStatus;
  462. DWORD dwRegValType;
  463. DWORD dwRegValue;
  464. DWORD dwRegValueSize;
  465. DWORD dwIndex;
  466. LPTSTR mszCounterPathList;
  467. LPTSTR szThisCounterPath;
  468. CListBox *cCounterList;
  469. DWORD dwItemExtent;
  470. InitDialogData();
  471. // now init other pages
  472. QuerySiblings (PDLCNFIG_PSM_QS_ARE_YOU_READY, 0);
  473. // start machine connection thread to make initial "ADD" dialog
  474. // "snappier"
  475. // AfxBeginThread ((AFX_THREADPROC)ConnectMachineThreadProc, NULL);
  476. // initialize the service state
  477. dwRegValType = 0;
  478. dwRegValue = 0;
  479. dwRegValueSize = sizeof(DWORD);
  480. lStatus = RegQueryValueEx (
  481. m_hKeyLogService,
  482. TEXT("Start"),
  483. NULL,
  484. &dwRegValType,
  485. (LPBYTE)&dwRegValue,
  486. &dwRegValueSize);
  487. if ((lStatus == ERROR_SUCCESS) &&
  488. (dwRegValType == REG_DWORD) &&
  489. (dwRegValue == SERVICE_DEMAND_START)) {
  490. // then set manual control
  491. CheckRadioButton (IDC_SERVICE_AUTO,
  492. IDC_SERVICE_MAN, IDC_SERVICE_MAN);
  493. } else {
  494. // set automatic control (default)
  495. CheckRadioButton (IDC_SERVICE_AUTO,
  496. IDC_SERVICE_MAN, IDC_SERVICE_AUTO);
  497. }
  498. // set manual buttons to reflect current state of control
  499. UpdateManualButtonsState();
  500. // load counter list box
  501. GetDlgItem(IDC_COUNTER_LIST)->SendMessage(LB_RESETCONTENT, 0, 0);
  502. // read path string from registry
  503. // find out buffer size required
  504. dwRegValType = 0;
  505. dwRegValue = 0;
  506. dwRegValueSize = 0;
  507. lStatus = RegQueryValueEx (
  508. m_hKeyLogSettingsDefault,
  509. TEXT("Counter List"),
  510. NULL,
  511. &dwRegValType,
  512. NULL,
  513. &dwRegValueSize);
  514. cCounterList = (CListBox *)GetDlgItem(IDC_COUNTER_LIST);
  515. if (dwRegValueSize > 0) {
  516. // allocate buffer
  517. mszCounterPathList = new TCHAR[dwRegValueSize/sizeof(TCHAR)];
  518. ASSERT (mszCounterPathList != NULL);
  519. *mszCounterPathList = 0;
  520. dwRegValType = 0;
  521. dwRegValue = 0;
  522. lStatus = RegQueryValueEx (
  523. m_hKeyLogSettingsDefault,
  524. TEXT("Counter List"),
  525. NULL,
  526. &dwRegValType,
  527. (LPBYTE)mszCounterPathList,
  528. &dwRegValueSize);
  529. if (lStatus != ERROR_SUCCESS) {
  530. // assign a MSZ termination
  531. mszCounterPathList[0] = 0;
  532. mszCounterPathList[1] = 0;
  533. }
  534. // load list box.
  535. dwIndex = 0;
  536. cCounterList->ResetContent();
  537. for (szThisCounterPath = mszCounterPathList;
  538. *szThisCounterPath != 0;
  539. szThisCounterPath += lstrlen(szThisCounterPath)+1) {
  540. lStatus = cCounterList->AddString (szThisCounterPath);
  541. if (lStatus != LB_ERR) {
  542. if (m_lCounterListHasStars != PDLCNFIG_LISTBOX_STARS_YES) {
  543. // save a string compare if this value is already set
  544. if (_tcsstr (szThisCounterPath, TEXT("*")) == NULL) {
  545. m_lCounterListHasStars = PDLCNFIG_LISTBOX_STARS_YES;
  546. }
  547. }
  548. dwItemExtent = (DWORD)((cCounterList->GetDC())->GetTextExtent (szThisCounterPath)).cx;
  549. if (dwItemExtent > m_dwMaxHorizListExtent) {
  550. m_dwMaxHorizListExtent = dwItemExtent;
  551. cCounterList->SetHorizontalExtent(dwItemExtent);
  552. }
  553. dwIndex++;
  554. }
  555. }
  556. cCounterList->SetSel(dwIndex-1);
  557. cCounterList->SetCaretIndex(dwIndex-1);
  558. delete mszCounterPathList;
  559. } else {
  560. // no counters presently in the list so just initialize everything
  561. cCounterList->ResetContent();
  562. }
  563. // select first counter in list (if present)
  564. if (GetDlgItem(IDC_COUNTER_LIST)->SendMessage(LB_GETCOUNT) > 0) {
  565. GetDlgItem(IDC_COUNTER_LIST)->SendMessage(LB_SETCURSEL, 0, 0);
  566. // highlight remove button if an item is selected
  567. GetDlgItem(IDC_REMOVE)->EnableWindow (TRUE);
  568. } else {
  569. GetDlgItem(IDC_REMOVE)->EnableWindow (FALSE);
  570. }
  571. if (m_lCounterListHasStars == PDLCNFIG_LISTBOX_STARS_DONT_KNOW) {
  572. // if here and the value hasn't been changed, then that means
  573. // there are no wild card entries in the list box
  574. m_lCounterListHasStars = PDLCNFIG_LISTBOX_STARS_NO;
  575. }
  576. CPropertyPage::OnInitDialog();
  577. return TRUE; // return TRUE unless you set the focus to a control
  578. // EXCEPTION: OCX Property Pages should return FALSE
  579. }
  580. void CSettingsPropPage::OnBrowseCounters()
  581. {
  582. PDH_BROWSE_DLG_CONFIG dlgConfig;
  583. CListBox *cCounterList;
  584. LONG lBeforeCount;
  585. LONG lAfterCount;
  586. LRESULT lWildCardOk;
  587. DWORD dwRegValType;
  588. DWORD dwRegValue;
  589. DWORD dwRegValueSize;
  590. LONG lStatus;
  591. if (m_szCounterListBuffer == NULL) {
  592. m_dwCounterListBufferSize = 16384;
  593. m_szCounterListBuffer = new TCHAR[m_dwCounterListBufferSize];
  594. }
  595. dlgConfig.bIncludeInstanceIndex = 0;
  596. dlgConfig.bSingleCounterPerAdd = 0;
  597. dlgConfig.bSingleCounterPerDialog = 0;
  598. dlgConfig.bLocalCountersOnly = 0;
  599. lWildCardOk = QuerySiblings (PDLCNFIG_PSM_QS_WILDCARD_LOG, 0);
  600. if ( lWildCardOk == PDLCNFIG_WILDCARD_LOG_YES) {
  601. dlgConfig.bWildCardInstances = 1;
  602. } else if (lWildCardOk == PDLCNFIG_WILDCARD_LOG_DONT_KNOW ){
  603. // the property page doesn't know so ask the registry
  604. // read log file format
  605. dwRegValType = 0;
  606. dwRegValue = 0;
  607. dwRegValueSize = sizeof(DWORD);
  608. lStatus = RegQueryValueEx (
  609. m_hKeyLogSettingsDefault,
  610. TEXT("Log File Type"),
  611. NULL,
  612. &dwRegValType,
  613. (LPBYTE)&dwRegValue,
  614. &dwRegValueSize);
  615. if (lStatus != ERROR_SUCCESS) {
  616. // then apply default value
  617. dwRegValue = OPD_CSV_FILE;
  618. }
  619. switch (dwRegValue) {
  620. case OPD_BIN_FILE:
  621. // the current log file does support wildcards
  622. dlgConfig.bWildCardInstances = 1;
  623. break;
  624. case OPD_CSV_FILE:
  625. case OPD_TSV_FILE:
  626. default:
  627. // the current log file doesn't support wildcards
  628. dlgConfig.bWildCardInstances = 0;
  629. break;
  630. }
  631. } else {
  632. // the current log file doesn't support wildcards
  633. dlgConfig.bWildCardInstances = 0;
  634. }
  635. dlgConfig.bHideDetailBox = 0;
  636. dlgConfig.bInitializePath = 0;
  637. dlgConfig.bDisableMachineSelection = 0;
  638. dlgConfig.bIncludeCostlyObjects = 0;
  639. dlgConfig.bReserved = 0;
  640. dlgConfig.hWndOwner = this->m_hWnd;
  641. dlgConfig.szDataSource = NULL;
  642. dlgConfig.szReturnPathBuffer = m_szCounterListBuffer;
  643. dlgConfig.cchReturnPathLength = m_dwCounterListBufferSize;
  644. dlgConfig.pCallBack = (CounterPathCallBack)DialogCallBack;
  645. dlgConfig.dwDefaultDetailLevel = PERF_DETAIL_WIZARD;
  646. dlgConfig.dwCallBackArg = (DWORD_PTR)this;
  647. dlgConfig.szDialogBoxCaption = TEXT("Select Counters To Log");
  648. cCounterList = (CListBox *)GetDlgItem(IDC_COUNTER_LIST);
  649. // get count of items in the list box before calling the browser
  650. lBeforeCount = cCounterList->GetCount();
  651. PdhBrowseCounters (&dlgConfig);
  652. // get count of items in the list box After calling the browser
  653. // to see if the Apply button should enabled
  654. lAfterCount = cCounterList->GetCount();
  655. if (lAfterCount > lBeforeCount) SetModified(TRUE);
  656. // see if the remove button should be enabled
  657. GetDlgItem (IDC_REMOVE)->EnableWindow(
  658. lAfterCount > 0 ? TRUE : FALSE);
  659. delete m_szCounterListBuffer;
  660. m_szCounterListBuffer = NULL;
  661. m_dwCounterListBufferSize = 0;
  662. }
  663. void CSettingsPropPage::OnManStart()
  664. {
  665. SetCurrentServiceState (LOG_SERV_START);
  666. UpdateManualButtonsState();
  667. // set focus to stop button
  668. GetDlgItem(IDC_MAN_STOP)->SetFocus();
  669. }
  670. void CSettingsPropPage::OnManStop()
  671. {
  672. SetCurrentServiceState (LOG_SERV_STOP);
  673. UpdateManualButtonsState();
  674. // set focus to start button
  675. GetDlgItem(IDC_MAN_START)->SetFocus();
  676. }
  677. void CSettingsPropPage::OnRemove()
  678. {
  679. CListBox *cCounterList;
  680. LONG lThisItem;
  681. BOOL bDone;
  682. LONG lOrigCaret;
  683. LONG lItemStatus;
  684. LONG lItemCount;
  685. BOOL bChanged = FALSE;
  686. DWORD dwItemExtent;
  687. CString csItemText;
  688. cCounterList = (CListBox *)GetDlgItem(IDC_COUNTER_LIST);
  689. // delete all selected items in the list box and
  690. // set the cursor to the item above the original caret position
  691. // or the first or last if that is out of the new range
  692. lOrigCaret = cCounterList->GetCaretIndex();
  693. lThisItem = 0;
  694. bDone = FALSE;
  695. // clear the max extent
  696. m_dwMaxHorizListExtent = 0;
  697. // clear the value and see if any non deleted items have a star, if so
  698. // then set the flag back
  699. do {
  700. lItemStatus = cCounterList->GetSel(lThisItem);
  701. if (lItemStatus > 0) {
  702. // then it's selected so delete it
  703. cCounterList->DeleteString(lThisItem);
  704. bChanged = TRUE;
  705. } else if (lItemStatus == 0) {
  706. // get the text length of this item since it will stay
  707. cCounterList->GetText(lThisItem, csItemText);
  708. if (m_lCounterListHasStars != PDLCNFIG_LISTBOX_STARS_YES) {
  709. // save a string compare if this value is already set
  710. if (_tcsstr (csItemText, TEXT("*")) == NULL) {
  711. m_lCounterListHasStars = PDLCNFIG_LISTBOX_STARS_YES;
  712. }
  713. }
  714. dwItemExtent = (DWORD)((cCounterList->GetDC())->GetTextExtent(csItemText)).cx;
  715. if (dwItemExtent > m_dwMaxHorizListExtent) {
  716. m_dwMaxHorizListExtent = dwItemExtent;
  717. }
  718. // then it's not selected so go to the next one
  719. lThisItem++;
  720. } else {
  721. // we've run out so exit
  722. bDone = TRUE;
  723. }
  724. } while (!bDone);
  725. // update the text extent of the list box
  726. cCounterList->SetHorizontalExtent(m_dwMaxHorizListExtent);
  727. // see how many entries are left and update the
  728. // caret position and the remove button state
  729. lItemCount = cCounterList->GetCount();
  730. if (lItemCount > 0) {
  731. // the update the caret
  732. if (lOrigCaret >= lItemCount) {
  733. lOrigCaret = lItemCount-1;
  734. } else {
  735. // caret should be within the list
  736. }
  737. cCounterList->SetSel(lOrigCaret);
  738. cCounterList->SetCaretIndex(lOrigCaret);
  739. } else {
  740. // the list is empty so remove caret, selection
  741. // disable the remove button and activate the
  742. // add button
  743. cCounterList->SetSel(-1);
  744. GetDlgItem(IDC_BROWSE_COUNTERS)->SetFocus();
  745. GetDlgItem(IDC_REMOVE)->EnableWindow(FALSE);
  746. }
  747. SetModified(bChanged);
  748. }
  749. void CSettingsPropPage::OnServiceAuto()
  750. {
  751. // set service to AutoStart
  752. UpdateManualButtonsState();
  753. SetModified(TRUE);
  754. }
  755. void CSettingsPropPage::OnServiceMan()
  756. {
  757. // set service to manual Start
  758. UpdateManualButtonsState();
  759. SetModified(TRUE);
  760. }
  761. void CSettingsPropPage::OnDeltaposIntervalSpin(NMHDR* pNMHDR, LRESULT* pResult)
  762. {
  763. TCHAR szStringValue[MAX_PATH];
  764. DWORD dwNumValue;
  765. int nChange;
  766. NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
  767. // get current value from edit window
  768. GetDlgItemText (IDC_INTERVAL_TIME, szStringValue, MAX_PATH);
  769. // convert to integer
  770. dwNumValue = _tcstoul (szStringValue, NULL, 10);
  771. // delta is opposite of arrow direction
  772. nChange = -pNMUpDown->iDelta;
  773. // apply value from spin control
  774. if (nChange < 0) {
  775. // make sure we haven't hit bottom already
  776. // we can't allow a 0 to be "spin-ed" in
  777. if (dwNumValue > 1) {
  778. dwNumValue += nChange;
  779. }
  780. } else {
  781. dwNumValue += nChange;
  782. }
  783. // update edit window
  784. _ultot (dwNumValue, szStringValue, 10);
  785. SetDlgItemText(IDC_INTERVAL_TIME, szStringValue);
  786. SetModified(TRUE);
  787. *pResult = 0;
  788. }
  789. void CSettingsPropPage::OnCancel()
  790. {
  791. CPropertyPage::OnCancel();
  792. }
  793. void CSettingsPropPage::OnOK()
  794. {
  795. CListBox *cCounterList;
  796. CString cIntervalString;
  797. CString cCounterListString;
  798. CString cThisCounterName;
  799. DWORD dwSampleInterval;
  800. LONG lIntervalUnits;
  801. DWORD dwNumCounters;
  802. DWORD dwThisCounter;
  803. DWORD dwBufferLength;
  804. LONG lStatus;
  805. LPTSTR mszCounterPathList = NULL;
  806. LPTSTR szNextItemInList;
  807. BOOL bStopped, bPaused;
  808. cCounterList = (CListBox *)GetDlgItem(IDC_COUNTER_LIST);
  809. // get service state
  810. GetCurrentServiceState (&bStopped, &bPaused);
  811. if (!bStopped) {
  812. AfxMessageBox (IDS_STOP_AND_START);
  813. }
  814. // write changes to registry
  815. //*********************************
  816. // update service start mode if necessary
  817. SyncServiceStartWithButtons();
  818. // sample interval
  819. // read value
  820. GetDlgItemText (IDC_INTERVAL_TIME, cIntervalString);
  821. dwSampleInterval = _tcstoul((LPCTSTR)cIntervalString, NULL, 10);
  822. // read units
  823. lIntervalUnits = ((CComboBox *)GetDlgItem(IDC_INTERVAL_UNITS))->GetCurSel();
  824. // convert value to seconds based on units
  825. switch (lIntervalUnits) {
  826. case SIU_MINUTES:
  827. dwSampleInterval *= SECONDS_IN_MINUTE;
  828. break;
  829. case SIU_HOURS:
  830. dwSampleInterval *= SECONDS_IN_HOUR;
  831. break;
  832. case SIU_DAYS:
  833. dwSampleInterval *= SECONDS_IN_DAY;
  834. break;
  835. case SIU_SECONDS:
  836. default:
  837. // already in second so leave it
  838. break;
  839. }
  840. // write value to registry
  841. lStatus = RegSetValueEx (
  842. m_hKeyLogSettingsDefault,
  843. TEXT("Sample Interval"),
  844. 0L,
  845. REG_DWORD,
  846. (LPBYTE)&dwSampleInterval,
  847. sizeof(DWORD));
  848. if (lStatus != ERROR_SUCCESS) {
  849. // unable to update value
  850. }
  851. //*********************************
  852. // counter list
  853. // retrieve items from list box
  854. dwNumCounters = cCounterList->GetCount();
  855. dwBufferLength = 0;
  856. // determine required buffer size
  857. for (dwThisCounter = 0; dwThisCounter < dwNumCounters; dwThisCounter++) {
  858. dwBufferLength += cCounterList->GetTextLen (dwThisCounter) + 1;
  859. }
  860. // add terminating NULL char
  861. dwBufferLength++;
  862. // allocate string buffer and copy list box entries to MSZ
  863. mszCounterPathList = new TCHAR[dwBufferLength];
  864. ASSERT (mszCounterPathList != NULL);
  865. // load listbox entries into MSZ
  866. szNextItemInList = mszCounterPathList;
  867. *szNextItemInList = 0;
  868. for (dwThisCounter = 0; dwThisCounter < dwNumCounters; dwThisCounter++) {
  869. lStatus = cCounterList->GetText(dwThisCounter, szNextItemInList);
  870. lStatus /= sizeof(TCHAR);
  871. szNextItemInList += lStatus;
  872. *szNextItemInList++ = 0;
  873. }
  874. *szNextItemInList++ = 0;
  875. dwBufferLength = (DWORD)((LPBYTE)szNextItemInList - (LPBYTE)mszCounterPathList);
  876. // write MSZ to registry
  877. lStatus = RegSetValueEx (
  878. m_hKeyLogSettingsDefault,
  879. TEXT("Counter List"),
  880. 0L,
  881. REG_MULTI_SZ,
  882. (LPBYTE)mszCounterPathList,
  883. dwBufferLength);
  884. if (lStatus != ERROR_SUCCESS) {
  885. // unable to update value
  886. }
  887. delete mszCounterPathList;
  888. CancelToClose();
  889. }
  890. BOOL CSettingsPropPage::OnQueryCancel()
  891. {
  892. return CPropertyPage::OnQueryCancel();
  893. }
  894. void CSettingsPropPage::OnSelchangeIntervalUnits()
  895. {
  896. SetModified(TRUE);
  897. }
  898. void CSettingsPropPage::OnRemoveService()
  899. {
  900. SC_HANDLE hSC = NULL;
  901. SC_HANDLE hService = NULL;
  902. DWORD dwMoreBytes = 0;
  903. LONG lStatus;
  904. if (AfxMessageBox (IDS_REMOVE_SERVICE_WARNING,
  905. MB_OKCANCEL | MB_DEFBUTTON2) == IDCANCEL) {
  906. return;
  907. }
  908. // open SC database
  909. hSC = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS);
  910. if (hSC == NULL) {
  911. lStatus = GetLastError();
  912. ASSERT (lStatus != ERROR_SUCCESS);
  913. }
  914. // open service
  915. hService = OpenService (hSC, TEXT("PerfDataLog"),
  916. SERVICE_CHANGE_CONFIG | DELETE);
  917. if (hService != NULL) {
  918. // Delete the service
  919. if (DeleteService (hService)) {
  920. EndDialog (IDCANCEL);
  921. }
  922. CloseServiceHandle (hService);
  923. } else {
  924. lStatus = GetLastError();
  925. ASSERT (lStatus != 0);
  926. }
  927. // close handles
  928. if (hSC != NULL) CloseServiceHandle (hSC);
  929. return;
  930. }
  931. void CSettingsPropPage::OnChangeIntervalTime()
  932. {
  933. // TODO: Add your control notification handler code here
  934. SetModified(TRUE);
  935. }