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.

2309 lines
61 KiB

  1. /*****************************************************************************
  2. *
  3. * Report.c - This file contains the report window handler. Some of the
  4. * support routines are in RptFct.c
  5. *
  6. * Microsoft Confidential
  7. * Copyright (c) 1992-1993 Microsoft Corporation
  8. *
  9. * Author -
  10. *
  11. * Hon-Wah Chan
  12. *
  13. ****************************************************************************/
  14. #include "perfmon.h"
  15. #include <stdio.h> // for sprintf
  16. #include <string.h> // for strncpy
  17. #include "report.h" // Exported declarations for this file
  18. #include "addline.h" // for AddLine, EditLine
  19. #include "perferr.h" // for PostError
  20. #include "fileutil.h" // for FileHandleCreate
  21. #include "line.h" // for LineAppend
  22. #include "pmemory.h" // for MemoryXXX (mallloc-type) routines
  23. #include "perfdata.h" // for UpdateLines
  24. #include "perfmops.h" // for DoWindowDrag
  25. #include "playback.h" // for PlaybackLines, PlayingBackLog
  26. #include "system.h" // for SystemGet
  27. #include "utils.h"
  28. #include "menuids.h" // for IDM_VIEWREPORT
  29. #include "fileopen.h" // for FileGetName
  30. #include "counters.h" // for CounterEntry
  31. //==========================================================================//
  32. // Local Data //
  33. //==========================================================================//
  34. TCHAR szSystemFormat [ResourceStringLen] ;
  35. TCHAR szObjectFormat [ResourceStringLen] ;
  36. //=============================//
  37. // Report Class //
  38. //=============================//
  39. TCHAR szReportWindowClass[] = TEXT("PerfRpt") ;
  40. #define dwReportClassStyle (CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS)
  41. #define iReportClassExtra (0)
  42. #define iReportWindowExtra (0)
  43. #define dwReportWindowStyle (WS_CHILD | WS_VSCROLL | WS_HSCROLL)
  44. #define szValuePlaceholder TEXT("-999999999.999")
  45. #define szValueLargeHexPlaceholder TEXT(" xBBBBBBBBDDDDDDDD")
  46. #define szHexFormat TEXT("x%08lX")
  47. #define szLargeHexFormat TEXT("x%08lX%08lX")
  48. #define szLargeValueFormat TEXT("%12.0f")
  49. #define eStatusLargeValueMax ((FLOAT) 999999999.0)
  50. #define szValueFormat TEXT("%12.3f")
  51. //==========================================================================//
  52. // Local Functions //
  53. //==========================================================================//
  54. PREPORT
  55. AllocateReportData (
  56. HWND hWndReport
  57. )
  58. {
  59. PREPORT pReport ;
  60. pReport = ReportData (hWndReport) ;
  61. pReport->hWnd = hWndReport ;
  62. pReport->iStatus = iPMStatusClosed ;
  63. pReport->bManualRefresh = FALSE ;
  64. pReport->bModified = FALSE ;
  65. pReport->Visual.iColorIndex = 0 ;
  66. pReport->Visual.iWidthIndex = -1 ;
  67. pReport->Visual.iStyleIndex = -1 ;
  68. pReport->iIntervalMSecs = iDefaultReportIntervalSecs * 1000 ;
  69. pReport->pSystemFirst = NULL ;
  70. pReport->pLineFirst = NULL ;
  71. pReport->pLineLast = NULL ;
  72. pReport->CurrentItemType = REPORT_TYPE_NOTHING ;
  73. pReport->CurrentItem.pLine = NULL ;
  74. return (pReport) ;
  75. }
  76. void FreeReportData (PREPORT pReport) {}
  77. void
  78. ReportLineAppend (
  79. PREPORT pReport,
  80. PLINE pLineNew
  81. )
  82. {
  83. if (pReport->pLineFirst == NULL) {
  84. pReport->pLineLast =
  85. pReport->pLineFirst = pLineNew ;
  86. } else {
  87. (pReport->pLineLast)->pLineNext = pLineNew ;
  88. pReport->pLineLast = pLineNew;
  89. }
  90. }
  91. BOOL
  92. LineCounterRemove (
  93. PCOUNTERGROUP pCGroup,
  94. PLINE pLineRemove
  95. )
  96. {
  97. PLINE pLine ;
  98. if (pCGroup->pLineFirst == pLineRemove) {
  99. pCGroup->pLineFirst = (pCGroup->pLineFirst)->pLineCounterNext ;
  100. return (TRUE) ;
  101. }
  102. for (pLine = pCGroup->pLineFirst ;
  103. pLine->pLineCounterNext ;
  104. pLine = pLine->pLineCounterNext) { // for
  105. if (pLine->pLineCounterNext == pLineRemove) {
  106. pLine->pLineCounterNext = pLineRemove->pLineCounterNext ;
  107. if (pLineRemove == pCGroup->pLineLast) {
  108. pCGroup->pLineLast = pLine;
  109. }
  110. return (TRUE) ;
  111. }
  112. }
  113. return (FALSE) ;
  114. }
  115. void
  116. DrawCounter (
  117. HDC hDC,
  118. PREPORT pReport,
  119. PCOUNTERGROUP pCounterGroup
  120. )
  121. {
  122. RECT Rect ;
  123. if (!pCounterGroup->pLineFirst)
  124. return ;
  125. SelectFont (hDC, pReport->hFont) ;
  126. TextOut (hDC, xCounterMargin, pCounterGroup->yLine,
  127. pCounterGroup->pLineFirst->lnCounterName,
  128. lstrlen (pCounterGroup->pLineFirst->lnCounterName)) ;
  129. if (pCounterGroup == pReport->CurrentItem.pCounter) {
  130. ReportCounterRect (pReport, pCounterGroup, &Rect) ;
  131. DrawFocusRect (hDC, &Rect) ;
  132. }
  133. }
  134. void
  135. DrawObject (
  136. HDC hDC,
  137. PREPORT pReport,
  138. POBJECTGROUP pObjectGroup
  139. )
  140. {
  141. TCHAR szLine [LongTextLen] ;
  142. PCOUNTERGROUP pCounterGroup ;
  143. PCOLUMNGROUP pColumnGroup ;
  144. if (!pObjectGroup->pCounterGroupFirst) {
  145. return ;
  146. }
  147. SelectFont (hDC, pReport->hFontHeaders) ;
  148. SetTextAlign (hDC, TA_RIGHT) ;
  149. for (pColumnGroup = pObjectGroup->pColumnGroupFirst ;
  150. pColumnGroup ;
  151. pColumnGroup = pColumnGroup->pColumnGroupNext) {
  152. // Draw Parent
  153. if (pColumnGroup->lpszParentName)
  154. TextOut (hDC,
  155. ValueMargin (pReport) +
  156. pColumnGroup->xPos + pColumnGroup->xWidth,
  157. pObjectGroup->yFirstLine - pReport->yLineHeight,
  158. pColumnGroup->lpszParentName,
  159. lstrlen (pColumnGroup->lpszParentName)) ;
  160. // Draw Instance
  161. if (pColumnGroup->lpszInstanceName) {
  162. TextOut (hDC,
  163. ValueMargin (pReport) +
  164. pColumnGroup->xPos + pColumnGroup->xWidth,
  165. pObjectGroup->yFirstLine,
  166. pColumnGroup->lpszInstanceName,
  167. lstrlen (pColumnGroup->lpszInstanceName)) ;
  168. }
  169. if (pColumnGroup == pReport->CurrentItem.pColumn) {
  170. RECT Rect ;
  171. ReportColumnRect (pReport, pColumnGroup, &Rect) ;
  172. DrawFocusRect (hDC, &Rect) ;
  173. }
  174. }
  175. SetTextAlign (hDC, TA_LEFT) ;
  176. TSPRINTF (szLine, szObjectFormat, pObjectGroup->lpszObjectName) ;
  177. TextOut (hDC,
  178. xObjectMargin, pObjectGroup->yFirstLine,
  179. szLine, lstrlen (szLine)) ;
  180. if (pObjectGroup == pReport->CurrentItem.pObject) {
  181. RECT Rect ;
  182. ReportObjectRect (pReport, pObjectGroup, &Rect) ;
  183. DrawFocusRect (hDC, &Rect) ;
  184. }
  185. SelectFont (hDC, pReport->hFont) ;
  186. for (pCounterGroup = pObjectGroup->pCounterGroupFirst;
  187. pCounterGroup;
  188. pCounterGroup = pCounterGroup->pCounterGroupNext) {
  189. DrawCounter (hDC, pReport, pCounterGroup) ;
  190. }
  191. }
  192. void
  193. DrawSystem (
  194. HDC hDC,
  195. PREPORT pReport,
  196. PSYSTEMGROUP pSystemGroup
  197. )
  198. {
  199. TCHAR szLine [LongTextLen] ;
  200. POBJECTGROUP pObjectGroup ;
  201. SelectFont (hDC, pReport->hFontHeaders) ;
  202. if (!pSystemGroup->pObjectGroupFirst)
  203. return ;
  204. SetTextAlign (hDC, TA_LEFT) ;
  205. TSPRINTF (szLine, szSystemFormat, pSystemGroup->lpszSystemName) ;
  206. TextOut (hDC,
  207. xSystemMargin, pSystemGroup->yFirstLine,
  208. szLine, lstrlen (szLine)) ;
  209. if (pSystemGroup == pReport->CurrentItem.pSystem) {
  210. RECT Rect ;
  211. ReportSystemRect (pReport, pSystemGroup, &Rect) ;
  212. DrawFocusRect (hDC, &Rect) ;
  213. }
  214. for (pObjectGroup = pSystemGroup->pObjectGroupFirst ;
  215. pObjectGroup ;
  216. pObjectGroup = pObjectGroup->pObjectGroupNext) {
  217. DrawObject (hDC, pReport, pObjectGroup) ;
  218. }
  219. }
  220. void
  221. DrawReportValue (
  222. HDC hDC,
  223. PREPORT pReport,
  224. PLINE pLine
  225. )
  226. {
  227. TCHAR szValue [20] ;
  228. FLOAT eValue ;
  229. RECT rectValue ;
  230. // skip until we have collect enough samples for the first data
  231. if (pLine->bFirstTime == 0) {
  232. eValue = CounterEntry (pLine) ;
  233. if (pLine->lnCounterType == PERF_COUNTER_RAWCOUNT_HEX ||
  234. pLine->lnCounterType == PERF_COUNTER_LARGE_RAWCOUNT_HEX) {
  235. if (pLine->lnCounterType == PERF_COUNTER_RAWCOUNT_HEX ||
  236. pLine->lnaCounterValue[0].HighPart == 0) {
  237. TSPRINTF (szValue,
  238. szHexFormat,
  239. pLine->lnaCounterValue[0].LowPart) ;
  240. } else {
  241. TSPRINTF (szValue,
  242. szLargeHexFormat,
  243. pLine->lnaCounterValue[0].HighPart,
  244. pLine->lnaCounterValue[0].LowPart) ;
  245. }
  246. } else {
  247. TSPRINTF (szValue,
  248. (eValue > eStatusLargeValueMax) ?
  249. szLargeValueFormat : szValueFormat,
  250. eValue) ;
  251. ConvertDecimalPoint (szValue) ;
  252. }
  253. } else {
  254. // draw "- - - -"
  255. lstrcpy(szValue, DashLine);
  256. }
  257. ReportLineValueRect (pReport, pLine, &rectValue) ;
  258. ExtTextOut (hDC,
  259. rectValue.right - 2, rectValue.top,
  260. ETO_CLIPPED | ETO_OPAQUE,
  261. &rectValue,
  262. szValue, lstrlen (szValue), NULL) ;
  263. if (pReport->CurrentItemType == REPORT_TYPE_LINE &&
  264. pLine == pReport->CurrentItem.pLine) {
  265. DrawFocusRect (hDC, &rectValue) ;
  266. }
  267. }
  268. void
  269. DrawReportValues (
  270. HDC hDC,
  271. PREPORT pReport
  272. )
  273. {
  274. PSYSTEMGROUP pSystemGroup ;
  275. POBJECTGROUP pObjectGroup ;
  276. PCOUNTERGROUP pCounterGroup ;
  277. PLINE pLine ;
  278. SelectFont (hDC, pReport->hFont) ;
  279. SetTextAlign (hDC, TA_RIGHT) ;
  280. for (pSystemGroup = pReport->pSystemGroupFirst ;
  281. pSystemGroup ;
  282. pSystemGroup = pSystemGroup->pSystemGroupNext) {
  283. for (pObjectGroup = pSystemGroup->pObjectGroupFirst ;
  284. pObjectGroup ;
  285. pObjectGroup = pObjectGroup->pObjectGroupNext) {
  286. for (pCounterGroup = pObjectGroup->pCounterGroupFirst ;
  287. pCounterGroup ;
  288. pCounterGroup = pCounterGroup->pCounterGroupNext) {
  289. for (pLine = pCounterGroup->pLineFirst ;
  290. pLine ;
  291. pLine = pLine->pLineCounterNext) {
  292. DrawReportValue (hDC, pReport, pLine) ;
  293. }
  294. }
  295. }
  296. }
  297. }
  298. void
  299. DrawReportHeaders (
  300. HDC hDC,
  301. PREPORT pReport
  302. )
  303. {
  304. PSYSTEMGROUP pSystemGroup ;
  305. for (pSystemGroup = pReport->pSystemGroupFirst ;
  306. pSystemGroup ;
  307. pSystemGroup = pSystemGroup->pSystemGroupNext) {
  308. DrawSystem (hDC, pReport, pSystemGroup) ;
  309. }
  310. }
  311. void
  312. DrawReport (
  313. HDC hDC,
  314. PREPORT pReport
  315. )
  316. {
  317. SetBkColor (hDC, GetSysColor(COLOR_WINDOW)) ;
  318. DrawReportHeaders (hDC, pReport) ;
  319. //UpdateLines (&(pReport->pSystemFirst), pReport->pLineFirst) ;
  320. DrawReportValues (hDC, pReport) ;
  321. }
  322. void
  323. SetLinePosition (
  324. HDC hDC,
  325. PREPORT pReport,
  326. POBJECTGROUP pObjectGroup,
  327. PLINE pLine
  328. )
  329. {
  330. PCOLUMNGROUP pColumnGroup ;
  331. pColumnGroup = GetColumnGroup (pReport, pObjectGroup, pLine) ;
  332. if (!pColumnGroup) {
  333. pLine->xReportPos = 0 ;
  334. pLine->iReportColumn = -1 ;
  335. } else {
  336. pLine->xReportPos = pColumnGroup->xPos ;
  337. pLine->iReportColumn = pColumnGroup->ColumnNumber ;
  338. }
  339. }
  340. void
  341. SetCounterPositions (
  342. HDC hDC,
  343. PREPORT pReport,
  344. POBJECTGROUP pObjectGroup,
  345. PCOUNTERGROUP pCounterGroup,
  346. int yLine
  347. )
  348. {
  349. PLINE pLine ;
  350. int yPos ;
  351. if (!pCounterGroup->pLineFirst)
  352. return ;
  353. yPos = pCounterGroup->yLine ;
  354. SelectFont (hDC, pReport->hFontHeaders) ;
  355. for (pLine = pCounterGroup->pLineFirst ;
  356. pLine ;
  357. pLine = pLine->pLineCounterNext) {
  358. SetLinePosition (hDC, pReport, pObjectGroup, pLine) ;
  359. pLine->yReportPos = yPos ;
  360. }
  361. }
  362. void
  363. SetColumnPositions (
  364. HDC hDC,
  365. PREPORT pReport,
  366. POBJECTGROUP pObjectGroup
  367. )
  368. {
  369. int xPos ;
  370. PCOLUMNGROUP pColumnGroup ;
  371. xPos = 0 ;
  372. for (pColumnGroup = pObjectGroup->pColumnGroupFirst ;
  373. pColumnGroup ;
  374. pColumnGroup = pColumnGroup->pColumnGroupNext) {
  375. pColumnGroup->xWidth = max (max (pColumnGroup->ParentNameTextWidth,
  376. pColumnGroup->InstanceNameTextWidth),
  377. pReport->xValueWidth) ;
  378. pColumnGroup->xPos = xPos ;
  379. pColumnGroup->yFirstLine = pObjectGroup->yFirstLine ;
  380. xPos += (pColumnGroup->xWidth + xColumnMargin) ;
  381. }
  382. }
  383. void
  384. SetObjectPositions (
  385. HDC hDC,
  386. PREPORT pReport,
  387. POBJECTGROUP pObjectGroup,
  388. int yLine
  389. )
  390. /*
  391. Effect: Determine and set the logical coordinates for the
  392. object pObject within the report pReport.
  393. For each instance x counter, determine the appropriate
  394. column, adding a column description to the object if
  395. needed.
  396. Called By: SetSystemPositions only.
  397. See Also: SetSystemPositions, SetCounterPositions, ColumnGroup.
  398. */
  399. {
  400. PCOUNTERGROUP pCounterGroup ;
  401. int yPos ;
  402. PLINE pLine ;
  403. // check if there is parent name for this object type
  404. // if so, need to add extra space for the parent name
  405. if (pObjectGroup->pCounterGroupFirst) {
  406. pCounterGroup = pObjectGroup->pCounterGroupFirst ;
  407. pLine = pCounterGroup->pLineFirst ;
  408. if (pLine && LineParentName(pLine)) {
  409. pObjectGroup->yFirstLine += yLine ;
  410. }
  411. }
  412. SetColumnPositions (hDC, pReport, pObjectGroup) ;
  413. yPos = pObjectGroup->yFirstLine + yLine ;
  414. for (pCounterGroup = pObjectGroup->pCounterGroupFirst ;
  415. pCounterGroup ;
  416. pCounterGroup = pCounterGroup->pCounterGroupNext) {
  417. pCounterGroup->yLine = yPos + yLine ;
  418. SetCounterPositions (hDC, pReport, pObjectGroup, pCounterGroup, yLine) ;
  419. yPos = pCounterGroup->yLine ;
  420. }
  421. pObjectGroup->yLastLine = yPos + yLine ;
  422. }
  423. void
  424. SetSystemPositions (
  425. HDC hDC,
  426. PREPORT pReport,
  427. PSYSTEMGROUP pSystemGroup,
  428. int yLine
  429. )
  430. {
  431. POBJECTGROUP pObjectGroup ;
  432. int yPos ;
  433. yPos = pSystemGroup->yFirstLine ;
  434. for (pObjectGroup = pSystemGroup->pObjectGroupFirst ;
  435. pObjectGroup ;
  436. pObjectGroup = pObjectGroup->pObjectGroupNext) {
  437. pObjectGroup->yFirstLine = yPos + yLine ;
  438. SetObjectPositions (hDC, pReport, pObjectGroup, yLine) ;
  439. yPos = pObjectGroup->yLastLine ;
  440. }
  441. pSystemGroup->yLastLine = yPos + yLine ;
  442. }
  443. void
  444. static
  445. SetScrollRanges (
  446. HWND hWnd
  447. )
  448. {
  449. PREPORT pReport ;
  450. RECT rectClient ;
  451. int xWidth, yHeight ;
  452. GetClientRect (hWnd, &rectClient) ;
  453. xWidth = rectClient.right - rectClient.left ;
  454. yHeight = rectClient.bottom - rectClient.top ;
  455. pReport = ReportData (hWnd) ;
  456. SetScrollRange (hWnd, SB_VERT,
  457. 0, max (0, pReport->yHeight - yHeight),
  458. TRUE) ;
  459. SetScrollRange (hWnd, SB_HORZ,
  460. 0, max (0, pReport->xWidth - xWidth),
  461. TRUE) ;
  462. }
  463. //==========================================================================//
  464. // Message Handlers //
  465. //==========================================================================//
  466. void
  467. static
  468. OnCreate (
  469. HWND hWnd
  470. )
  471. {
  472. HDC hDC ;
  473. PREPORT pReport ;
  474. pReport = AllocateReportData (hWnd) ;
  475. if (!pReport)
  476. return ;
  477. pReport->hFont = hFontScales ;
  478. pReport->hFontHeaders = hFontScalesBold ;
  479. pReport->pLineFirst = NULL ;
  480. pReport->pSystemFirst = NULL ;
  481. pReport->pSystemGroupFirst = NULL ;
  482. hDC = GetDC (hWnd) ;
  483. SelectFont (hDC, pReport->hFont) ;
  484. pReport->yLineHeight = FontHeight (hDC, TRUE) ;
  485. pReport->xValueWidth = TextWidth (hDC, szValuePlaceholder) ;
  486. ReleaseDC (hWnd, hDC) ;
  487. pReport->xWidth = 0 ;
  488. pReport->yHeight = 0 ;
  489. StringLoad (IDS_SYSTEMFORMAT, szSystemFormat) ;
  490. StringLoad (IDS_OBJECTFORMAT, szObjectFormat) ;
  491. }
  492. void
  493. static
  494. OnPaint (
  495. HWND hWnd
  496. )
  497. {
  498. HDC hDC ;
  499. PAINTSTRUCT ps ;
  500. PREPORT pReport ;
  501. pReport = ReportData (hWnd) ;
  502. hDC = BeginPaint (hWnd, &ps) ;
  503. //hDC = hReportDC ;
  504. SetWindowOrgEx (hDC,
  505. GetScrollPos (hWnd, SB_HORZ),
  506. GetScrollPos (hWnd, SB_VERT),
  507. NULL) ;
  508. DrawReport (hDC, pReport) ;
  509. EndPaint (hWnd, &ps) ;
  510. }
  511. void
  512. static
  513. UpdateReportValues (
  514. PREPORT pReport
  515. )
  516. /*
  517. Effect: Redraw all the visible report values of pReport.
  518. Since drawing the values completely covers any
  519. previous values, there is no need to erase (or flicker)
  520. between updating values.
  521. Called By: ReportTimer, OnVScroll, OnHScroll.
  522. */
  523. {
  524. HDC hDC ;
  525. hDC = GetDC (pReport->hWnd) ;
  526. if (!hDC)
  527. return;
  528. SetBkColor (hDC, GetSysColor(COLOR_WINDOW)) ;
  529. SetWindowOrgEx (hDC,
  530. GetScrollPos (pReport->hWnd, SB_HORZ),
  531. GetScrollPos (pReport->hWnd, SB_VERT),
  532. NULL) ;
  533. DrawReportValues (hDC, pReport) ;
  534. ReleaseDC (pReport->hWnd, hDC) ;
  535. }
  536. void
  537. static
  538. OnHScroll (
  539. HWND hWnd,
  540. int iScrollCode,
  541. int iScrollNewPos
  542. )
  543. {
  544. PREPORT pReport ;
  545. int iScrollAmt, iScrollPos, iScrollRange ;
  546. int iScrollLo ;
  547. RECT rectClient ;
  548. int xWidth ;
  549. pReport = ReportData (hWnd) ;
  550. GetClientRect (hWnd, &rectClient) ;
  551. xWidth = rectClient.right - rectClient.left ;
  552. if (pReport->xWidth <= xWidth) {
  553. // no horz scroll bar, forget it
  554. return ;
  555. }
  556. iScrollPos = GetScrollPos (hWnd, SB_HORZ) ;
  557. GetScrollRange (hWnd, SB_HORZ, &iScrollLo, &iScrollRange) ;
  558. switch (iScrollCode) {
  559. case SB_LINEUP:
  560. iScrollAmt = - Report.yLineHeight ;
  561. break ;
  562. case SB_LINEDOWN:
  563. iScrollAmt = Report.yLineHeight ;
  564. break ;
  565. case SB_PAGEUP:
  566. iScrollAmt = - (rectClient.right - rectClient.left) / 2 ;
  567. break ;
  568. case SB_PAGEDOWN:
  569. iScrollAmt = (rectClient.right - rectClient.left) / 2 ;
  570. break ;
  571. case SB_THUMBPOSITION:
  572. iScrollAmt = iScrollNewPos - iScrollPos ;
  573. break ;
  574. default:
  575. iScrollAmt = 0 ;
  576. }
  577. iScrollAmt = PinInclusive (iScrollAmt,
  578. -iScrollPos,
  579. iScrollRange - iScrollPos) ;
  580. if (iScrollAmt) {
  581. iScrollPos += iScrollAmt ;
  582. ScrollWindow (hWnd, -iScrollAmt, 0, NULL, NULL) ;
  583. SetScrollPos (hWnd, SB_HORZ, iScrollPos, TRUE) ;
  584. UpdateWindow (hWnd) ;
  585. #if 0
  586. UpdateReportValues (pReport) ;
  587. #endif
  588. }
  589. }
  590. void
  591. static
  592. OnVScroll (
  593. HWND hWnd,
  594. int iScrollCode,
  595. int iScrollNewPos
  596. )
  597. {
  598. PREPORT pReport ;
  599. int iScrollAmt, iScrollPos, iScrollRange ;
  600. int iScrollLo ;
  601. RECT rectClient ;
  602. pReport = ReportData (hWnd) ;
  603. iScrollPos = GetScrollPos (hWnd, SB_VERT) ;
  604. GetScrollRange (hWnd, SB_VERT, &iScrollLo, &iScrollRange) ;
  605. GetClientRect (hWnd, &rectClient) ;
  606. switch (iScrollCode) {
  607. case SB_LINEUP:
  608. iScrollAmt = - Report.yLineHeight ;
  609. break ;
  610. case SB_LINEDOWN:
  611. iScrollAmt = Report.yLineHeight ;
  612. break ;
  613. case SB_PAGEUP:
  614. iScrollAmt = - (rectClient.bottom - rectClient.top) / 2 ;
  615. break ;
  616. case SB_PAGEDOWN:
  617. iScrollAmt = (rectClient.bottom - rectClient.top) / 2 ;
  618. break ;
  619. case SB_THUMBPOSITION:
  620. iScrollAmt = iScrollNewPos - iScrollPos ;
  621. break ;
  622. default:
  623. iScrollAmt = 0 ;
  624. }
  625. iScrollAmt = PinInclusive (iScrollAmt,
  626. -iScrollPos,
  627. iScrollRange - iScrollPos) ;
  628. if (iScrollAmt) {
  629. iScrollPos += iScrollAmt ;
  630. ScrollWindow (hWnd, 0, -iScrollAmt, NULL, NULL) ;
  631. SetScrollPos (hWnd, SB_VERT, iScrollPos, TRUE) ;
  632. // WindowInvalidate (hWnd) ;
  633. UpdateWindow (hWnd) ;
  634. #if 0
  635. UpdateReportValues (pReport) ;
  636. #endif
  637. }
  638. }
  639. void
  640. static
  641. OnKeyDown (
  642. HWND hWnd,
  643. WPARAM wParam
  644. )
  645. {
  646. switch (wParam) {
  647. case VK_UP:
  648. OnVScroll (hWnd, SB_LINEUP, 0) ;
  649. break ;
  650. case VK_DOWN:
  651. OnVScroll (hWnd, SB_LINEDOWN, 0) ;
  652. break ;
  653. case VK_LEFT:
  654. OnHScroll (hWnd, SB_LINEUP, 0) ;
  655. break ;
  656. case VK_RIGHT:
  657. OnHScroll (hWnd, SB_LINEDOWN, 0) ;
  658. break ;
  659. case VK_PRIOR:
  660. OnVScroll (hWnd, SB_PAGEUP, 0) ;
  661. break ;
  662. case VK_NEXT:
  663. OnVScroll (hWnd, SB_PAGEDOWN, 0) ;
  664. break ;
  665. }
  666. }
  667. LRESULT
  668. APIENTRY
  669. ReportWndProc (
  670. HWND hWnd,
  671. UINT wMsg,
  672. WPARAM wParam,
  673. LPARAM lParam
  674. )
  675. {
  676. BOOL bCallDefProc ;
  677. LRESULT lReturnValue ;
  678. bCallDefProc = FALSE ;
  679. lReturnValue = 0L ;
  680. switch (wMsg) {
  681. case WM_CREATE:
  682. OnCreate (hWnd) ;
  683. break ;
  684. case WM_LBUTTONDOWN:
  685. if (!OnReportLButtonDown (hWnd, LOWORD (lParam), HIWORD (lParam))) {
  686. // mouse click do not hit on any entries, see if we
  687. // need to drag Perfmon
  688. if (!(Options.bMenubar)) {
  689. DoWindowDrag (hWnd, lParam) ;
  690. }
  691. }
  692. break ;
  693. case WM_LBUTTONDBLCLK:
  694. SendMessage (hWndMain, WM_LBUTTONDBLCLK, wParam, lParam) ;
  695. break ;
  696. case WM_PAINT:
  697. OnPaint (hWnd) ;
  698. break ;
  699. case WM_SIZE:
  700. SetScrollRanges (hWnd) ;
  701. break ;
  702. case WM_HSCROLL:
  703. OnHScroll (hWnd, LOWORD (wParam), HIWORD (wParam)) ;
  704. break ;
  705. case WM_VSCROLL:
  706. OnVScroll (hWnd, LOWORD (wParam), HIWORD (wParam)) ;
  707. break ;
  708. case WM_TIMER:
  709. ReportTimer (hWnd, FALSE) ;
  710. break ;
  711. case WM_KEYDOWN:
  712. OnKeyDown (hWnd, wParam) ;
  713. break ;
  714. case WM_DESTROY:
  715. KillTimer (hWnd, ReportTimerID) ;
  716. break ;
  717. default:
  718. bCallDefProc = TRUE ;
  719. }
  720. if (bCallDefProc)
  721. lReturnValue = DefWindowProc (hWnd, wMsg, wParam, lParam) ;
  722. return (lReturnValue);
  723. }
  724. //==========================================================================//
  725. // Exported Functions //
  726. //==========================================================================//
  727. void
  728. SetReportTimer (
  729. PREPORT pReport
  730. )
  731. {
  732. if (pReport->iStatus == iPMStatusCollecting)
  733. KillTimer (pReport->hWnd, ReportTimerID) ;
  734. SetTimer (pReport->hWnd, ReportTimerID,
  735. pReport->iIntervalMSecs , NULL) ;
  736. pReport->iStatus = iPMStatusCollecting ;
  737. }
  738. void
  739. ClearReportTimer (
  740. PREPORT pReport
  741. )
  742. {
  743. pReport->iStatus = iPMStatusClosed ;
  744. KillTimer (pReport->hWnd, ReportTimerID) ;
  745. }
  746. BOOL
  747. ReportInitializeApplication (void)
  748. {
  749. BOOL bSuccess ;
  750. WNDCLASS wc ;
  751. //=============================//
  752. // Register ReportWindow class //
  753. //=============================//
  754. wc.style = dwReportClassStyle ;
  755. wc.lpfnWndProc = ReportWndProc ;
  756. wc.hInstance = hInstance ;
  757. wc.cbClsExtra = iReportWindowExtra ;
  758. wc.cbWndExtra = iReportClassExtra ;
  759. wc.hIcon = NULL ;
  760. wc.hCursor = LoadCursor(NULL, IDC_ARROW) ;
  761. // wc.hbrBackground = GetStockObject (WHITE_BRUSH) ;
  762. wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1) ;
  763. wc.lpszMenuName = NULL ;
  764. wc.lpszClassName = szReportWindowClass ;
  765. bSuccess = RegisterClass (&wc) ;
  766. //=============================//
  767. // Register Child classes //
  768. //=============================//
  769. return (bSuccess) ;
  770. }
  771. HWND
  772. CreateReportWindow (
  773. HWND hWndParent
  774. )
  775. /*
  776. Effect: Create the graph window. This window is a child of
  777. hWndMain and is a container for the graph data,
  778. graph label, graph legend, and graph status windows.
  779. Note: We dont worry about the size here, as this window
  780. will be resized whenever the main window is resized.
  781. */
  782. {
  783. return (CreateWindow (szReportWindowClass, // window class
  784. NULL, // caption
  785. dwReportWindowStyle, // style for window
  786. 0, 0, // initial position
  787. 0, 0, // initial size
  788. hWndParent, // parent
  789. NULL, // menu
  790. hInstance, // program instance
  791. NULL)) ; // user-supplied data
  792. }
  793. void
  794. SetReportPositions (
  795. HDC hDC,
  796. PREPORT pReport
  797. )
  798. {
  799. PSYSTEMGROUP pSystemGroup ;
  800. int yLine ;
  801. int yPos ;
  802. // pReport->xMaxCounterWidth = 0 ;
  803. yLine = pReport->yLineHeight ;
  804. yPos = 2 * yLine ;
  805. for (pSystemGroup = pReport->pSystemGroupFirst ;
  806. pSystemGroup ;
  807. pSystemGroup = pSystemGroup->pSystemGroupNext) {
  808. pSystemGroup->yFirstLine = yPos + yLine ;
  809. SetSystemPositions (hDC, pReport, pSystemGroup, yLine) ;
  810. yPos = pSystemGroup->yLastLine ;
  811. }
  812. pReport->yHeight = yPos ;
  813. SetScrollRanges (pReport->hWnd) ;
  814. }
  815. void
  816. PlaybackReport (
  817. HWND hWndReport
  818. )
  819. {
  820. PREPORT pReport ;
  821. pReport = ReportData (hWndReport) ;
  822. PlaybackLines (pReport->pSystemFirst,
  823. pReport->pLineFirst,
  824. PlaybackLog.StartIndexPos.iPosition) ;
  825. PlaybackLines (pReport->pSystemFirst,
  826. pReport->pLineFirst,
  827. PlaybackLog.StopIndexPos.iPosition) ;
  828. }
  829. BOOL
  830. CurrentReportItem (
  831. HWND hWndReport
  832. )
  833. {
  834. PREPORT pReport ;
  835. pReport = ReportData (hWndReport) ;
  836. if (!pReport)
  837. return (FALSE) ;
  838. return (pReport->CurrentItemType != REPORT_TYPE_NOTHING) ;
  839. }
  840. BOOL
  841. AddReport (
  842. HWND hWndParent
  843. )
  844. {
  845. PREPORT pReport ;
  846. LPTSTR pCurrentSystem ;
  847. POBJECTGROUP pParentObject ;
  848. pReport = ReportData (hWndReport) ;
  849. if (pReport->CurrentItemType == REPORT_TYPE_LINE) {
  850. pCurrentSystem = pReport->CurrentItem.pLine->lnSystemName ;
  851. } else if (pReport->CurrentItemType == REPORT_TYPE_SYSTEM) {
  852. pCurrentSystem = pReport->CurrentItem.pSystem->lpszSystemName ;
  853. } else if (pReport->CurrentItemType == REPORT_TYPE_OBJECT) {
  854. pCurrentSystem = pReport->CurrentItem.pObject->pParentSystem->lpszSystemName ;
  855. } else if (pReport->CurrentItemType == REPORT_TYPE_COLUMN) {
  856. pParentObject = pReport->CurrentItem.pColumn->pParentObject ;
  857. pCurrentSystem = pParentObject->pParentSystem->lpszSystemName ;
  858. } else if (pReport->CurrentItemType == REPORT_TYPE_COUNTER) {
  859. pParentObject = pReport->CurrentItem.pCounter->pParentObject ;
  860. pCurrentSystem = pParentObject->pParentSystem->lpszSystemName ;
  861. } else {
  862. pCurrentSystem = NULL ;
  863. }
  864. return (AddLine (hWndParent,
  865. &(pReport->pSystemFirst),
  866. &(pReport->Visual),
  867. pCurrentSystem,
  868. LineTypeReport)) ;
  869. }
  870. BOOL
  871. ToggleReportRefresh (
  872. HWND hWnd
  873. )
  874. {
  875. PREPORT pReport ;
  876. pReport = ReportData (hWnd) ;
  877. if (pReport->bManualRefresh)
  878. SetReportTimer (pReport) ;
  879. else
  880. ClearReportTimer (pReport) ;
  881. pReport->bManualRefresh = !pReport->bManualRefresh ;
  882. return (pReport->bManualRefresh) ;
  883. }
  884. BOOL
  885. ReportRefresh (
  886. HWND hWnd
  887. )
  888. {
  889. PREPORT pReport ;
  890. pReport = ReportData (hWnd) ;
  891. return (pReport->bManualRefresh) ;
  892. }
  893. void
  894. ReportTimer (
  895. HWND hWnd,
  896. BOOL bForce
  897. )
  898. {
  899. PREPORT pReport ;
  900. pReport = ReportData (hWnd) ;
  901. if (PlayingBackLog () || !pReport) {
  902. return;
  903. }
  904. if (bForce || !pReport->bManualRefresh) {
  905. UpdateLines (&(pReport->pSystemFirst), pReport->pLineFirst) ;
  906. if (iPerfmonView == IDM_VIEWREPORT && !bPerfmonIconic) {
  907. // only need to draw the data when we are viewing it...
  908. UpdateReportValues (pReport) ;
  909. }
  910. }
  911. }
  912. BOOL
  913. SaveReport (
  914. HWND hWndReport,
  915. HANDLE hInputFile,
  916. BOOL bGetFileName
  917. )
  918. {
  919. PREPORT pReport ;
  920. PLINE pLine ;
  921. HANDLE hFile = NULL;
  922. DISKREPORT DiskReport ;
  923. PERFFILEHEADER FileHeader ;
  924. TCHAR szFileName [256] ;
  925. BOOL newFileName = FALSE ;
  926. pReport = ReportData (hWndReport) ;
  927. if (!pReport) {
  928. return (FALSE) ;
  929. }
  930. if (hInputFile) {
  931. // use the input file handle if it is available
  932. // this is the case for saving workspace data
  933. hFile = hInputFile ;
  934. } else {
  935. if (pReportFullFileName) {
  936. lstrcpy (szFileName, pReportFullFileName) ;
  937. }
  938. if (bGetFileName || pReportFullFileName == NULL) {
  939. if (!FileGetName (hWndReport, IDS_REPORTFILE, szFileName)) {
  940. return (FALSE) ;
  941. }
  942. newFileName = TRUE ;
  943. }
  944. hFile = FileHandleCreate (szFileName) ;
  945. if (hFile && newFileName) {
  946. ChangeSaveFileName (szFileName, IDM_VIEWREPORT) ;
  947. } else if (!hFile) {
  948. DlgErrorBox (hWndReport, ERR_CANT_OPEN, szFileName) ;
  949. }
  950. }
  951. if (!hFile || hFile == INVALID_HANDLE_VALUE)
  952. return (FALSE) ;
  953. if (!hInputFile) {
  954. memset (&FileHeader, 0, sizeof (FileHeader)) ;
  955. lstrcpy (FileHeader.szSignature, szPerfReportSignature) ;
  956. FileHeader.dwMajorVersion = ReportMajorVersion ;
  957. FileHeader.dwMinorVersion = ReportMinorVersion ;
  958. if (!FileWrite (hFile, &FileHeader, sizeof (PERFFILEHEADER))) {
  959. goto Exit0 ;
  960. }
  961. }
  962. DiskReport.Visual = pReport->Visual ;
  963. DiskReport.bManualRefresh = pReport->bManualRefresh ;
  964. DiskReport.dwIntervalSecs = pReport->iIntervalMSecs ;
  965. DiskReport.dwNumLines = NumLines (pReport->pLineFirst) ;
  966. DiskReport.perfmonOptions = Options ;
  967. if (!FileWrite (hFile, &DiskReport, sizeof (DISKREPORT))) {
  968. goto Exit0 ;
  969. }
  970. for (pLine = pReport->pLineFirst ;
  971. pLine ;
  972. pLine = pLine->pLineNext) {
  973. if (!WriteLine (pLine, hFile)) {
  974. goto Exit0 ;
  975. }
  976. }
  977. if (!hInputFile) {
  978. CloseHandle (hFile) ;
  979. }
  980. return (TRUE) ;
  981. Exit0:
  982. if (!hInputFile) {
  983. CloseHandle (hFile) ;
  984. // only need to report error if not workspace
  985. DlgErrorBox (hWndReport, ERR_SETTING_FILE, szFileName) ;
  986. }
  987. return (FALSE) ;
  988. }
  989. void
  990. ReportAddAction (
  991. PREPORT pReport
  992. )
  993. {
  994. HDC hDC ;
  995. //=============================//
  996. // Calculate report positions //
  997. //=============================//
  998. hDC = GetDC (hWndReport) ;
  999. if (hDC) {
  1000. SetReportPositions (hDC, pReport) ;
  1001. ReleaseDC (hWndReport, hDC) ;
  1002. }
  1003. }
  1004. void
  1005. UpdateReportData (
  1006. HWND hWndReport
  1007. )
  1008. {
  1009. PREPORT pReport ;
  1010. pReport = ReportData (hWndReport) ;
  1011. if (PlayingBackLog ()) {
  1012. PlaybackReport (hWndReport) ;
  1013. } else if (pReport->iStatus == iPMStatusClosed) {
  1014. SetReportTimer (pReport) ;
  1015. }
  1016. WindowInvalidate (hWndReport) ;
  1017. }
  1018. BOOL
  1019. OpenReportVer1 (
  1020. HANDLE hFile,
  1021. DISKREPORT *pDiskReport,
  1022. PREPORT pReport,
  1023. DWORD dwMinorVersion
  1024. )
  1025. {
  1026. HDC hDC ;
  1027. pReport->Visual = pDiskReport->Visual ;
  1028. pReport->iIntervalMSecs = pDiskReport->dwIntervalSecs ;
  1029. if (dwMinorVersion < 3) {
  1030. // convert this to msec
  1031. pReport->iIntervalMSecs *= 1000 ;
  1032. }
  1033. pReport->bManualRefresh = pDiskReport->bManualRefresh ;
  1034. bDelayAddAction = TRUE ;
  1035. ReadLines (hFile, pDiskReport->dwNumLines,
  1036. &(pReport->pSystemFirst), &(pReport->pLineFirst), IDM_VIEWREPORT) ;
  1037. if (pReport->pLineFirst) {
  1038. // set focus on the first line
  1039. pReport->CurrentItem.pLine = pReport->pLineFirst ;
  1040. pReport->CurrentItemType = REPORT_TYPE_LINE ;
  1041. }
  1042. bDelayAddAction = FALSE ;
  1043. //=============================//
  1044. // Calculate report positions //
  1045. //=============================//
  1046. hDC = GetDC (hWndReport) ;
  1047. if (hDC) {
  1048. SetReportPositions (hDC, pReport) ;
  1049. ReleaseDC (hWndReport, hDC) ;
  1050. }
  1051. if (PlayingBackLog ()) {
  1052. PlaybackReport (hWndReport) ;
  1053. } else if (pReport->iStatus == iPMStatusClosed) {
  1054. SetReportTimer (pReport) ;
  1055. }
  1056. WindowInvalidate (hWndReport) ;
  1057. return (TRUE) ;
  1058. }
  1059. BOOL
  1060. OpenReport (
  1061. HWND hWndReport,
  1062. HANDLE hFile,
  1063. DWORD dwMajorVersion,
  1064. DWORD dwMinorVersion,
  1065. BOOL bReportFile
  1066. )
  1067. {
  1068. PREPORT pReport ;
  1069. DISKREPORT DiskReport ;
  1070. BOOL bSuccess = TRUE ;
  1071. pReport = ReportData (hWndReport) ;
  1072. if (!pReport) {
  1073. bSuccess = FALSE ;
  1074. goto Exit0 ;
  1075. }
  1076. if (!FileRead (hFile, &DiskReport, sizeof (DISKREPORT))) {
  1077. bSuccess = FALSE ;
  1078. goto Exit0 ;
  1079. }
  1080. switch (dwMajorVersion) {
  1081. case (1):
  1082. SetHourglassCursor() ;
  1083. ResetReportView (hWndReport) ;
  1084. OpenReportVer1 (hFile, &DiskReport, pReport, dwMinorVersion) ;
  1085. // change to report view if we are opening a
  1086. // report file
  1087. if (bReportFile && iPerfmonView != IDM_VIEWREPORT) {
  1088. SendMessage (hWndMain, WM_COMMAND, (LONG)IDM_VIEWREPORT, 0L) ;
  1089. }
  1090. if (iPerfmonView == IDM_VIEWREPORT) {
  1091. SetPerfmonOptions (&DiskReport.perfmonOptions) ;
  1092. }
  1093. SetArrowCursor() ;
  1094. break ;
  1095. }
  1096. Exit0:
  1097. if (bReportFile) {
  1098. CloseHandle (hFile) ;
  1099. }
  1100. return (bSuccess) ;
  1101. }
  1102. void
  1103. ResetReportView (
  1104. HWND hWndReport
  1105. )
  1106. {
  1107. PREPORT pReport ;
  1108. pReport = ReportData (hWndReport) ;
  1109. if (!pReport) {
  1110. return ;
  1111. }
  1112. ChangeSaveFileName (NULL, IDM_VIEWREPORT) ;
  1113. if (pReport->pSystemGroupFirst) {
  1114. ResetReport (hWndReport) ;
  1115. }
  1116. }
  1117. void
  1118. ResetReport (
  1119. HWND hWndReport
  1120. )
  1121. {
  1122. PREPORT pReport ;
  1123. PSYSTEMGROUP pSystemGroup, pSystemGroupDelete ;
  1124. POBJECTGROUP pObjectGroup, pObjectGroupDelete ;
  1125. PCOUNTERGROUP pCounterGroup, pCounterGroupDelete ;
  1126. HDC hDC ;
  1127. pReport = ReportData (hWndReport) ;
  1128. if (!pReport)
  1129. return ;
  1130. ClearReportTimer (pReport) ;
  1131. pSystemGroup = pReport->pSystemGroupFirst ;
  1132. while (pSystemGroup) {
  1133. pObjectGroup = pSystemGroup->pObjectGroupFirst ;
  1134. while (pObjectGroup) {
  1135. pCounterGroup = pObjectGroup->pCounterGroupFirst ;
  1136. while (pCounterGroup) {
  1137. pCounterGroupDelete = pCounterGroup ;
  1138. pCounterGroup = pCounterGroup->pCounterGroupNext ;
  1139. MemoryFree (pCounterGroupDelete) ;
  1140. }
  1141. pObjectGroupDelete = pObjectGroup ;
  1142. pObjectGroup = pObjectGroup->pObjectGroupNext ;
  1143. ColumnGroupRemove (pObjectGroupDelete->pColumnGroupFirst) ;
  1144. MemoryFree (pObjectGroupDelete->lpszObjectName) ;
  1145. MemoryFree (pObjectGroupDelete) ;
  1146. }
  1147. pSystemGroupDelete = pSystemGroup ;
  1148. pSystemGroup = pSystemGroup->pSystemGroupNext ;
  1149. MemoryFree (pSystemGroupDelete->lpszSystemName) ;
  1150. MemoryFree (pSystemGroupDelete) ;
  1151. }
  1152. FreeLines (pReport->pLineFirst) ;
  1153. pReport->pLineFirst = NULL ;
  1154. FreeSystems (pReport->pSystemFirst) ;
  1155. pReport->pSystemFirst = NULL ;
  1156. pReport->pSystemGroupFirst = NULL ;
  1157. pReport->CurrentItemType = REPORT_TYPE_NOTHING ;
  1158. pReport->CurrentItem.pLine = NULL ;
  1159. // reset scrolling ranges
  1160. pReport->xWidth = 0 ;
  1161. pReport->yHeight = 0 ;
  1162. pReport->xMaxCounterWidth = 0 ;
  1163. hDC = GetDC (hWndReport) ;
  1164. if (hDC) {
  1165. SetReportPositions (hDC, pReport) ;
  1166. SelectFont (hDC, pReport->hFont) ;
  1167. pReport->xValueWidth = TextWidth (hDC, szValuePlaceholder) ;
  1168. ReleaseDC (hWndReport, hDC) ;
  1169. }
  1170. WindowInvalidate (hWndReport) ;
  1171. }
  1172. void
  1173. ClearReportDisplay (
  1174. HWND hWndReport
  1175. )
  1176. {
  1177. PREPORT pReport ;
  1178. PLINE pLine;
  1179. if (PlayingBackLog()) {
  1180. return ;
  1181. }
  1182. pReport = ReportData (hWndReport) ;
  1183. if (!pReport || !pReport->pLineFirst)
  1184. return ;
  1185. for (pLine = pReport->pLineFirst ;
  1186. pLine ;
  1187. pLine = pLine->pLineNext) {
  1188. // reset the new data counts
  1189. pLine->bFirstTime = 2 ;
  1190. }
  1191. // re-draw the values
  1192. UpdateReportValues (pReport) ;
  1193. }
  1194. //=========================================
  1195. // we don't print. we just export
  1196. //
  1197. // if need printing, define KEEP_PRINT
  1198. //=========================================
  1199. #ifdef KEEP_PRINT
  1200. BOOL
  1201. PrintReportDisplay (
  1202. HDC hDC,
  1203. PREPORT pReport
  1204. )
  1205. {
  1206. SetReportPositions (hDC, pReport) ;
  1207. DrawReport (hDC, pReport) ;
  1208. return TRUE ;
  1209. }
  1210. BOOL
  1211. PrintReport (
  1212. HWND hWndParent,
  1213. HWND hWndReport
  1214. )
  1215. {
  1216. PREPORT pReport ;
  1217. HDC hDC ;
  1218. int xPageWidth ;
  1219. int yPageHeight ;
  1220. int xValueWidth ;
  1221. HFONT hFont, hFontHeaders ;
  1222. int yLineHeight ;
  1223. pReport = ReportData (hWndReport) ;
  1224. if (!pReport)
  1225. return (FALSE) ;
  1226. hDC = PrintDC () ;
  1227. if (!hDC) {
  1228. PostError () ;
  1229. return (FALSE) ;
  1230. }
  1231. xPageWidth = GetDeviceCaps (hDC, HORZRES) ;
  1232. yPageHeight = GetDeviceCaps (hDC, VERTRES) ;
  1233. StartJob (hDC, TEXT("Performance Monitor Report")) ;
  1234. StartPage (hDC) ;
  1235. hFont = pReport->hFont ;
  1236. hFontHeaders = pReport->hFontHeaders ;
  1237. yLineHeight = pReport->yLineHeight ;
  1238. xValueWidth = pReport->xValueWidth ;
  1239. pReport->hFont = hFontPrinterScales ;
  1240. pReport->hFontHeaders = hFontPrinterScalesBold ;
  1241. SelectFont (hDC, pReport->hFont) ;
  1242. pReport->yLineHeight = FontHeight (hDC, TRUE) ;
  1243. pReport->xValueWidth = TextWidth (hDC, szValuePlaceholder) ;
  1244. PrintReportDisplay (hDC, pReport) ;
  1245. EndPage (hDC) ;
  1246. EndJob (hDC) ;
  1247. DeleteDC (hDC) ;
  1248. pReport->hFont = hFont ;
  1249. pReport->hFontHeaders = hFontHeaders ;
  1250. pReport->yLineHeight = yLineHeight ;
  1251. pReport->xValueWidth = xValueWidth ;
  1252. hDC = GetDC (hWndReport) ;
  1253. SetReportPositions (hDC, pReport) ;
  1254. ReleaseDC (hWndReport, hDC) ;
  1255. return (FALSE) ;
  1256. }
  1257. // we don't print. we just export
  1258. #endif
  1259. #if 0
  1260. /*
  1261. NOTE:
  1262. this function was attempted as a replacement for the
  1263. FindEquivalentLine function used to locate matching
  1264. report entries. It "Almost" works, but because of how
  1265. the new entries (lines) are added to the list. Since new
  1266. columns aren't added in a timely fashion for this test
  1267. to work, the list of counters still must be searched
  1268. sequentially. To make this indexed search work for "bulk"
  1269. additions, the column updating/addtion must take place
  1270. more "synchronously" with the counter addition.
  1271. -- bobw 2-Jan-97
  1272. */
  1273. PLINE
  1274. FindEquivalentReportLine (
  1275. PLINE pLineToFind,
  1276. PREPORT pReport
  1277. )
  1278. {
  1279. PLINE pLine = NULL;
  1280. PLINE pLastEquivLine = NULL;
  1281. BOOL bNotUsed;
  1282. PSYSTEMGROUP pSystemGroup = NULL;
  1283. POBJECTGROUP pObjectGroup = NULL;
  1284. PCOUNTERGROUP pCounterGroup = NULL;
  1285. PCOLUMNGROUP pColumnGroup = NULL;
  1286. PCOLUMNGROUP pMatchingColumn = NULL;
  1287. int dwColumn;
  1288. // since the report data is organized hierarchically, we'll search
  1289. // that way instead of just looking at each lin
  1290. pSystemGroup = GetSystemGroup (pReport, pLineToFind->lnSystemName);
  1291. if (pSystemGroup != NULL) {
  1292. // found the system that this line belongs to so look up the
  1293. // object
  1294. pObjectGroup = GetObjectGroup (pSystemGroup, pLineToFind->lnObjectName) ;
  1295. if (pObjectGroup != NULL) {
  1296. // find matching instance column
  1297. for (pColumnGroup = pObjectGroup->pColumnGroupFirst;
  1298. pColumnGroup;
  1299. pColumnGroup = pColumnGroup->pColumnGroupNext) {
  1300. if (pstrsame (pLineToFind->lnInstanceName, pColumnGroup->lpszInstanceName) &&
  1301. pstrsame (pLineToFind->lnPINName, pColumnGroup->lpszParentName)) {
  1302. // this column has the same name as the one we're
  1303. // looking for so find the highest matching index value
  1304. if (pMatchingColumn == NULL) {
  1305. pMatchingColumn = pColumnGroup;
  1306. } else {
  1307. if (pColumnGroup->dwInstanceIndex > pMatchingColumn->dwInstanceIndex) {
  1308. pMatchingColumn = pColumnGroup;
  1309. }
  1310. }
  1311. }
  1312. }
  1313. if (pMatchingColumn == NULL) {
  1314. dwColumn = 0;
  1315. } else {
  1316. dwColumn = (int)pMatchingColumn->ColumnNumber;
  1317. }
  1318. // then try to find the matching counter in this column
  1319. pCounterGroup = GetCounterGroup (pObjectGroup,
  1320. pLineToFind->lnCounterDef.CounterNameTitleIndex,
  1321. &bNotUsed,
  1322. pLineToFind->lnCounterName,
  1323. FALSE);
  1324. if (pCounterGroup != NULL) {
  1325. // search the instances of this counter group for a match
  1326. for (pLine = pCounterGroup->pLineFirst ;
  1327. pLine ;
  1328. pLine = pLine->pLineNext) {
  1329. if (pLine->iReportColumn == dwColumn) {
  1330. // match counter names to confir
  1331. if (pstrsame(pLine->lnCounterName,
  1332. pLineToFind->lnCounterName)) {
  1333. pLastEquivLine = pLine;
  1334. break;
  1335. }
  1336. }
  1337. }
  1338. }
  1339. }
  1340. }
  1341. return (pLastEquivLine) ;
  1342. }
  1343. #endif
  1344. BOOL
  1345. ReportInsertLine (
  1346. HWND hWnd,
  1347. PLINE pLine
  1348. )
  1349. /*
  1350. Effect: Insert the line pLine into the data structures for the
  1351. Report of window hWnd. The line is added to the list of
  1352. lines, and also added to the report structure in the
  1353. appropriate System, Object, and Counter.
  1354. Returns: Whether the function was successful. If this function
  1355. returns FALSE, the line was not added.
  1356. */
  1357. {
  1358. HDC hDC ;
  1359. PREPORT pReport ;
  1360. PSYSTEMGROUP pSystemGroup ;
  1361. POBJECTGROUP pObjectGroup ;
  1362. PCOUNTERGROUP pCounterGroup ;
  1363. PLINE pLineEquivalent ;
  1364. int OldCounterWidth ;
  1365. BOOL bNewCounterGroup ;
  1366. pReport = ReportData (hWnd) ;
  1367. pReport->bModified = TRUE ;
  1368. pLineEquivalent = FindEquivalentLine (pLine, pReport->pLineFirst);
  1369. if (pLineEquivalent) {
  1370. if (bMonitorDuplicateInstances) {
  1371. pLine->dwInstanceIndex = pLineEquivalent->dwInstanceIndex + 1;
  1372. } else {
  1373. return (FALSE) ;
  1374. }
  1375. }
  1376. //=============================//
  1377. // Add line, line's system //
  1378. //=============================//
  1379. ReportLineAppend (pReport, pLine) ;
  1380. //=============================//
  1381. // Find correct spot; add line //
  1382. //=============================//
  1383. pSystemGroup = GetSystemGroup (pReport, pLine->lnSystemName) ;
  1384. pObjectGroup = GetObjectGroup (pSystemGroup, pLine->lnObjectName) ;
  1385. pCounterGroup = GetCounterGroup (pObjectGroup,
  1386. pLine->lnCounterDef.CounterNameTitleIndex,
  1387. &bNewCounterGroup,
  1388. pLine->lnCounterName,
  1389. TRUE);
  1390. if (!pCounterGroup)
  1391. return (FALSE) ;
  1392. LineCounterAppend (pCounterGroup, pLine) ;
  1393. //=============================//
  1394. // Calculate report positions //
  1395. //=============================//
  1396. hDC = GetDC (hWnd) ;
  1397. SelectFont (hDC, pReport->hFontHeaders) ;
  1398. if (bNewCounterGroup) {
  1399. // re-calc. the max. counter group width
  1400. OldCounterWidth = pReport->xMaxCounterWidth ;
  1401. pReport->xMaxCounterWidth =
  1402. max (pReport->xMaxCounterWidth,
  1403. TextWidth (hDC, pLine->lnCounterName)) ;
  1404. if (OldCounterWidth < pReport->xMaxCounterWidth) {
  1405. // adjust the report width with the new counter width
  1406. pReport->xWidth +=
  1407. (pReport->xMaxCounterWidth - OldCounterWidth);
  1408. }
  1409. }
  1410. if (pLine->lnCounterType == PERF_COUNTER_LARGE_RAWCOUNT_HEX) {
  1411. SelectFont (hDC, pReport->hFont) ;
  1412. pReport->xValueWidth = TextWidth (hDC, szValueLargeHexPlaceholder) ;
  1413. }
  1414. if (!bDelayAddAction) {
  1415. SetReportPositions (hDC, pReport) ;
  1416. }
  1417. ReleaseDC (hWnd, hDC) ;
  1418. pReport->CurrentItem.pLine = pLine ;
  1419. pReport->CurrentItemType = REPORT_TYPE_LINE ;
  1420. if (!bDelayAddAction) {
  1421. if (PlayingBackLog ()) {
  1422. PlaybackReport (hWndReport) ;
  1423. } else if (pReport->iStatus == iPMStatusClosed) {
  1424. SetReportTimer (pReport) ;
  1425. }
  1426. WindowInvalidate (hWnd) ;
  1427. }
  1428. return (TRUE) ;
  1429. }
  1430. BOOL
  1431. ExportComputerName (
  1432. HANDLE hFile,
  1433. PSYSTEMGROUP pSystemGroup
  1434. )
  1435. {
  1436. int StringLen ;
  1437. BOOL bWriteSuccess = TRUE ;
  1438. CHAR TempBuff [LongTextLen] ;
  1439. TCHAR UnicodeBuff [LongTextLen] ;
  1440. // export computer name
  1441. strcpy (TempBuff, LineEndStr) ;
  1442. strcat (TempBuff, LineEndStr) ;
  1443. StringLen = strlen (TempBuff) ;
  1444. TSPRINTF (UnicodeBuff, szSystemFormat, pSystemGroup->lpszSystemName) ;
  1445. ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
  1446. strcat (TempBuff, LineEndStr) ;
  1447. if (!FileWrite (hFile, TempBuff, strlen(TempBuff))) {
  1448. bWriteSuccess = FALSE ;
  1449. }
  1450. return (bWriteSuccess) ;
  1451. }
  1452. #define WRITE_FILE_TIME 2
  1453. BOOL
  1454. ExportObjectName (
  1455. HANDLE hFile,
  1456. POBJECTGROUP pObjectGroup,
  1457. int *pColNum
  1458. )
  1459. {
  1460. int StringLen ;
  1461. BOOL bNeedToExport ;
  1462. BOOL bWriteSuccess = TRUE ;
  1463. PCOLUMNGROUP pColumnGroup ;
  1464. int ParentNum, InstanceNum ;
  1465. int TimeToWrite ;
  1466. CHAR TempBuff [512] ;
  1467. TCHAR UnicodeBuff [512] ;
  1468. ParentNum = InstanceNum = 0 ;
  1469. if (pColNum) {
  1470. *pColNum = 0 ;
  1471. }
  1472. // export object name
  1473. strcpy (TempBuff, LineEndStr) ;
  1474. StringLen = strlen (TempBuff) ;
  1475. TSPRINTF (UnicodeBuff, szObjectFormat, pObjectGroup->lpszObjectName) ;
  1476. ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
  1477. strcat (TempBuff, LineEndStr) ;
  1478. if (!FileWrite (hFile, TempBuff, strlen(TempBuff))) {
  1479. goto Exit0 ;
  1480. }
  1481. TimeToWrite = 0 ;
  1482. // export column group
  1483. if (pObjectGroup->pColumnGroupFirst) {
  1484. strcpy (TempBuff, pDelimiter) ;
  1485. strcat (TempBuff, pDelimiter) ;
  1486. StringLen = strlen (TempBuff) ;
  1487. bNeedToExport = FALSE ;
  1488. // export Parent Names
  1489. for (pColumnGroup = pObjectGroup->pColumnGroupFirst ;
  1490. pColumnGroup ;
  1491. pColumnGroup = pColumnGroup->pColumnGroupNext) {
  1492. if (pColumnGroup->lpszParentName) {
  1493. ParentNum++ ;
  1494. bNeedToExport = TRUE ;
  1495. ConvertUnicodeStr (&TempBuff[StringLen],
  1496. pColumnGroup->lpszParentName) ;
  1497. StringLen = strlen (TempBuff) ;
  1498. }
  1499. strcat (&TempBuff[StringLen], pDelimiter) ;
  1500. StringLen = strlen (TempBuff) ;
  1501. // check if we need to export this line before it is filled up
  1502. TimeToWrite++ ;
  1503. if (TimeToWrite > WRITE_FILE_TIME) {
  1504. if (!FileWrite (hFile, TempBuff, strlen(TempBuff))) {
  1505. goto Exit0 ;
  1506. }
  1507. TimeToWrite = 0 ;
  1508. StringLen = 0 ;
  1509. TempBuff[0] = TEXT('\0') ;
  1510. }
  1511. }
  1512. // write the line delimiter
  1513. strcpy (&TempBuff[StringLen], LineEndStr) ;
  1514. if (!FileWrite (hFile, TempBuff, strlen(TempBuff))) {
  1515. goto Exit0 ;
  1516. }
  1517. if (!bNeedToExport) {
  1518. ParentNum = 0 ;
  1519. }
  1520. // setup to export Instances
  1521. strcpy (TempBuff, pDelimiter) ;
  1522. strcat (TempBuff, pDelimiter) ;
  1523. StringLen = strlen (TempBuff) ;
  1524. bNeedToExport = FALSE ;
  1525. TimeToWrite = 0 ;
  1526. // export Instance Names
  1527. for (pColumnGroup = pObjectGroup->pColumnGroupFirst ;
  1528. pColumnGroup ;
  1529. pColumnGroup = pColumnGroup->pColumnGroupNext) {
  1530. if (pColumnGroup->lpszInstanceName) {
  1531. InstanceNum++ ;
  1532. bNeedToExport = TRUE ;
  1533. ConvertUnicodeStr (&TempBuff[StringLen],
  1534. pColumnGroup->lpszInstanceName) ;
  1535. StringLen = strlen (TempBuff) ;
  1536. }
  1537. strcat (&TempBuff[StringLen], pDelimiter) ;
  1538. StringLen = strlen (TempBuff) ;
  1539. // check if we need to export this line before it is filled up
  1540. TimeToWrite++ ;
  1541. if (TimeToWrite > WRITE_FILE_TIME) {
  1542. if (!FileWrite (hFile, TempBuff, strlen(TempBuff))) {
  1543. goto Exit0 ;
  1544. }
  1545. TimeToWrite = 0 ;
  1546. StringLen = 0 ;
  1547. TempBuff[0] = TEXT('\0') ;
  1548. }
  1549. }
  1550. // write the line delimiter
  1551. strcpy (&TempBuff[StringLen], LineEndStr) ;
  1552. if (!FileWrite (hFile, TempBuff, strlen(TempBuff))) {
  1553. goto Exit0 ;
  1554. }
  1555. if (!bNeedToExport) {
  1556. InstanceNum = 0 ;
  1557. }
  1558. }
  1559. if (pColNum) {
  1560. *pColNum = max (ParentNum, InstanceNum) ;
  1561. }
  1562. return (TRUE) ;
  1563. Exit0:
  1564. return (FALSE) ;
  1565. }
  1566. BOOL
  1567. ExportLineName (
  1568. HANDLE hFile,
  1569. PLINE pLine,
  1570. int *pExportCounterName
  1571. )
  1572. {
  1573. FLOAT eValue ;
  1574. int StringLen ;
  1575. BOOL bWriteSuccess = TRUE ;
  1576. CHAR TempBuff [LongTextLen] ;
  1577. TCHAR UnicodeBuff [LongTextLen] ;
  1578. strcpy (TempBuff, pDelimiter) ;
  1579. if (*pExportCounterName) {
  1580. StringLen = strlen (TempBuff) ;
  1581. ConvertUnicodeStr (&TempBuff[StringLen], pLine->lnCounterName) ;
  1582. strcat (TempBuff, pDelimiter) ;
  1583. *pExportCounterName = FALSE ;
  1584. }
  1585. StringLen = strlen (TempBuff) ;
  1586. if (pLine->bFirstTime == 0) {
  1587. eValue = CounterEntry (pLine) ;
  1588. if (pLine->lnCounterType == PERF_COUNTER_RAWCOUNT_HEX ||
  1589. pLine->lnCounterType == PERF_COUNTER_LARGE_RAWCOUNT_HEX) {
  1590. if (pLine->lnCounterType == PERF_COUNTER_RAWCOUNT_HEX ||
  1591. pLine->lnaCounterValue[0].HighPart == 0) {
  1592. TSPRINTF (UnicodeBuff,
  1593. szHexFormat,
  1594. pLine->lnaCounterValue[0].LowPart) ;
  1595. } else {
  1596. TSPRINTF (UnicodeBuff,
  1597. szLargeHexFormat,
  1598. pLine->lnaCounterValue[0].HighPart,
  1599. pLine->lnaCounterValue[0].LowPart) ;
  1600. }
  1601. } else {
  1602. TSPRINTF (UnicodeBuff,
  1603. (eValue > eStatusLargeValueMax) ?
  1604. szLargeValueFormat : szValueFormat,
  1605. eValue) ;
  1606. ConvertDecimalPoint (UnicodeBuff) ;
  1607. }
  1608. ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
  1609. } else {
  1610. // export "----" for unstable values
  1611. strcat (&TempBuff[StringLen], "----");
  1612. }
  1613. // write the line value
  1614. if (!FileWrite (hFile, TempBuff, strlen(TempBuff))) {
  1615. goto Exit0 ;
  1616. }
  1617. return (TRUE) ;
  1618. Exit0:
  1619. return (FALSE) ;
  1620. }
  1621. // This routine is need to insert the line values into its
  1622. // column location. It is needed because not all the instances (columns)
  1623. // are available for the same line.
  1624. void
  1625. SaveColumnLineData (
  1626. PLINE pLine,
  1627. LPSTR pColumnLineData
  1628. )
  1629. {
  1630. FLOAT eValue ;
  1631. LPSTR pColumnLine ;
  1632. CHAR TempBuff [LongTextLen] ;
  1633. TCHAR UnicodeBuff [LongTextLen] ;
  1634. if (!pColumnLineData || pLine->iReportColumn < 0) {
  1635. return ;
  1636. }
  1637. // find the offset into the pColumnLineData buffer for current line
  1638. pColumnLine = pColumnLineData + pLine->iReportColumn * ShortTextLen ;
  1639. if (pLine->bFirstTime == 0) {
  1640. eValue = CounterEntry (pLine) ;
  1641. if (pLine->lnCounterType == PERF_COUNTER_RAWCOUNT_HEX ||
  1642. pLine->lnCounterType == PERF_COUNTER_LARGE_RAWCOUNT_HEX) {
  1643. if (pLine->lnCounterType == PERF_COUNTER_RAWCOUNT_HEX ||
  1644. pLine->lnaCounterValue[0].HighPart == 0) {
  1645. TSPRINTF (UnicodeBuff,
  1646. szHexFormat,
  1647. pLine->lnaCounterValue[0].LowPart) ;
  1648. } else {
  1649. TSPRINTF (UnicodeBuff,
  1650. szLargeHexFormat,
  1651. pLine->lnaCounterValue[0].HighPart,
  1652. pLine->lnaCounterValue[0].LowPart) ;
  1653. }
  1654. } else {
  1655. TSPRINTF (UnicodeBuff,
  1656. (eValue > eStatusLargeValueMax) ?
  1657. szLargeValueFormat : szValueFormat,
  1658. eValue) ;
  1659. ConvertDecimalPoint (UnicodeBuff) ;
  1660. }
  1661. ConvertUnicodeStr (TempBuff, UnicodeBuff) ;
  1662. strncpy (pColumnLine, TempBuff, ShortTextLen) ;
  1663. *(pColumnLine + ShortTextLen - 1) = '\0' ;
  1664. } else {
  1665. // export "----" for unstable values
  1666. strcpy (pColumnLine, "----");
  1667. }
  1668. }
  1669. BOOL
  1670. ExportColumnLineData (
  1671. HANDLE hFile,
  1672. int ColumnTotal,
  1673. PCOUNTERGROUP pCounterGroup,
  1674. LPSTR pColumnLineData
  1675. )
  1676. {
  1677. int iIndex ;
  1678. int StringLen ;
  1679. CHAR TempBuff [LongTextLen] ;
  1680. LPSTR pCurrentLineData ;
  1681. // export the counter name
  1682. strcpy (TempBuff, pDelimiter) ;
  1683. StringLen = strlen (TempBuff) ;
  1684. ConvertUnicodeStr (&TempBuff[StringLen], pCounterGroup->pLineFirst->lnCounterName) ;
  1685. strcat (TempBuff, pDelimiter) ;
  1686. if (!FileWrite (hFile, TempBuff, strlen(TempBuff))) {
  1687. goto Exit0 ;
  1688. }
  1689. // go thru each column and export the line value if it has been stored
  1690. for (iIndex = 0, pCurrentLineData = pColumnLineData ;
  1691. iIndex < ColumnTotal ;
  1692. iIndex++, pCurrentLineData += ShortTextLen ) {
  1693. if (*pCurrentLineData != 0) {
  1694. // data available for this column
  1695. if (!FileWrite (hFile, pCurrentLineData, strlen(pCurrentLineData))) {
  1696. goto Exit0 ;
  1697. }
  1698. }
  1699. if (!FileWrite (hFile, pDelimiter, strlen(pDelimiter))) {
  1700. goto Exit0 ;
  1701. }
  1702. }
  1703. if (!FileWrite (hFile, LineEndStr, strlen(LineEndStr))) {
  1704. goto Exit0 ;
  1705. }
  1706. return (TRUE) ;
  1707. Exit0:
  1708. return (FALSE) ;
  1709. }
  1710. void
  1711. ExportReport (void)
  1712. {
  1713. HANDLE hFile = 0 ;
  1714. PREPORT pReport ;
  1715. PSYSTEMGROUP pSystemGroup ;
  1716. POBJECTGROUP pObjectGroup ;
  1717. PCOUNTERGROUP pCounterGroup ;
  1718. PLINE pLine ;
  1719. BOOL bExportComputer ;
  1720. BOOL bExportObject ;
  1721. BOOL bExportCounterName ;
  1722. int ColumnTotal = 0 ;
  1723. LPSTR pColumnLineData = NULL ;
  1724. LPTSTR pFileName = NULL ;
  1725. INT ErrCode = 0 ;
  1726. if (!(pReport = ReportData (hWndReport))) {
  1727. return ;
  1728. }
  1729. // see if there is anything to export..
  1730. if (!(pReport->pSystemGroupFirst)) {
  1731. return ;
  1732. }
  1733. SetHourglassCursor() ;
  1734. if (ErrCode = ExportFileOpen (hWndReport, &hFile,
  1735. pReport->iIntervalMSecs, &pFileName)) {
  1736. goto Exit0 ;
  1737. }
  1738. if (!pFileName) {
  1739. // the case when user cancel
  1740. goto Exit0 ;
  1741. }
  1742. // export each system group
  1743. for (pSystemGroup = pReport->pSystemGroupFirst ;
  1744. pSystemGroup ;
  1745. pSystemGroup = pSystemGroup->pSystemGroupNext) {
  1746. bExportComputer = TRUE ;
  1747. for (pObjectGroup = pSystemGroup->pObjectGroupFirst ;
  1748. pObjectGroup ;
  1749. pObjectGroup = pObjectGroup->pObjectGroupNext) {
  1750. bExportObject = TRUE ;
  1751. for (pCounterGroup = pObjectGroup->pCounterGroupFirst ;
  1752. pCounterGroup ;
  1753. pCounterGroup = pCounterGroup->pCounterGroupNext) {
  1754. bExportCounterName = TRUE ;
  1755. // Column data buffer has been allocated for this object type,
  1756. // zero out the buffer and prepare for next round.
  1757. if (pColumnLineData) {
  1758. memset (pColumnLineData, 0, ColumnTotal * ShortTextLen) ;
  1759. }
  1760. for (pLine = pCounterGroup->pLineFirst ;
  1761. pLine ;
  1762. pLine = pLine->pLineCounterNext) {
  1763. if (bExportComputer) {
  1764. // only need to do this for the first object
  1765. bExportComputer = FALSE ;
  1766. if (!ExportComputerName (hFile, pSystemGroup)) {
  1767. ErrCode = ERR_EXPORT_FILE ;
  1768. goto Exit0 ;
  1769. }
  1770. }
  1771. if (bExportObject) {
  1772. // only need to do this for the first counter group
  1773. bExportObject = FALSE ;
  1774. if (!ExportObjectName (hFile, pObjectGroup, &ColumnTotal)) {
  1775. ErrCode = ERR_EXPORT_FILE ;
  1776. goto Exit0 ;
  1777. }
  1778. if (ColumnTotal > 1) {
  1779. // special case to setup a column array and export
  1780. // the line values later
  1781. pColumnLineData = MemoryAllocate (ColumnTotal * ShortTextLen) ;
  1782. if (!pColumnLineData) {
  1783. ErrCode = ERR_EXPORT_FILE ;
  1784. goto Exit0 ;
  1785. }
  1786. }
  1787. }
  1788. if (ColumnTotal > 1) {
  1789. // save the line value into its column & export later
  1790. SaveColumnLineData (pLine, pColumnLineData) ;
  1791. } else {
  1792. // simple case, export the line now
  1793. if (!ExportLineName (hFile, pLine, &bExportCounterName)) {
  1794. ErrCode = ERR_EXPORT_FILE ;
  1795. goto Exit0 ;
  1796. }
  1797. }
  1798. }
  1799. if (!bExportCounterName) {
  1800. // export the line end
  1801. if (!FileWrite (hFile, LineEndStr, strlen(LineEndStr))) {
  1802. ErrCode = ERR_EXPORT_FILE ;
  1803. goto Exit0 ;
  1804. }
  1805. }
  1806. if (pColumnLineData) {
  1807. // now, do the actual export
  1808. if (!ExportColumnLineData (hFile,
  1809. ColumnTotal,
  1810. pCounterGroup,
  1811. pColumnLineData)) {
  1812. ErrCode = ERR_EXPORT_FILE ;
  1813. goto Exit0 ;
  1814. }
  1815. }
  1816. }
  1817. // done with the object, done with the buffer
  1818. if (pColumnLineData) {
  1819. MemoryFree (pColumnLineData) ;
  1820. ColumnTotal = 0 ;
  1821. pColumnLineData = NULL ;
  1822. }
  1823. }
  1824. }
  1825. Exit0:
  1826. SetArrowCursor() ;
  1827. if (pColumnLineData) {
  1828. MemoryFree (pColumnLineData) ;
  1829. }
  1830. if (hFile) {
  1831. CloseHandle (hFile) ;
  1832. }
  1833. if (pFileName) {
  1834. if (ErrCode) {
  1835. DlgErrorBox (hWndGraph, ErrCode, pFileName) ;
  1836. }
  1837. MemoryFree (pFileName) ;
  1838. }
  1839. }