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.

1517 lines
38 KiB

  1. #include "perfmon.h"
  2. #include <lmcons.h>
  3. #include <lmerr.h>
  4. #include <lmapibuf.h>
  5. #include <lmwksta.h>
  6. #include <uiexport.h>
  7. #include <stdio.h> // for sprintf
  8. #include <locale.h> // for setlocale
  9. #include "utils.h"
  10. #include "perfdata.h" // for OpenSystemPerfData
  11. #include "alert.h" // for AlertInsertLine
  12. #include "report.h" // for ReportInsertLine
  13. #include "grafdata.h" // for GraphInsertLine
  14. #include "log.h" // for OpenLog
  15. #include "fileopen.h" // for FileGetName
  16. #include "fileutil.h" // for FileRead etc
  17. #include "command.h" // for PrepareMenu
  18. #include "playback.h" // for PlayingBackLog & LogPositionSystemTime
  19. #include "system.h"
  20. #include "globals.h"
  21. #include "pmemory.h" // for MemoryFree
  22. #include "status.h" // for StatusLineReady
  23. #include "pmhelpid.h"
  24. // test for delimiter, end of line and non-digit characters
  25. // used by IsNumberInUnicodeList routine
  26. //
  27. #define DIGIT 1
  28. #define DELIMITER 2
  29. #define INVALID 3
  30. // globals used for International Date and Time formats
  31. enum DATE_STYLE
  32. {
  33. YEAR_FIRST, // YYMMDD
  34. DAY_FIRST, // DDMMYY
  35. MONTH_FIRST // MMDDYY
  36. } DateStyle ;
  37. TCHAR szInternational[] = TEXT("Intl") ;
  38. TCHAR sz1159[6] ; // AM String
  39. TCHAR sz2359[6] ; // PM String
  40. int iTime ; // = 0 for 12-hour format, <> 0 for 24-hour format
  41. int YearCharCount ; // = 4 for 1990, = 2 for 90
  42. TCHAR szDateFormat[ResourceStringLen] ;
  43. TCHAR szTimeFormat[ResourceStringLen] ; // time format including msec
  44. TCHAR szTimeFormat1[ResourceStringLen] ; // time format without msec
  45. TCHAR LeadingZeroStr [] = TEXT("%02d") ;
  46. TCHAR NoLeadingZeroStr [] = TEXT("%d") ;
  47. TCHAR szDecimal [2] ;
  48. TCHAR szCurrentDecimal [2] ;
  49. #define EvalThisChar(c,d) ( \
  50. (c == d) ? DELIMITER : \
  51. (c == 0) ? DELIMITER : \
  52. (c < (WCHAR)'0') ? INVALID : \
  53. (c > (WCHAR)'9') ? INVALID : \
  54. DIGIT)
  55. #define SIZE_OF_BIGGEST_INTEGER 16
  56. // #define SIZE_OF_BIGGEST_INTEGER (16*sizeof(WCHAR))
  57. //==========================================================================//
  58. // Typedefs //
  59. //==========================================================================//
  60. BOOL AddObjectToSystem ( PLINE , PPERFSYSTEM );
  61. BOOL GetLogFileComputer (HWND hWndParent, LPTSTR lpComputerName, DWORD BufferSize) ;
  62. HWND PerfmonViewWindow (void)
  63. /*
  64. Effect: Return the current data window, i.e. the window currently
  65. visible as the client area of Perfmon. This is either a
  66. chart, log, alert, or report window.
  67. */
  68. { // PerfmonDataWindow
  69. switch (iPerfmonView)
  70. { // switch
  71. case IDM_VIEWLOG:
  72. return (hWndLog) ;
  73. case IDM_VIEWALERT:
  74. return (hWndAlert) ;
  75. case IDM_VIEWREPORT:
  76. return (hWndReport) ;
  77. // case IDM_VIEWCHART:
  78. default:
  79. return (hWndGraph) ;
  80. } // switch
  81. } // PerfmonViewWindow
  82. #define szChooseComputerLibrary TEXT("ntlanman.dll")
  83. #define szChooseComputerFunction "I_SystemFocusDialog"
  84. BOOL ChooseComputer (HWND hWndParent, LPTSTR lpszComputer)
  85. /*
  86. Effect: Display the choose Domain/Computer dialog provided by
  87. network services. If the user selects a computer,
  88. copy the computer name to lpszComputer and return
  89. nonnull. If the user cancels, return FALSE.
  90. Internals: This dialog and code is currently not an exported
  91. routine regularly found on any user's system. Right
  92. now, we dynamically load and call the routine.
  93. This is definitely temporary code that will be
  94. rewritten when NT stabilizes. The callers of this
  95. routine, however, will not need to be modified.
  96. Also, the Domain/Computer dialog currently allows
  97. a domain to be selected, which we cannot use. We
  98. therefore loop until the user cancels or selects
  99. a computer, putting up a message if the user selects
  100. a domain.
  101. Assert: lpszComputer is at least MAX_SYSTEM_NAME_LENGTH + 1
  102. characters.
  103. */
  104. { // ChooseComputer
  105. BOOL bSuccess ;
  106. WCHAR wszWideComputer[MAX_PATH + 3] ;
  107. HLIBRARY hLibrary ;
  108. LPFNI_SYSTEMFOCUSDIALOG lpfnChooseComputer ;
  109. LONG lError ;
  110. if (!PlayingBackLog())
  111. {
  112. // bring up the select network computer dialog
  113. hLibrary = LoadLibrary (szChooseComputerLibrary) ;
  114. if (!hLibrary || hLibrary == INVALID_HANDLE_VALUE)
  115. {
  116. return (FALSE) ;
  117. }
  118. lpfnChooseComputer = (LPFNI_SYSTEMFOCUSDIALOG)
  119. GetProcAddress (hLibrary, szChooseComputerFunction) ;
  120. if (!lpfnChooseComputer)
  121. {
  122. FreeLibrary (hLibrary) ;
  123. return (FALSE) ;
  124. }
  125. lError = (*lpfnChooseComputer) (hWndParent,
  126. FOCUSDLG_SERVERS_ONLY | FOCUSDLG_BROWSE_ALL_DOMAINS,
  127. wszWideComputer,
  128. sizeof(wszWideComputer) / sizeof(WCHAR),
  129. &bSuccess,
  130. pszHelpFile,
  131. HC_PM_idDlgSelectNetworkComputer) ;
  132. FreeLibrary (hLibrary) ;
  133. }
  134. else
  135. {
  136. // bring up the select Log Computer dialog
  137. bSuccess = GetLogFileComputer (hWndParent,
  138. wszWideComputer,
  139. sizeof(wszWideComputer) / sizeof(WCHAR)) ;
  140. }
  141. if (bSuccess)
  142. {
  143. lstrcpy (lpszComputer, wszWideComputer) ;
  144. }
  145. return (bSuccess) ;
  146. } // ChooseComputer
  147. void SystemTimeDateString (SYSTEMTIME *pSystemTime,
  148. LPTSTR lpszDate)
  149. {
  150. int wYear ;
  151. wYear = pSystemTime->wYear ;
  152. if (YearCharCount == 2)
  153. {
  154. wYear %= 100 ;
  155. }
  156. switch (DateStyle)
  157. {
  158. case YEAR_FIRST:
  159. TSPRINTF (lpszDate, szDateFormat,
  160. wYear, pSystemTime->wMonth, pSystemTime->wDay) ;
  161. break ;
  162. case DAY_FIRST:
  163. TSPRINTF (lpszDate, szDateFormat,
  164. pSystemTime->wDay, pSystemTime->wMonth, wYear) ;
  165. break ;
  166. case MONTH_FIRST:
  167. default:
  168. TSPRINTF (lpszDate, szDateFormat,
  169. pSystemTime->wMonth, pSystemTime->wDay, wYear) ;
  170. break ;
  171. }
  172. }
  173. void SystemTimeTimeString (SYSTEMTIME *pSystemTime,
  174. LPTSTR lpszTime,
  175. BOOL bOutputMsec)
  176. {
  177. int iHour ;
  178. BOOL bPM ;
  179. if (iTime)
  180. {
  181. // 24 hor format
  182. if (bOutputMsec)
  183. {
  184. TSPRINTF (lpszTime, szTimeFormat,
  185. pSystemTime->wHour,
  186. pSystemTime->wMinute,
  187. (FLOAT)pSystemTime->wSecond +
  188. (FLOAT)pSystemTime->wMilliseconds / (FLOAT) 1000.0) ;
  189. }
  190. else
  191. {
  192. TSPRINTF (lpszTime, szTimeFormat1,
  193. pSystemTime->wHour,
  194. pSystemTime->wMinute,
  195. pSystemTime->wSecond) ;
  196. }
  197. }
  198. else
  199. {
  200. // 12 hour format
  201. iHour = pSystemTime->wHour ;
  202. bPM = (iHour >= 12) ;
  203. if (iHour > 12)
  204. iHour -= 12 ;
  205. else if (!iHour)
  206. iHour = 12 ;
  207. if (bOutputMsec)
  208. {
  209. TSPRINTF (lpszTime, szTimeFormat,
  210. iHour, pSystemTime->wMinute,
  211. (FLOAT)pSystemTime->wSecond +
  212. (FLOAT)pSystemTime->wMilliseconds / (FLOAT) 1000.0 ,
  213. bPM ? sz2359 : sz1159) ;
  214. }
  215. else
  216. {
  217. TSPRINTF (lpszTime, szTimeFormat1,
  218. iHour, pSystemTime->wMinute,
  219. pSystemTime->wSecond,
  220. bPM ? sz2359 : sz1159) ;
  221. }
  222. }
  223. }
  224. void ShowPerfmonWindowText ()
  225. {
  226. LPTSTR *ppFileName ;
  227. TCHAR szApplication [MessageLen] ;
  228. switch (iPerfmonView)
  229. {
  230. case IDM_VIEWCHART:
  231. ppFileName = &pChartFileName ;
  232. break ;
  233. case IDM_VIEWALERT:
  234. ppFileName = &pAlertFileName ;
  235. break ;
  236. case IDM_VIEWREPORT:
  237. ppFileName = &pReportFileName ;
  238. break ;
  239. case IDM_VIEWLOG:
  240. ppFileName = &pLogFileName ;
  241. break ;
  242. default:
  243. ppFileName = NULL ;
  244. break ;
  245. }
  246. if (ppFileName == NULL)
  247. {
  248. ppFileName = &pWorkSpaceFileName ;
  249. }
  250. // display the name file name on the Title bar.
  251. StringLoad (IDS_APPNAME, szApplication) ;
  252. if (*ppFileName)
  253. {
  254. lstrcat (szApplication, TEXT(" - ")) ;
  255. lstrcat (szApplication, *ppFileName) ;
  256. }
  257. SetWindowText (hWndMain, szApplication) ;
  258. }
  259. void ShowPerfmonMenu (BOOL bMenu)
  260. { // ShowPerfmonMenu
  261. if (!bMenu)
  262. {
  263. WindowEnableTitle (hWndMain, FALSE) ;
  264. // SetMenu(hWndMain, NULL) ;
  265. }
  266. else
  267. {
  268. WindowEnableTitle (hWndMain, TRUE) ;
  269. switch (iPerfmonView)
  270. { // switch
  271. case IDM_VIEWCHART:
  272. SetMenu (hWndMain, hMenuChart) ;
  273. break ;
  274. case IDM_VIEWALERT:
  275. SetMenu (hWndMain, hMenuAlert) ;
  276. break ;
  277. case IDM_VIEWLOG:
  278. SetMenu (hWndMain, hMenuLog) ;
  279. break ;
  280. case IDM_VIEWREPORT:
  281. SetMenu (hWndMain, hMenuReport) ;
  282. break ;
  283. } // switch
  284. } // else
  285. if (bMenu != Options.bMenubar)
  286. {
  287. PrepareMenu (GetMenu (hWndMain)) ;
  288. }
  289. Options.bMenubar = bMenu ;
  290. // Show Window Text
  291. if (bMenu)
  292. {
  293. ShowPerfmonWindowText () ;
  294. }
  295. } // ShowPerfmonMenu
  296. void SmallFileSizeString (int iFileSize,
  297. LPTSTR lpszFileText)
  298. { // SmallFileSizeString
  299. if (iFileSize < 1000000)
  300. TSPRINTF (lpszFileText, TEXT(" %1.1fK "), ((FLOAT) iFileSize) / 1000.0f) ;
  301. else
  302. TSPRINTF (lpszFileText, TEXT(" %1.1fM "), ((FLOAT) iFileSize) / 1000000.0f) ;
  303. } // SmallFileSizeString
  304. BOOL DoWindowDrag (HWND hWnd, LPARAM lParam)
  305. {
  306. POINT lPoint ;
  307. if (!Options.bMenubar && !IsZoomed (hWndMain))
  308. {
  309. // convert lParam from client to screen
  310. lPoint.x = LOWORD (lParam) ;
  311. lPoint.y = HIWORD (lParam) ;
  312. ClientToScreen (hWnd, &lPoint) ;
  313. lParam = MAKELONG (lPoint.x, lPoint.y) ;
  314. SendMessage (hWndMain, WM_NCLBUTTONDOWN, HTCAPTION, lParam) ;
  315. return (TRUE) ;
  316. }
  317. else
  318. return (FALSE) ;
  319. }
  320. // Filetimes are in 100NS units
  321. #define FILETIMES_PER_SECOND 10000000
  322. int SystemTimeDifference (SYSTEMTIME *pst1, SYSTEMTIME *pst2, BOOL bAbs)
  323. {
  324. LARGE_INTEGER li1, li2 ;
  325. LARGE_INTEGER liDifference, liDifferenceSeconds ;
  326. DWORD uRemainder ;
  327. int RetInteger;
  328. BOOL bNegative;
  329. li1.HighPart = li1.LowPart = 0 ;
  330. li2.HighPart = li2.LowPart = 0 ;
  331. SystemTimeToFileTime (pst1, (FILETIME *) &li1) ;
  332. SystemTimeToFileTime (pst2, (FILETIME *) &li2) ;
  333. // check for special cases when the time can be 0
  334. if (li2.HighPart == 0 && li2.LowPart == 0)
  335. {
  336. if (li1.HighPart == 0 && li1.LowPart == 0)
  337. {
  338. return 0 ;
  339. }
  340. else
  341. {
  342. return -INT_MAX ;
  343. }
  344. }
  345. else if (li1.HighPart == 0 && li1.LowPart == 0)
  346. {
  347. return INT_MAX ;
  348. }
  349. liDifference.QuadPart = li2.QuadPart - li1.QuadPart ;
  350. bNegative = liDifference.QuadPart < 0 ;
  351. // add the round-off factor before doing the division
  352. if (bNegative)
  353. {
  354. liDifferenceSeconds.QuadPart = (LONGLONG)(- FILETIMES_PER_SECOND / 2) ;
  355. }
  356. else
  357. {
  358. liDifferenceSeconds.QuadPart = (LONGLONG)(FILETIMES_PER_SECOND / 2) ;
  359. }
  360. liDifferenceSeconds.QuadPart = liDifferenceSeconds.QuadPart +
  361. liDifference.QuadPart ;
  362. liDifferenceSeconds.QuadPart = liDifferenceSeconds.QuadPart /
  363. FILETIMES_PER_SECOND;
  364. RetInteger = liDifferenceSeconds.LowPart;
  365. if (bNegative && bAbs)
  366. {
  367. return (-RetInteger) ;
  368. }
  369. else
  370. {
  371. return (RetInteger) ;
  372. }
  373. }
  374. BOOL InsertLine (PLINE pLine)
  375. { // InsertLine
  376. BOOL bReturn = FALSE;
  377. switch (pLine->iLineType) { // switch
  378. case LineTypeChart:
  379. bReturn = ChartInsertLine (pGraphs, pLine) ;
  380. break ;
  381. case LineTypeAlert:
  382. bReturn = AlertInsertLine (hWndAlert, pLine) ;
  383. break ;
  384. case LineTypeReport:
  385. bReturn = ReportInsertLine (hWndReport, pLine) ;
  386. break ;
  387. } // switch
  388. return bReturn;
  389. } // InsertLine
  390. BOOL OpenWorkspace (HANDLE hFile, DWORD dwMajorVersion, DWORD dwMinorVersion)
  391. {
  392. DISKWORKSPACE DiskWorkspace ;
  393. if (!FileRead (hFile, &DiskWorkspace, sizeof(DiskWorkspace)))
  394. {
  395. goto Exit0 ;
  396. }
  397. if (DiskWorkspace.ChartOffset == 0 &&
  398. DiskWorkspace.AlertOffset == 0 &&
  399. DiskWorkspace.LogOffset == 0 &&
  400. DiskWorkspace.ReportOffset == 0)
  401. {
  402. goto Exit0 ;
  403. }
  404. switch (dwMajorVersion)
  405. { // switch
  406. case (1):
  407. if (dwMinorVersion >= 1)
  408. {
  409. // setup the window position and size
  410. DiskWorkspace.WindowPlacement.length = sizeof(WINDOWPLACEMENT);
  411. DiskWorkspace.WindowPlacement.flags = WPF_SETMINPOSITION;
  412. if (!SetWindowPlacement (hWndMain, &(DiskWorkspace.WindowPlacement)))
  413. {
  414. goto Exit0 ;
  415. }
  416. }
  417. // change to the view as stored in the workspace file
  418. SendMessage (hWndMain, WM_COMMAND,
  419. (LONG)DiskWorkspace.iPerfmonView, 0L) ;
  420. iPerfmonView = DiskWorkspace.iPerfmonView ;
  421. if (DiskWorkspace.ChartOffset)
  422. {
  423. if (FileSeekBegin(hFile, DiskWorkspace.ChartOffset) == 0xFFFFFFFF)
  424. {
  425. goto Exit0 ;
  426. }
  427. if (!OpenChart (hWndGraph,
  428. hFile,
  429. dwMajorVersion,
  430. dwMinorVersion,
  431. FALSE))
  432. {
  433. goto Exit0 ;
  434. }
  435. }
  436. if (DiskWorkspace.AlertOffset)
  437. {
  438. if (FileSeekBegin(hFile, DiskWorkspace.AlertOffset) == 0xffffffff)
  439. {
  440. goto Exit0 ;
  441. }
  442. if (!OpenAlert (hWndAlert,
  443. hFile,
  444. dwMajorVersion,
  445. dwMinorVersion,
  446. FALSE))
  447. {
  448. goto Exit0 ;
  449. }
  450. }
  451. if (DiskWorkspace.LogOffset)
  452. {
  453. if (FileSeekBegin(hFile, DiskWorkspace.LogOffset) == 0xffffffff)
  454. {
  455. goto Exit0 ;
  456. }
  457. if (!OpenLog (hWndLog,
  458. hFile,
  459. dwMajorVersion,
  460. dwMinorVersion,
  461. FALSE))
  462. {
  463. goto Exit0 ;
  464. }
  465. }
  466. if (DiskWorkspace.ReportOffset)
  467. {
  468. if (FileSeekBegin(hFile, DiskWorkspace.ReportOffset) == 0xffffffff)
  469. {
  470. goto Exit0 ;
  471. }
  472. if (!OpenReport (hWndReport,
  473. hFile,
  474. dwMajorVersion,
  475. dwMinorVersion,
  476. FALSE))
  477. {
  478. goto Exit0 ;
  479. }
  480. }
  481. break ;
  482. default:
  483. goto Exit0 ;
  484. break ;
  485. }
  486. CloseHandle (hFile) ;
  487. return (TRUE) ;
  488. Exit0:
  489. CloseHandle (hFile) ;
  490. return (FALSE) ;
  491. } // OpenWorkspace
  492. BOOL SaveWorkspace (void)
  493. {
  494. DISKWORKSPACE DiskWorkspace ;
  495. PERFFILEHEADER FileHeader ;
  496. HANDLE hFile ;
  497. long DiskWorkspacePosition ;
  498. TCHAR szFileName[FilePathLen] ;
  499. BOOL bWriteErr = TRUE ;
  500. if (!FileGetName (PerfmonViewWindow(), IDS_WORKSPACEFILE, szFileName))
  501. {
  502. return (FALSE) ;
  503. }
  504. hFile = FileHandleCreate (szFileName) ;
  505. if (!hFile || hFile == INVALID_HANDLE_VALUE)
  506. {
  507. DlgErrorBox (PerfmonViewWindow (), ERR_CANT_OPEN, szFileName) ;
  508. return (FALSE) ;
  509. }
  510. memset (&FileHeader, 0, sizeof (FileHeader)) ;
  511. lstrcpy (FileHeader.szSignature, szPerfWorkspaceSignature) ;
  512. FileHeader.dwMajorVersion = WorkspaceMajorVersion ;
  513. FileHeader.dwMinorVersion = WorkspaceMinorVersion ;
  514. if (!FileWrite (hFile, &FileHeader, sizeof (PERFFILEHEADER)))
  515. {
  516. goto Exit0 ;
  517. }
  518. // reserve space in the file. We will fill up info
  519. // and write into this guy later.
  520. memset (&DiskWorkspace, 0, sizeof(DiskWorkspace)) ;
  521. DiskWorkspacePosition = FileTell (hFile) ;
  522. DiskWorkspace.WindowPlacement.length = sizeof(WINDOWPLACEMENT);
  523. if (!GetWindowPlacement (hWndMain, &(DiskWorkspace.WindowPlacement)))
  524. {
  525. goto Exit0 ;
  526. }
  527. if (!FileWrite (hFile, &DiskWorkspace, sizeof (DISKWORKSPACE)))
  528. {
  529. goto Exit0 ;
  530. }
  531. // put in chart data
  532. DiskWorkspace.ChartOffset = FileTell (hFile) ;
  533. if (!SaveChart (hWndGraph, hFile, 0))
  534. {
  535. goto Exit0 ;
  536. }
  537. // put in alert data
  538. DiskWorkspace.AlertOffset = FileTell (hFile) ;
  539. if (!SaveAlert (hWndAlert, hFile, 0))
  540. {
  541. goto Exit0 ;
  542. }
  543. // put in log data
  544. DiskWorkspace.LogOffset = FileTell (hFile) ;
  545. if (!SaveLog (hWndLog, hFile, 0))
  546. {
  547. goto Exit0 ;
  548. }
  549. // put in report data
  550. DiskWorkspace.ReportOffset = FileTell (hFile) ;
  551. if (!SaveReport (hWndReport, hFile, 0))
  552. {
  553. goto Exit0 ;
  554. }
  555. // put in the disk header info
  556. DiskWorkspace.iPerfmonView = iPerfmonView ;
  557. FileSeekBegin (hFile, DiskWorkspacePosition) ;
  558. if (!FileWrite (hFile, &DiskWorkspace, sizeof (DISKWORKSPACE)))
  559. {
  560. goto Exit0 ;
  561. }
  562. bWriteErr = FALSE ;
  563. Exit0:
  564. if (bWriteErr)
  565. {
  566. DlgErrorBox (PerfmonViewWindow (), ERR_SETTING_FILE, szFileName) ;
  567. }
  568. CloseHandle (hFile) ;
  569. return TRUE;
  570. } // SaveWorkspace
  571. void SetPerfmonOptions (OPTIONS *pOptions)
  572. {
  573. Options = *pOptions ;
  574. ShowPerfmonMenu (Options.bMenubar) ;
  575. SizePerfmonComponents () ;
  576. WindowSetTopmost (hWndMain, Options.bAlwaysOnTop) ;
  577. } // SetPerfmonOptions
  578. void ChangeSaveFileName (LPTSTR szFileName, int iPMView)
  579. {
  580. LPTSTR *ppFullName = NULL;
  581. LPTSTR *ppFileName = NULL;
  582. BOOL errorInput = FALSE ;
  583. TCHAR szApplication [MessageLen] ;
  584. switch (iPMView)
  585. {
  586. case IDM_VIEWCHART:
  587. ppFileName = &pChartFileName ;
  588. ppFullName = &pChartFullFileName ;
  589. break ;
  590. case IDM_VIEWALERT:
  591. ppFileName = &pAlertFileName ;
  592. ppFullName = &pAlertFullFileName ;
  593. break ;
  594. case IDM_VIEWREPORT:
  595. ppFileName = &pReportFileName ;
  596. ppFullName = &pReportFullFileName ;
  597. break ;
  598. case IDM_VIEWLOG:
  599. ppFileName = &pLogFileName ;
  600. ppFullName = &pLogFullFileName ;
  601. break ;
  602. case IDM_WORKSPACE:
  603. // not a view but a define
  604. ppFileName = &pWorkSpaceFileName ;
  605. ppFullName = &pWorkSpaceFullFileName ;
  606. break ;
  607. default:
  608. errorInput = TRUE ;
  609. break ;
  610. }
  611. if (errorInput)
  612. {
  613. return ;
  614. }
  615. // release last filename
  616. if (*ppFullName)
  617. {
  618. MemoryFree (*ppFullName) ;
  619. *ppFileName = NULL ;
  620. *ppFullName = NULL ;
  621. }
  622. // allocate new file name and display it
  623. if (szFileName && (*ppFullName = StringAllocate (szFileName)))
  624. {
  625. *ppFileName = ExtractFileName (*ppFullName) ;
  626. }
  627. if (iPerfmonView == iPMView || iPMView == IDM_WORKSPACE)
  628. {
  629. StatusLineReady (hWndStatus) ;
  630. if (Options.bMenubar)
  631. {
  632. // display the name file name on the Title bar.
  633. StringLoad (IDS_APPNAME, szApplication) ;
  634. if (*ppFileName == NULL)
  635. {
  636. ppFileName = &pWorkSpaceFileName ;
  637. }
  638. if (*ppFileName)
  639. {
  640. lstrcat (szApplication, TEXT(" - ")) ;
  641. lstrcat (szApplication, *ppFileName) ;
  642. }
  643. SetWindowText (hWndMain, szApplication) ;
  644. }
  645. }
  646. } // ChangeSaveFileName
  647. BOOL
  648. IsNumberInUnicodeList (
  649. IN DWORD dwNumber,
  650. IN LPTSTR lpwszUnicodeList
  651. )
  652. /*++
  653. IsNumberInUnicodeList
  654. Arguments:
  655. IN dwNumber
  656. DWORD number to find in list
  657. IN lpwszUnicodeList
  658. Null terminated, Space delimited list of decimal numbers
  659. Return Value:
  660. TRUE:
  661. dwNumber was found in the list of unicode number strings
  662. FALSE:
  663. dwNumber was not found in the list.
  664. --*/
  665. {
  666. DWORD dwThisNumber;
  667. WCHAR *pwcThisChar;
  668. BOOL bValidNumber;
  669. BOOL bNewItem;
  670. WCHAR wcDelimiter; // could be an argument to be more flexible
  671. if (lpwszUnicodeList == 0) return FALSE; // null pointer, # not founde
  672. pwcThisChar = lpwszUnicodeList;
  673. dwThisNumber = 0;
  674. wcDelimiter = (WCHAR)' ';
  675. bValidNumber = FALSE;
  676. bNewItem = TRUE;
  677. while (TRUE) {
  678. switch (EvalThisChar (*pwcThisChar, wcDelimiter)) {
  679. case DIGIT:
  680. // if this is the first digit after a delimiter, then
  681. // set flags to start computing the new number
  682. if (bNewItem) {
  683. bNewItem = FALSE;
  684. bValidNumber = TRUE;
  685. }
  686. if (bValidNumber) {
  687. dwThisNumber *= 10;
  688. dwThisNumber += (*pwcThisChar - (WCHAR)'0');
  689. }
  690. break;
  691. case DELIMITER:
  692. // a delimter is either the delimiter character or the
  693. // end of the string ('\0') if when the delimiter has been
  694. // reached a valid number was found, then compare it to the
  695. // number from the argument list. if this is the end of the
  696. // string and no match was found, then return.
  697. //
  698. if (bValidNumber) {
  699. if (dwThisNumber == dwNumber) return TRUE;
  700. bValidNumber = FALSE;
  701. }
  702. if (*pwcThisChar == 0) {
  703. return FALSE;
  704. } else {
  705. bNewItem = TRUE;
  706. dwThisNumber = 0;
  707. }
  708. break;
  709. case INVALID:
  710. // if an invalid character was encountered, ignore all
  711. // characters up to the next delimiter and then start fresh.
  712. // the invalid number is not compared.
  713. bValidNumber = FALSE;
  714. break;
  715. default:
  716. break;
  717. }
  718. pwcThisChar++;
  719. }
  720. } // IsNumberInUnicodeList
  721. BOOL
  722. AppendObjectToValueList (
  723. DWORD dwObjectId,
  724. PWSTR pwszValueList
  725. )
  726. /*++
  727. AppendObjectToValueList
  728. Arguments:
  729. IN dwNumber
  730. DWORD number to insert in list
  731. IN PUNICODE_STRING
  732. pointer to unicode string structure that contains buffer that is
  733. Null terminated, Space delimited list of decimal numbers that
  734. may have this number appended to.
  735. Return Value:
  736. TRUE:
  737. dwNumber was added to list
  738. FALSE:
  739. dwNumber was not added. (because it's already there or
  740. an error occured)
  741. --*/
  742. {
  743. WCHAR tempString [SIZE_OF_BIGGEST_INTEGER] ;
  744. DWORD dwStrLen, dwNewStrLen;
  745. LPTSTR szFormatString;
  746. if (!pwszValueList) {
  747. return FALSE;
  748. }
  749. if (IsNumberInUnicodeList(dwObjectId, pwszValueList)) {
  750. return FALSE; // object already in list
  751. } else {
  752. // append the new object id the value list
  753. // if this is the first string to enter then don't
  754. // prefix with a space character otherwise do
  755. szFormatString = (*pwszValueList == 0) ? TEXT("%d") : TEXT(" %d");
  756. TSPRINTF (tempString, szFormatString, dwObjectId) ;
  757. // see if string will fit (compare in bytes)
  758. dwStrLen = MemorySize (pwszValueList) - sizeof (UNICODE_NULL);
  759. dwNewStrLen = (lstrlen (pwszValueList) + lstrlen (tempString)) *
  760. sizeof (WCHAR);
  761. if (dwNewStrLen <= dwStrLen) {
  762. lstrcat (pwszValueList, tempString);
  763. return TRUE;
  764. } else {
  765. SetLastError (ERROR_OUTOFMEMORY);
  766. return FALSE;
  767. }
  768. }
  769. }
  770. BOOL
  771. AddObjectToSystem (
  772. PLINE pLine,
  773. PPERFSYSTEM pFirstSystem
  774. )
  775. {
  776. PPERFSYSTEM pSystem;
  777. if ((ARGUMENT_PRESENT (pLine)) && (ARGUMENT_PRESENT(pFirstSystem))) {
  778. pSystem = SystemGet (pFirstSystem, pLine->lnSystemName);
  779. if (pSystem) {
  780. return AppendObjectToValueList (
  781. pLine->lnObject.ObjectNameTitleIndex,
  782. pSystem->lpszValue);
  783. } else {
  784. return FALSE;
  785. }
  786. } else {
  787. return FALSE;
  788. }
  789. }
  790. BOOL
  791. RemoveObjectsFromSystem (
  792. PPERFSYSTEM pSystem
  793. )
  794. {
  795. DWORD dwBufferSize = 0;
  796. if (ARGUMENT_PRESENT (pSystem)) {
  797. // don't do foreign computers
  798. if (pSystem->lpszValue && (_wcsnicmp(pSystem->lpszValue, L"Foreign", 7) != 0)){
  799. dwBufferSize = MemorySize (pSystem->lpszValue);
  800. memset (pSystem->lpszValue, 0, dwBufferSize);
  801. return TRUE;
  802. } else {
  803. return FALSE;
  804. }
  805. } else {
  806. return FALSE;
  807. }
  808. }
  809. BOOL
  810. BuildValueListForSystems (
  811. PPERFSYSTEM pSystemListHead,
  812. PLINE pLineListHead
  813. )
  814. /*++
  815. BuildValueListForSystem
  816. Abstract:
  817. Walks down line list and builds the list of objects to query from
  818. that system containing that line.
  819. Arguments:
  820. pSystemListHead
  821. head of system linked list
  822. each system will have it's "Value Name" list appended
  823. pLineListHead
  824. head of line list that will be searched for creating the new
  825. valuelist.
  826. Return Value:
  827. --*/
  828. {
  829. PPERFSYSTEM pSystem; // system that contains current line
  830. PLINE pThisLine; // current line
  831. if ((ARGUMENT_PRESENT (pLineListHead)) && (ARGUMENT_PRESENT(pSystemListHead))) {
  832. // clear system entries:
  833. for (pSystem = pSystemListHead; pSystem; pSystem = pSystem->pSystemNext) {
  834. if (pSystem && pSystem->FailureTime == 0) {
  835. RemoveObjectsFromSystem (pSystem);
  836. }
  837. }
  838. // add new enties
  839. for (pThisLine = pLineListHead; pThisLine; pThisLine = pThisLine->pLineNext) {
  840. pSystem = SystemGet (pSystemListHead, pThisLine->lnSystemName);
  841. if (pSystem && pSystem->FailureTime == 0) {
  842. AppendObjectToValueList (
  843. pThisLine->lnObject.ObjectNameTitleIndex,
  844. pSystem->lpszValue);
  845. }
  846. }
  847. return TRUE;
  848. } else { // argument(s) missing
  849. return FALSE;
  850. }
  851. }
  852. // define in Addline.c
  853. extern PLINESTRUCT pLineEdit ;
  854. #define bEditLine (pLineEdit != NULL)
  855. BOOL
  856. SetSystemValueNameToGlobal (
  857. PPERFSYSTEM pSystem
  858. )
  859. {
  860. if (!bEditLine && ARGUMENT_PRESENT(pSystem)) {
  861. if (pSystem->lpszValue && RemoveObjectsFromSystem(pSystem)) {
  862. if (pSystem->lpszValue && (_wcsnicmp(pSystem->lpszValue, L"Foreign",7) != 0)){
  863. // don't change foreign computer strings
  864. lstrcpy (
  865. pSystem->lpszValue,
  866. TEXT("Global")) ;
  867. }
  868. return TRUE;
  869. } else {
  870. return FALSE;
  871. }
  872. } else {
  873. return FALSE;
  874. }
  875. }
  876. BOOL
  877. RemoveUnusedSystems (
  878. PPERFSYSTEM pSystemHead,
  879. PLINE pLineHead
  880. )
  881. /*++
  882. walks system list and removes systems with no lines from list
  883. --*/
  884. {
  885. PPERFSYSTEM pSystem;
  886. PPERFSYSTEM pLastSystem;
  887. PLINE pLine;
  888. BOOL bSystemFound;
  889. pLastSystem = NULL;
  890. if ((ARGUMENT_PRESENT (pLineHead)) && (ARGUMENT_PRESENT(pSystemHead))) {
  891. for (pSystem = pSystemHead;
  892. pSystem != NULL;
  893. pLastSystem = pSystem, pSystem = pSystem->pSystemNext) {
  894. if (pSystem) {
  895. bSystemFound = FALSE;
  896. // walk lines to see if this system has a line
  897. for (pLine = pLineHead; pLine; pLine = pLine->pLineNext) {
  898. // if system in line is this system, then bailout
  899. if (strsame (pLine->lnSystemName, pSystem->sysName)) {
  900. bSystemFound = TRUE;
  901. break;
  902. }
  903. }
  904. if (!bSystemFound) { // delete this unused system
  905. // fix pointers
  906. if (pLastSystem)
  907. pLastSystem->pSystemNext = pSystem->pSystemNext;
  908. SystemFree (pSystem, TRUE);
  909. // set pointer back to a valid structure
  910. pSystem = pLastSystem;
  911. if (pSystem == NULL)
  912. break;
  913. }
  914. }
  915. }
  916. }
  917. return TRUE;
  918. }
  919. void CreatePerfmonSystemObjects ()
  920. {
  921. ColorBtnFace = GetSysColor (COLOR_BTNFACE) ;
  922. hBrushFace = CreateSolidBrush (ColorBtnFace) ;
  923. hPenHighlight = CreatePen (PS_SOLID, 1, GetSysColor (COLOR_BTNHIGHLIGHT)) ;
  924. hPenShadow = CreatePen (PS_SOLID, 1, GetSysColor (COLOR_BTNSHADOW)) ;
  925. SetClassLongPtr (hWndMain, GCLP_HBRBACKGROUND, (LONG_PTR)hBrushFace);
  926. }
  927. void DeletePerfmonSystemObjects ()
  928. {
  929. if (hBrushFace)
  930. {
  931. DeleteBrush (hBrushFace) ;
  932. hBrushFace = 0 ;
  933. }
  934. if (hPenHighlight)
  935. {
  936. DeletePen (hPenHighlight) ;
  937. hPenHighlight = 0 ;
  938. }
  939. if (hPenShadow)
  940. {
  941. DeletePen (hPenShadow) ;
  942. hPenShadow = 0 ;
  943. }
  944. }
  945. // This routine count the number of the same charatcer in the input string
  946. int SameCharCount (LPTSTR pInputString)
  947. {
  948. int Count = 0 ;
  949. TCHAR InputChar = *pInputString ;
  950. if (InputChar)
  951. {
  952. while (InputChar == *pInputString)
  953. {
  954. Count ++ ;
  955. pInputString ++ ;
  956. }
  957. }
  958. return (Count) ;
  959. }
  960. // create the format to be used in SystemTimeDateString()
  961. BOOL CreateDateFormat (LPTSTR pShortDate)
  962. {
  963. int iIndex ;
  964. int iDayCount ;
  965. int iMonthCount ;
  966. int DateSeparatorCount ;
  967. TCHAR szDateSeparator [10] ;
  968. BOOL bFirstLeading, bSecondLeading, bThirdLeading ;
  969. // get the date format based on the first char
  970. if (*pShortDate == TEXT('M') || *pShortDate == TEXT('m'))
  971. {
  972. DateStyle = MONTH_FIRST ;
  973. }
  974. else if (*pShortDate == TEXT('D') || *pShortDate == TEXT('d'))
  975. {
  976. DateStyle = DAY_FIRST ;
  977. }
  978. else if (*pShortDate == TEXT('Y') || *pShortDate == TEXT('y'))
  979. {
  980. DateStyle = YEAR_FIRST ;
  981. }
  982. else
  983. {
  984. // bad format
  985. return FALSE ;
  986. }
  987. bFirstLeading = bSecondLeading = bThirdLeading = FALSE ;
  988. switch (DateStyle)
  989. {
  990. case YEAR_FIRST:
  991. // YYYY-MM-DD
  992. YearCharCount = SameCharCount (pShortDate) ;
  993. pShortDate += YearCharCount ;
  994. DateSeparatorCount = SameCharCount (pShortDate) ;
  995. // get the separator string
  996. for (iIndex = 0; iIndex < DateSeparatorCount; iIndex ++)
  997. {
  998. szDateSeparator [iIndex] = *pShortDate++ ;
  999. }
  1000. szDateSeparator [iIndex] = TEXT('\0') ;
  1001. iMonthCount = SameCharCount (pShortDate) ;
  1002. pShortDate += iMonthCount + DateSeparatorCount ;
  1003. iDayCount = SameCharCount (pShortDate) ;
  1004. if (YearCharCount == 2)
  1005. {
  1006. bFirstLeading = TRUE ;
  1007. }
  1008. if (iMonthCount == 2)
  1009. {
  1010. bSecondLeading = TRUE ;
  1011. }
  1012. if (iDayCount == 2)
  1013. {
  1014. bThirdLeading = TRUE ;
  1015. }
  1016. break ;
  1017. case MONTH_FIRST:
  1018. // MM-DD-YYYY
  1019. iMonthCount = SameCharCount (pShortDate) ;
  1020. pShortDate += iMonthCount ;
  1021. DateSeparatorCount = SameCharCount (pShortDate) ;
  1022. // get the separator string
  1023. for (iIndex = 0; iIndex < DateSeparatorCount; iIndex ++)
  1024. {
  1025. szDateSeparator [iIndex] = *pShortDate++ ;
  1026. }
  1027. szDateSeparator [iIndex] = TEXT('\0') ;
  1028. iDayCount = SameCharCount (pShortDate) ;
  1029. pShortDate += iMonthCount + DateSeparatorCount ;
  1030. YearCharCount = SameCharCount (pShortDate) ;
  1031. if (iMonthCount == 2)
  1032. {
  1033. bFirstLeading = TRUE ;
  1034. }
  1035. if (iDayCount == 2)
  1036. {
  1037. bSecondLeading = TRUE ;
  1038. }
  1039. if (YearCharCount == 2)
  1040. {
  1041. bThirdLeading = TRUE ;
  1042. }
  1043. break ;
  1044. case DAY_FIRST:
  1045. // DD-MM-YYYY
  1046. iDayCount = SameCharCount (pShortDate) ;
  1047. pShortDate += iDayCount ;
  1048. DateSeparatorCount = SameCharCount (pShortDate) ;
  1049. // get the separator string
  1050. for (iIndex = 0; iIndex < DateSeparatorCount; iIndex ++)
  1051. {
  1052. szDateSeparator [iIndex] = *pShortDate++ ;
  1053. }
  1054. szDateSeparator [iIndex] = TEXT('\0') ;
  1055. iMonthCount = SameCharCount (pShortDate) ;
  1056. pShortDate += iMonthCount + DateSeparatorCount ;
  1057. YearCharCount = SameCharCount (pShortDate) ;
  1058. if (iDayCount == 2)
  1059. {
  1060. bFirstLeading = TRUE ;
  1061. }
  1062. if (iMonthCount == 2)
  1063. {
  1064. bSecondLeading = TRUE ;
  1065. }
  1066. if (YearCharCount == 2)
  1067. {
  1068. bThirdLeading = TRUE ;
  1069. }
  1070. break ;
  1071. }
  1072. // now generate the date format
  1073. lstrcpy (szDateFormat, bFirstLeading ? LeadingZeroStr : NoLeadingZeroStr) ;
  1074. lstrcat (szDateFormat, szDateSeparator) ;
  1075. lstrcat (szDateFormat, bSecondLeading ? LeadingZeroStr : NoLeadingZeroStr) ;
  1076. lstrcat (szDateFormat, szDateSeparator) ;
  1077. lstrcat (szDateFormat, bThirdLeading ? LeadingZeroStr : NoLeadingZeroStr) ;
  1078. return TRUE ;
  1079. }
  1080. BOOL CreateTimeFormat (LPTSTR pTimeSeparator, int iLeadingZero)
  1081. {
  1082. // create the format to be used in SystemTimeTimeString
  1083. if (iLeadingZero)
  1084. {
  1085. lstrcpy (szTimeFormat, LeadingZeroStr) ;
  1086. }
  1087. else
  1088. {
  1089. lstrcpy (szTimeFormat, NoLeadingZeroStr) ;
  1090. }
  1091. lstrcat (szTimeFormat, pTimeSeparator) ;
  1092. lstrcat (szTimeFormat, LeadingZeroStr) ;
  1093. lstrcat (szTimeFormat, pTimeSeparator) ;
  1094. // lstrcat (szTimeFormat, LeadingZeroStr) ;
  1095. // Duplicate the format without the msec field (for export use)
  1096. lstrcpy (szTimeFormat1, szTimeFormat) ;
  1097. // for the msec
  1098. lstrcat (szTimeFormat, TEXT("%02.1f")) ;
  1099. // for sec without msec
  1100. lstrcat (szTimeFormat1, TEXT("%02d")) ;
  1101. if (iTime == 0)
  1102. {
  1103. lstrcat (szTimeFormat, TEXT(" %s ")) ;
  1104. lstrcat (szTimeFormat1, TEXT(" %s ")) ;
  1105. }
  1106. return TRUE ;
  1107. } // CreateTimeFormats
  1108. BOOL GetInternational()
  1109. {
  1110. TCHAR szShortDate[40] ;
  1111. TCHAR szTime[40] ; // time separator
  1112. DWORD RetCode ;
  1113. int iTLZero = 0 ; // = 0 for no leading zero, <> 0 for leading zero
  1114. CHAR aLanguageStr [2] ;
  1115. LPSTR pRetStr ;
  1116. LPTSTR lpStr ;
  1117. // read the data from the win.ini (which i smapped to registry)
  1118. RetCode = GetProfileString(szInternational,
  1119. TEXT("sShortDate"), szShortDate, szShortDate, sizeof(szShortDate)/sizeof(TCHAR));
  1120. if (RetCode)
  1121. {
  1122. RetCode = GetProfileString(szInternational,
  1123. TEXT("sTime"), szTime, szTime, sizeof(szTime)/sizeof(TCHAR));
  1124. }
  1125. if (RetCode)
  1126. {
  1127. iTime = GetProfileInt(szInternational, TEXT("iTime"), iTime);
  1128. iTLZero = GetProfileInt(szInternational, TEXT("iTLZero"), iTLZero);
  1129. GetProfileString(szInternational, TEXT("sDecimal"), szDecimal, szDecimal, sizeof(szDecimal)/sizeof(TCHAR));
  1130. if (iTime == 0)
  1131. {
  1132. // get the AM PM strings for 12-hour format.
  1133. // These two strings could be NULL.
  1134. sz1159[0] = sz2359[0] = TEXT('\0') ;
  1135. GetProfileString(szInternational,
  1136. TEXT("s1159"), sz1159, sz1159, sizeof(sz1159)/sizeof(TCHAR));
  1137. GetProfileString(szInternational,
  1138. TEXT("s2359"), sz2359, sz2359, sizeof(sz2359)/sizeof(TCHAR));
  1139. }
  1140. }
  1141. // create the two formats
  1142. if (RetCode)
  1143. {
  1144. RetCode = (DWORD) CreateDateFormat (szShortDate) ;
  1145. }
  1146. if (RetCode)
  1147. {
  1148. RetCode = (DWORD) CreateTimeFormat (szTime, iTLZero) ;
  1149. }
  1150. // use the system default language numeric
  1151. aLanguageStr[0] = '\0' ;
  1152. pRetStr = setlocale(LC_NUMERIC, aLanguageStr);
  1153. // get current decimal point used by C-runtime
  1154. TSPRINTF (szShortDate, TEXT("%f"), (FLOAT)1.0) ;
  1155. lpStr = szShortDate ;
  1156. szCurrentDecimal [0] = TEXT('\0') ;
  1157. while (*lpStr != TEXT('\0'))
  1158. {
  1159. if (*lpStr == TEXT('1'))
  1160. {
  1161. lpStr++ ;
  1162. szCurrentDecimal [0] = *lpStr ;
  1163. break ;
  1164. }
  1165. lpStr++ ;
  1166. }
  1167. if (szCurrentDecimal[0] == TEXT('\0'))
  1168. {
  1169. szCurrentDecimal [0] = TEXT('.') ;
  1170. }
  1171. return (RetCode != 0) ;
  1172. } // GetInternational
  1173. // this routine is called to get the date/time formats either
  1174. // for the resource or from the registry.
  1175. void GetDateTimeFormats ()
  1176. {
  1177. PALERT pAlert ;
  1178. PLOG pLog ;
  1179. if (!GetInternational())
  1180. {
  1181. // GetInternational failed, then get default formats from resource
  1182. iTime = 0 ;
  1183. DateStyle = MONTH_FIRST ;
  1184. YearCharCount = 4 ;
  1185. StringLoad (IDS_S1159, sz1159) ;
  1186. StringLoad (IDS_S2359, sz2359) ;
  1187. StringLoad (IDS_TIME_FORMAT, szTimeFormat) ;
  1188. StringLoad (IDS_SHORT_DATE_FORMAT, szDateFormat) ;
  1189. }
  1190. WindowInvalidate (PerfmonViewWindow()) ;
  1191. // reset all the field taht may be affected by the
  1192. // language numberic changes
  1193. pAlert = AlertData (hWndMain) ;
  1194. pLog = LogData (hWndMain) ;
  1195. if (pAlert)
  1196. {
  1197. DialogSetInterval (hWndAlert, IDD_ALERTINTERVAL, pAlert->iIntervalMSecs) ;
  1198. }
  1199. if (pLog)
  1200. {
  1201. DialogSetInterval (hWndLog, IDD_LOGINTERVAL, pLog->iIntervalMSecs) ;
  1202. }
  1203. } // GetDateTimeFormats
  1204. void ConvertDecimalPoint (LPTSTR lpFloatPointStr)
  1205. {
  1206. if (szCurrentDecimal[0] == szDecimal[0])
  1207. {
  1208. // no need to convert anything
  1209. return ;
  1210. }
  1211. while (*lpFloatPointStr)
  1212. {
  1213. if (*lpFloatPointStr == szCurrentDecimal[0])
  1214. {
  1215. *lpFloatPointStr = szDecimal[0] ;
  1216. break ;
  1217. }
  1218. ++lpFloatPointStr ;
  1219. }
  1220. } // ConvertDecimalPoint
  1221. void ReconvertDecimalPoint (LPTSTR lpFloatPointStr)
  1222. {
  1223. if (szCurrentDecimal[0] == szDecimal[0])
  1224. {
  1225. // no need to convert anything
  1226. return ;
  1227. }
  1228. while (*lpFloatPointStr)
  1229. {
  1230. if (*lpFloatPointStr == szDecimal[0])
  1231. {
  1232. *lpFloatPointStr = szCurrentDecimal[0] ;
  1233. break ;
  1234. }
  1235. ++lpFloatPointStr ;
  1236. }
  1237. } // ReconvertDecimalPoint