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.

639 lines
21 KiB

  1. //==========================================================================//
  2. // Includes //
  3. //==========================================================================//
  4. #include "perfmon.h" // basic defns, windows.h
  5. #include "logoptns.h" // external declarations for this file
  6. #include "dlgs.h" // common dialog control IDs
  7. #include "log.h" // for StartLog, SetLogTimer, CloseLog
  8. #include "fileutil.h" // file utilities
  9. #include "utils.h" // various utilities
  10. #include "playback.h" // for PlayingBackLog
  11. #include "pmhelpid.h" // Help IDs
  12. //==========================================================================//
  13. // Local Data //
  14. //==========================================================================//
  15. DWORD iIntervalMSecs ;
  16. BOOL bNeedToRelogData ;
  17. BOOL bNeedToStartLog ;
  18. BOOL bNeedToSetTimer ;
  19. extern BOOL LocalManualRefresh ;
  20. static BOOL bStopButtonClicked ;
  21. extern HWND hWndLogEntries ;
  22. #if WINVER >= 0x0400
  23. // the win4.0 common dialogs are organized a little differently
  24. // the hDlg passed in not the Master dialog, but only the window
  25. // with the extended controls. This buffer is to save the extended
  26. // controls in.
  27. static HDLG hWndDlg = NULL;
  28. #endif
  29. // This is a counter that is init. to 0. It is incremened by 1
  30. // when the user click the cancel button.
  31. // It is set to -1 when we sent the cancell msg internally.
  32. int bCancelled ;
  33. TCHAR szmsgFILEOK[] = FILEOKSTRING ;
  34. DWORD msgFILEOK ;
  35. //==========================================================================//
  36. // Macros //
  37. //==========================================================================//
  38. #define LogOptionsOFNStyle \
  39. (OFN_ENABLETEMPLATE | OFN_HIDEREADONLY | \
  40. OFN_ENABLEHOOK | OFN_EXPLORER)
  41. // OFN_SHOWHELP | OFN_ENABLEHOOK)
  42. //==========================================================================//
  43. // Local Functions //
  44. //==========================================================================//
  45. void
  46. EnableFileControls (
  47. HDLG hDlg,
  48. BOOL bEnable
  49. )
  50. {
  51. DialogEnable (hDlg, stc3, bEnable) ;
  52. DialogEnable (hDlg, lst1, bEnable) ;
  53. DialogEnable (hDlg, stc1, bEnable) ;
  54. DialogEnable (hDlg, lst2, bEnable) ;
  55. DialogEnable (hDlg, stc2, bEnable) ;
  56. DialogEnable (hDlg, cmb1, bEnable) ;
  57. DialogEnable (hDlg, stc4, bEnable) ;
  58. DialogEnable (hDlg, cmb2, bEnable) ;
  59. DialogEnable (hDlg, edt1, bEnable) ;
  60. }
  61. //==========================================================================//
  62. // Message Handlers //
  63. //==========================================================================//
  64. void
  65. static
  66. OnInitDialog (
  67. HDLG hDlg
  68. )
  69. {
  70. PLOG pLog ;
  71. int i ;
  72. BOOL DisplayManualRefresh ;
  73. pLog = LogData (hWndLog) ;
  74. if (msgFILEOK == 0) {
  75. msgFILEOK = RegisterWindowMessage(szmsgFILEOK);
  76. }
  77. bCancelled = 0 ;
  78. switch (pLog->iStatus) {
  79. case iPMStatusClosed:
  80. // DialogEnable (hDlg, IDD_LOGOPTPAUSE, FALSE) ;
  81. break ;
  82. case iPMStatusPaused:
  83. EnableFileControls (hDlg, FALSE) ;
  84. DialogSetText (hDlg, IDD_LOGOPTSTART, IDS_STOP) ;
  85. // DialogSetText (hDlg, IDD_LOGOPTPAUSE, IDS_RESUME) ;
  86. break ;
  87. case iPMStatusCollecting:
  88. EnableFileControls (hDlg, FALSE) ;
  89. DialogSetText (hDlg, IDD_LOGOPTSTART, IDS_STOP) ;
  90. break ;
  91. }
  92. for (i = 0 ;
  93. i < NumIntervals ;
  94. i++)
  95. CBAddInt (DialogControl (hDlg, IDD_LOGOPTINTERVAL), aiIntervals [i]) ;
  96. DialogSetInterval (hDlg, IDD_LOGOPTINTERVAL, pLog->iIntervalMSecs) ;
  97. iIntervalMSecs = pLog->iIntervalMSecs ;
  98. LocalManualRefresh = pLog->bManualRefresh ;
  99. DisplayManualRefresh = TRUE ;
  100. if (PlayingBackLog ()) {
  101. DialogSetText (hDlg, IDD_LOGOPTSTART, IDS_CREATELOGFILE) ;
  102. DisplayManualRefresh = FALSE ;
  103. }
  104. if (LBNumItems (hWndLogEntries) == 0) {
  105. DialogEnable (hDlg, IDD_LOGOPTSTART, FALSE) ;
  106. // DialogEnable (hDlg, IDD_LOGOPTPAUSE, FALSE) ;
  107. }
  108. if (DisplayManualRefresh) {
  109. if (LocalManualRefresh) {
  110. DialogEnable (hDlg, IDD_LOGOPTINTERVAL, FALSE) ;
  111. DialogEnable (hDlg, IDD_LOGOPTINTERVALTEXT, FALSE) ;
  112. }
  113. CheckRadioButton (hDlg,
  114. IDD_LOGOPTIONSMANUALREFRESH,
  115. IDD_LOGOPTIONSPERIODIC,
  116. LocalManualRefresh ? IDD_LOGOPTIONSMANUALREFRESH :
  117. IDD_LOGOPTIONSPERIODIC) ;
  118. } else {
  119. DialogEnable (hDlg, IDD_LOGOPTIONSMANUALREFRESH, FALSE) ;
  120. CheckRadioButton (hDlg,
  121. IDD_LOGOPTIONSMANUALREFRESH,
  122. IDD_LOGOPTIONSPERIODIC,
  123. IDD_LOGOPTIONSPERIODIC) ;
  124. }
  125. dwCurrentDlgID = HC_PM_idDlgOptionLog ;
  126. WindowCenter (hDlg) ;
  127. }
  128. void
  129. OnStart (
  130. HDLG hDlg
  131. )
  132. /*
  133. Effect: Handle any actions necessary when the user clicks on
  134. the "Start/Stop" button.
  135. Note: This button could be displaying start or stop, depending
  136. on the situation.
  137. */
  138. {
  139. PLOG pLog ;
  140. pLog = LogData (hDlg) ;
  141. bStopButtonClicked = FALSE ;
  142. switch (pLog->iStatus) {
  143. case iPMStatusClosed:
  144. if (PlayingBackLog ()) {
  145. bNeedToRelogData = TRUE ;
  146. } else {
  147. FLOAT eTimeInterval ;
  148. eTimeInterval = DialogFloat (hDlg, IDD_LOGOPTINTERVAL, NULL) ;
  149. if (eTimeInterval > MAX_INTERVALSEC ||
  150. eTimeInterval < MIN_INTERVALSEC) {
  151. DlgErrorBox (hDlg, ERR_BADTIMEINTERVAL) ;
  152. SetFocus (DialogControl (hDlg, IDD_LOGOPTINTERVAL)) ;
  153. EditSetTextEndPos (hDlg, IDD_LOGOPTINTERVAL) ;
  154. return ;
  155. break ;
  156. }
  157. eTimeInterval = eTimeInterval * (FLOAT) 1000.0 + (FLOAT) 0.5 ;
  158. pLog->iIntervalMSecs = (DWORD) eTimeInterval ;
  159. iIntervalMSecs = pLog->iIntervalMSecs ;
  160. bNeedToStartLog = TRUE ;
  161. }
  162. break ;
  163. case iPMStatusCollecting:
  164. case iPMStatusPaused:
  165. CloseLog (hWndLog, pLog) ;
  166. bStopButtonClicked = TRUE ;
  167. break ;
  168. }
  169. #if WINVER < 0x0400
  170. SimulateButtonPush (hDlg, IDD_OK) ;
  171. #else
  172. SimulateButtonPush (hWndDlg, IDOK) ;
  173. #endif
  174. }
  175. BOOL
  176. static
  177. OnOK (
  178. HDLG hDlg
  179. )
  180. /*
  181. Effect: Perform any hooked actions needed when the user selects
  182. OK in the log options dialog. In particular, if we are
  183. currently logging, record the need to relog and CANCEL
  184. the dialog, never letting the real dialog proc get the
  185. OK. Remember, this is actually a file open dialog that
  186. we have perverted. If we let the OK through, the common
  187. dialog manager will try to open it and it will inform
  188. the user that the file is locked. This way, we let the
  189. user click OK, but the dialog thinks we cancelled.
  190. Called By: LogOptionsHookProc only.
  191. Returns: Whether the message was handled by this function or not.
  192. */
  193. {
  194. PLOG pLog ;
  195. pLog = LogData (hWndLog) ;
  196. if (pLog->iStatus == iPMStatusCollecting ||
  197. pLog->iStatus == iPMStatusPaused) {
  198. if (LocalManualRefresh != pLog->bManualRefresh) {
  199. if (!LocalManualRefresh) {
  200. FLOAT eTimeInterval ;
  201. eTimeInterval = DialogFloat (hDlg, IDD_LOGOPTINTERVAL, NULL) ;
  202. if (eTimeInterval > MAX_INTERVALSEC ||
  203. eTimeInterval < MIN_INTERVALSEC) {
  204. DlgErrorBox (hDlg, ERR_BADTIMEINTERVAL) ;
  205. SetFocus (DialogControl (hDlg, IDD_LOGOPTINTERVAL)) ;
  206. EditSetTextEndPos (hDlg, IDD_LOGOPTINTERVAL) ;
  207. return (FALSE) ;
  208. }
  209. eTimeInterval = eTimeInterval * (FLOAT) 1000.0 + (FLOAT) 0.5 ;
  210. pLog->iIntervalMSecs = (DWORD) eTimeInterval ;
  211. iIntervalMSecs = pLog->iIntervalMSecs ;
  212. UpdateLogDisplay (hWndLog) ;
  213. }
  214. ToggleLogRefresh (hWndLog) ;
  215. } else {
  216. bNeedToSetTimer = TRUE ;
  217. bCancelled = -1 ;
  218. }
  219. #if WINVER < 0x0400
  220. SimulateButtonPush (hDlg, IDD_CANCEL) ;
  221. #else
  222. SimulateButtonPush (hWndDlg, IDCANCEL) ;
  223. #endif
  224. return TRUE ;
  225. } else {
  226. if (!LocalManualRefresh) {
  227. FLOAT eTimeInterval ;
  228. eTimeInterval = DialogFloat (hDlg, IDD_LOGOPTINTERVAL, NULL) ;
  229. if (eTimeInterval > MAX_INTERVALSEC ||
  230. eTimeInterval < MIN_INTERVALSEC) {
  231. DlgErrorBox (hDlg, ERR_BADTIMEINTERVAL) ;
  232. SetFocus (DialogControl (hDlg, IDD_LOGOPTINTERVAL)) ;
  233. EditSetTextEndPos (hDlg, IDD_LOGOPTINTERVAL) ;
  234. return (TRUE) ;
  235. }
  236. }
  237. }
  238. return FALSE ;
  239. }
  240. void OnPause (HDLG hDlg) { }
  241. BOOL
  242. APIENTRY
  243. LogOptionsHookProc (
  244. HWND hDlg,
  245. UINT iMessage,
  246. WPARAM wParam,
  247. LPARAM lParam
  248. )
  249. {
  250. BOOL bHandled ;
  251. bHandled = TRUE ;
  252. if (iMessage == msgFILEOK) {
  253. bHandled = OnOK (hDlg) ;
  254. return (bHandled) ;
  255. }
  256. switch (iMessage) {
  257. case WM_INITDIALOG:
  258. OnInitDialog (hDlg) ;
  259. break ;
  260. #if WINVER >= 0x0400
  261. case WM_NOTIFY:
  262. {
  263. LPOFNOTIFY pOfn;
  264. pOfn = (LPOFNOTIFY)lParam;
  265. switch (pOfn->hdr.code) {
  266. case CDN_INITDONE:
  267. hWndDlg = pOfn->hdr.hwndFrom;
  268. OnInitDialog (hWndDlg);
  269. break;
  270. case CDN_FILEOK:
  271. {
  272. INT_PTR iFileIndex ;
  273. HWND hWndCBox;
  274. hWndCBox = GetDlgItem (pOfn->hdr.hwndFrom, cmb1); // Type combo box
  275. iFileIndex = CBSelection (hWndCBox) ;
  276. // the order of the entries in the combo box depends on
  277. // the current delimiter character
  278. if (pDelimiter == TabStr) {
  279. pDelimiter = iFileIndex == 0 ? // 0 = TSV, 1=CSV
  280. TabStr : CommasStr;
  281. } else {
  282. pDelimiter = iFileIndex == 0 ? // 0 = TSV, 1=CSV
  283. CommasStr : TabStr;
  284. }
  285. }
  286. break;
  287. default:
  288. break;
  289. }
  290. }
  291. break;
  292. case WM_HELP:
  293. {
  294. LPHELPINFO pInfo;
  295. PLOG pLog ;
  296. int iHelpId;
  297. pInfo = (LPHELPINFO)lParam;
  298. pLog = LogData (hDlg) ;
  299. if (pInfo->iContextType == HELPINFO_WINDOW) {
  300. // display perfmon help if a "perfmon" control is selected
  301. switch (pInfo->iCtrlId) {
  302. case IDD_LOGOPTSTART:
  303. case IDD_LOGOPTPAUSE:
  304. // call winhelp to display text
  305. // decide if start or stop button is pressed
  306. switch (pLog->iStatus) {
  307. case iPMStatusCollecting:
  308. case iPMStatusPaused:
  309. // then it's a stop button
  310. iHelpId = IDD_LOGOPTPAUSE;
  311. break;
  312. case iPMStatusClosed:
  313. default:
  314. // then it's a start button
  315. iHelpId = IDD_LOGOPTSTART;
  316. break;
  317. }
  318. if (*pszHelpFile != 0) {
  319. bHandled = WinHelp (
  320. hDlg,
  321. pszHelpFile,
  322. HELP_CONTEXTPOPUP,
  323. iHelpId);
  324. } else {
  325. DlgErrorBox (hDlg, ERR_HELP_NOT_AVAILABLE);
  326. }
  327. break;
  328. case IDD_LOGOPTINTERVAL:
  329. case IDD_LOGOPTIONSPERIODIC:
  330. case IDD_LOGOPTIONSMANUALREFRESH:
  331. // call winhelp to display text
  332. if (*pszHelpFile != 0) {
  333. bHandled = WinHelp (
  334. hDlg,
  335. pszHelpFile,
  336. HELP_CONTEXTPOPUP,
  337. pInfo->iCtrlId);
  338. } else {
  339. DlgErrorBox (hDlg, ERR_HELP_NOT_AVAILABLE);
  340. }
  341. break;
  342. default:
  343. bHandled = FALSE;
  344. break;
  345. }
  346. } else {
  347. bHandled = FALSE;
  348. }
  349. }
  350. break;
  351. #endif
  352. case WM_DESTROY:
  353. {
  354. FLOAT eTimeInterval ;
  355. if (!bCancelled) {
  356. eTimeInterval = DialogFloat (hDlg, IDD_LOGOPTINTERVAL, NULL) ;
  357. if (eTimeInterval > MAX_INTERVALSEC ||
  358. eTimeInterval < MIN_INTERVALSEC) {
  359. DlgErrorBox (hDlg, ERR_BADTIMEINTERVAL) ;
  360. } else {
  361. eTimeInterval = eTimeInterval * (FLOAT) 1000.0 + (FLOAT) 0.5 ;
  362. iIntervalMSecs = (DWORD) eTimeInterval ;
  363. }
  364. }
  365. #if WINVER >= 0x0400
  366. hWndDlg = NULL;
  367. #endif
  368. dwCurrentDlgID = 0 ;
  369. bHandled = FALSE ;
  370. }
  371. break ;
  372. case WM_COMMAND:
  373. switch (wParam) {
  374. case IDD_LOGOPTSTART:
  375. OnStart (hDlg) ;
  376. break ;
  377. case IDD_LOGOPTPAUSE:
  378. OnPause (hDlg) ;
  379. break ;
  380. case IDD_OK:
  381. bHandled = OnOK (hDlg) ;
  382. break ;
  383. case IDD_CANCEL:
  384. bCancelled += 1 ;
  385. bHandled = FALSE ;
  386. break ;
  387. case IDD_LOGOPTIONSPERIODIC:
  388. if (PlayingBackLog()) {
  389. break ;
  390. }
  391. // else fall thru to the following case...
  392. case IDD_LOGOPTIONSMANUALREFRESH:
  393. // check if the Manual refresh is currently checked.
  394. // Then toggle the ManualRefresh button
  395. LocalManualRefresh =
  396. (wParam == IDD_LOGOPTIONSMANUALREFRESH) ;
  397. CheckRadioButton (hDlg,
  398. IDD_LOGOPTIONSMANUALREFRESH,
  399. IDD_LOGOPTIONSPERIODIC,
  400. LocalManualRefresh ? IDD_LOGOPTIONSMANUALREFRESH :
  401. IDD_LOGOPTIONSPERIODIC) ;
  402. DialogEnable (hDlg, IDD_LOGOPTINTERVAL, !LocalManualRefresh) ;
  403. DialogEnable (hDlg, IDD_LOGOPTINTERVALTEXT, !LocalManualRefresh) ;
  404. break ;
  405. case ID_HELP:
  406. CallWinHelp (dwCurrentDlgID, hDlg) ;
  407. break ;
  408. default:
  409. bHandled = FALSE ;
  410. break ;
  411. }
  412. break;
  413. default:
  414. bHandled = FALSE ;
  415. break;
  416. }
  417. return (bHandled) ;
  418. }
  419. BOOL
  420. DisplayLogOptions (
  421. HWND hWndParent,
  422. HWND hWndLog
  423. )
  424. {
  425. TCHAR szFilePath [FilePathLen + 1] ;
  426. TCHAR szFileTitle [FilePathLen + 1] ;
  427. TCHAR szFileDirectory [FilePathLen + 1] ;
  428. TCHAR szCaption [WindowCaptionLen + 1] ;
  429. OPENFILENAME ofn ;
  430. PLOG pLog ;
  431. int RetCode ;
  432. int PrevLogSize ;
  433. BOOL bSameFile ;
  434. TCHAR szFilter[LongTextLen] ;
  435. int StringLength ;
  436. szFilter[0] = 0;
  437. StringLoad (IDS_SAVELOGFILE, szFilter) ;
  438. StringLength = lstrlen (szFilter) + 1 ;
  439. LoadString (hInstance, IDS_SAVELOGFILEEXT,
  440. &szFilter[StringLength],
  441. (sizeof(szFilter)/sizeof(TCHAR))-StringLength) ;
  442. StringLength += lstrlen (&szFilter[StringLength]) ;
  443. szFilter[StringLength+1] = szFilter[StringLength+2] = TEXT('\0') ;
  444. // This dialog is used to change attributes for an existing log file,
  445. // and to select the name of a log file to open. Therefore we have
  446. // different options in these cases.
  447. pLog = LogData (hWndLog) ;
  448. if (!strempty (pLog->szFilePath)) {
  449. FileNameExtension (pLog->szFilePath, szFileTitle) ;
  450. FileDriveDirectory (pLog->szFilePath, szFileDirectory) ;
  451. lstrcpy (szFilePath, szFileTitle) ;
  452. } else {
  453. szFileTitle[0] = szFileDirectory[0] = TEXT('\0') ;
  454. StringLoad (IDS_SAVELOGFILEEXT, szFilePath) ;
  455. }
  456. StringLoad (IDS_LOGOPTIONS, szCaption) ;
  457. ofn.lStructSize = sizeof(OPENFILENAME) ;
  458. ofn.hwndOwner = hWndParent ;
  459. ofn.hInstance = hInstance ;
  460. ofn.lpstrFilter = szFilter;
  461. ofn.lpstrCustomFilter = (LPTSTR) NULL;
  462. ofn.nMaxCustFilter = 0L;
  463. ofn.nFilterIndex = 1L;
  464. ofn.lpstrFile = szFilePath ;
  465. ofn.nMaxFile = FilePathLen ;
  466. ofn.lpstrFileTitle = szFileTitle ;
  467. ofn.nMaxFileTitle = FilePathLen ;
  468. ofn.lpstrInitialDir = szFileDirectory ;
  469. ofn.lpstrTitle = (LPTSTR) szCaption ;
  470. ofn.Flags = LogOptionsOFNStyle ;
  471. ofn.nFileOffset = 0;
  472. ofn.nFileExtension = 0;
  473. ofn.lpstrDefExt = (LPTSTR) NULL;
  474. ofn.lpfnHook = (LPOFNHOOKPROC) LogOptionsHookProc ;
  475. ofn.lpTemplateName = idDlgLogOptions ;
  476. bNeedToRelogData = FALSE;
  477. bNeedToStartLog = FALSE ;
  478. bNeedToSetTimer = FALSE ;
  479. bStopButtonClicked = FALSE ;
  480. if (GetSaveFileName(&ofn) && !bStopButtonClicked) {
  481. pLog = LogData (hWndLog) ;
  482. // save previous log file name & size
  483. // so we can reset if error
  484. PrevLogSize = pLog->lFileSize ;
  485. lstrcpy (szFileTitle, pLog->szFilePath) ;
  486. bSameFile = pstrsamei (pLog->szFilePath, ofn.lpstrFile) ;
  487. if (!bSameFile) {
  488. lstrcpy (pLog->szFilePath, ofn.lpstrFile) ;
  489. }
  490. pLog->iIntervalMSecs = iIntervalMSecs ;
  491. if (bNeedToStartLog) {
  492. pLog->bManualRefresh = LocalManualRefresh ;
  493. StartLog (hWndLog, pLog, bSameFile) ;
  494. } else if (bNeedToRelogData) {
  495. bNeedToRelogData = FALSE ;
  496. SetHourglassCursor() ;
  497. ReLog (hWndLog, bSameFile) ;
  498. SetArrowCursor() ;
  499. } else if (LocalManualRefresh != pLog->bManualRefresh) {
  500. ToggleLogRefresh (hWndLog) ;
  501. }
  502. if (!pLog->hFile) {
  503. if (bNeedToStartLog) {
  504. // if we get here, that means StartLog has detected
  505. // problem, just restore the old stuff..
  506. pLog->lFileSize = PrevLogSize ;
  507. lstrcpy (pLog->szFilePath, szFileTitle) ;
  508. }
  509. // verify if this is a good log file and setup the file size
  510. else if ((RetCode = CreateLogFile (pLog, FALSE, bSameFile)) != 0) {
  511. DlgErrorBox (hWndLog, RetCode, pLog->szFilePath);
  512. pLog->lFileSize = PrevLogSize ;
  513. lstrcpy (pLog->szFilePath, szFileTitle) ;
  514. } else {
  515. // unfortunately, we have to close this file.
  516. // Otherwise, when we do StartLog, the common dialog
  517. // will complain that this file is already in-used.
  518. CloseHandle (pLog->hFile) ;
  519. }
  520. pLog->hFile = 0 ;
  521. }
  522. // UpdateLogDisplay (hWndLog) ;
  523. }
  524. // Remember, we faked out GetSaveFileName to return FALSE. See OnOK doc.
  525. if (bNeedToSetTimer) {
  526. SetLogTimer (hWndLog, iIntervalMSecs) ;
  527. // UpdateLogDisplay (hWndLog) ;
  528. }
  529. UpdateLogDisplay (hWndLog) ;
  530. return (TRUE) ;
  531. }