|
|
1.1 ! root 1: /***************************************************************************** ! 2: * ! 3: * Log.c - This module handles the Logging. ! 4: * ! 5: * Microsoft Confidential ! 6: * Copyright (c) 1992-1993 Microsoft Corporation ! 7: * ! 8: * ! 9: ****************************************************************************/ ! 10: ! 11: ! 12: //==========================================================================// ! 13: // Includes // ! 14: //==========================================================================// ! 15: ! 16: #include <stdio.h> ! 17: ! 18: #include "perfmon.h" ! 19: #include "log.h" ! 20: ! 21: #include "fileutil.h" ! 22: #include "owndraw.h" ! 23: #include "pmemory.h" // for MemoryXXX (mallloc-type) routines ! 24: #include "perfmops.h" // for SystemAdd ! 25: #include "perfdata.h" ! 26: #include "playback.h" // for PlayingBackLog ! 27: #include "status.h" // for StatusUpdateIcons ! 28: #include "system.h" // for SystemAdd ! 29: #include "utils.h" ! 30: #include "fileopen.h" // for FileGetName ! 31: #include "command.h" ! 32: ! 33: extern TCHAR LOCAL_SYS_CODE_NAME[] ; ! 34: ! 35: //==========================================================================// ! 36: // Funtion Prototypes // ! 37: //==========================================================================// ! 38: ! 39: ! 40: BOOL LogWriteStartBookmark (HWND hWnd, SYSTEMTIME *pSystemTime) ; ! 41: BOOL LogWriteBookmarkData (HWND hWnd, PBOOKMARK pBookMark) ; ! 42: ! 43: ! 44: //==========================================================================// ! 45: // Constants // ! 46: //==========================================================================// ! 47: ! 48: ! 49: ! 50: #define LogNameMinLen 15 ! 51: #define LogObjectMinLen 20 ! 52: ! 53: // This is set to 1 min ! 54: #define LARGE_INTERVAL 60 ! 55: ! 56: //=============================// ! 57: // Log Class // ! 58: //=============================// ! 59: ! 60: ! 61: #define dwLogClassStyle (CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS) ! 62: #define iLogClassExtra (0) ! 63: #define iLogWindowExtra (0) ! 64: #define dwLogWindowStyle (WS_CHILD) ! 65: ! 66: ! 67: //==========================================================================// ! 68: // Local Data // ! 69: //==========================================================================// ! 70: ! 71: ! 72: ! 73: int xStatusWidth ; ! 74: int xNameMinWidth ; ! 75: ! 76: TCHAR szClosed [ShortTextLen] ; ! 77: TCHAR szCollecting [ShortTextLen] ; ! 78: // TCHAR szPaused [ControlStringLen + 1] ; ! 79: ! 80: ! 81: HWND hWndLogEntries ; ! 82: ! 83: LOGINDEXBLOCK *pLogIndexBlock ; ! 84: ! 85: ! 86: //==========================================================================// ! 87: // Macros // ! 88: //==========================================================================// ! 89: ! 90: ! 91: #define LogEntryN(hWndLogEntries, iIndex) \ ! 92: ((PLOGENTRY) LBData (hWndLogEntries, iIndex)) ! 93: ! 94: ! 95: //==========================================================================// ! 96: // Local Functions // ! 97: //==========================================================================// ! 98: ! 99: void LogAddEntryToList (PLOGENTRY *ppLogEntryFirst, PLOGENTRY pLogNewEntry) ! 100: { ! 101: // insert the new entry at the beginning ! 102: pLogNewEntry->pNextLogEntry = *ppLogEntryFirst ; ! 103: *ppLogEntryFirst = pLogNewEntry ; ! 104: } ! 105: ! 106: void LogDeleteEntryFromList (PLOGENTRY *ppLogEntryFirst, PLOGENTRY pLogEntryDel) ! 107: { ! 108: PLOGENTRY pLogEntry ; ! 109: ! 110: if (*ppLogEntryFirst == pLogEntryDel) ! 111: { ! 112: *ppLogEntryFirst = pLogEntryDel->pNextLogEntry ; ! 113: } ! 114: else ! 115: { ! 116: for (pLogEntry = *ppLogEntryFirst ; ! 117: pLogEntry ; ! 118: pLogEntry = pLogEntry->pNextLogEntry) ! 119: { ! 120: if (pLogEntry->pNextLogEntry == pLogEntryDel) ! 121: { ! 122: // found, remove this entry from the list ! 123: pLogEntry->pNextLogEntry = ! 124: pLogEntryDel->pNextLogEntry ; ! 125: break ; ! 126: } ! 127: } ! 128: } ! 129: } ! 130: ! 131: ! 132: // LogDeleteIndex - delete the log entry specified by iIndex ! 133: // and do memory clean-up ! 134: void static LogDeleteIndex (HWND hWndLogEntries, int iIndex) ! 135: { ! 136: PLOGENTRY pLogEntry ; ! 137: PLOG pLog ; ! 138: ! 139: pLogEntry = (PLOGENTRY) LBData(hWndLogEntries, iIndex) ; ! 140: ! 141: ! 142: if (pLogEntry && pLogEntry != (PLOGENTRY)LB_ERR) ! 143: { ! 144: pLog = LogData (hWndLog) ; ! 145: ! 146: if (pLog->pLogEntryFirst) ! 147: { ! 148: LogDeleteEntryFromList (&(pLog->pLogEntryFirst), pLogEntry) ; ! 149: } ! 150: ! 151: MemoryFree (pLogEntry) ; ! 152: } ! 153: ! 154: LBDelete (hWndLogEntries, iIndex) ; ! 155: } ! 156: ! 157: ! 158: void LogEntriesChanged (HWND hWndLogEntries) ! 159: /* ! 160: Effect: Perform any actions needed when an entry has been added or ! 161: removed from the log. In particular, determine if a new ! 162: "Object" column width is appropriate. If it is, then ! 163: change the width and redraw the log entries list. ! 164: */ ! 165: { // LogEntriesChanged ! 166: int iIndex ; ! 167: int iIndexNum ; ! 168: int xCol1Width ; ! 169: HDC hDC ; ! 170: PLOG pLog ; ! 171: PLOGENTRY pLogEntry ; ! 172: PPERFSYSTEM pSystem; ! 173: ! 174: pLog = LogData (hWndLog) ; ! 175: xCol1Width = 0 ; ! 176: ! 177: hDC = GetDC (hWndLog) ; ! 178: iIndexNum = LBNumItems (hWndLogEntries) ; ! 179: ! 180: // clear value Strings for all systems ! 181: ! 182: for (pSystem = pLog->pSystemFirst; ! 183: pSystem; ! 184: pSystem = pSystem->pSystemNext) { ! 185: if (pSystem) { ! 186: RemoveObjectsFromSystem (pSystem); ! 187: } ! 188: } ! 189: ! 190: for (iIndex = 0 ; ! 191: iIndex < iIndexNum ; ! 192: iIndex++) ! 193: { // for all items in the list ! 194: pLogEntry = LogEntryN (hWndLogEntries, iIndex) ; ! 195: xCol1Width = max (TextWidth (hDC, pLogEntry->szObject), ! 196: xCol1Width) ; ! 197: ! 198: pSystem = SystemGet (pLog->pSystemFirst, pLogEntry->szComputer); ! 199: if (pSystem) { ! 200: AppendObjectToValueList ( ! 201: pLogEntry->ObjectTitleIndex, ! 202: pSystem->lpszValue); ! 203: } ! 204: ! 205: } // for ! 206: ! 207: xCol1Width += 2 * xScrollWidth ; ! 208: xCol1Width = max (xCol1Width, ! 209: TextAvgWidth (hDC, LogObjectMinLen)) ; ! 210: if (xCol1Width != pLog->xCol1Width) ! 211: { ! 212: pLog->xCol1Width = xCol1Width ; ! 213: WindowInvalidate (hWndLogEntries) ; ! 214: } ! 215: ReleaseDC (hWndLog, hDC) ; ! 216: } // LogEntriesChanged ! 217: ! 218: ! 219: LPTSTR StatusText (int iPMStatus) ! 220: /* ! 221: Effect: Return a string representation of the log status ! 222: iPMStatus. ! 223: ! 224: Note: Since these are globals, we can just return a pointer ! 225: to them. The user of this routine should not free ! 226: these pointers or modify the string. ! 227: */ ! 228: { ! 229: switch (iPMStatus) ! 230: { // switch ! 231: case iPMStatusClosed: ! 232: return (szClosed) ; ! 233: ! 234: case iPMStatusCollecting: ! 235: return (szCollecting) ; ! 236: ! 237: // case iPMStatusPaused: ! 238: // return (szPaused) ; ! 239: ! 240: default: ! 241: return (szClosed) ; ! 242: } // switch ! 243: } // StatusText ! 244: ! 245: ! 246: PLOG AllocateLogData (HWND hWndLog) ! 247: { ! 248: PLOG pLog ; ! 249: ! 250: pLog = LogData (hWndLog) ; ! 251: ! 252: pLog->iStatus = iPMStatusClosed ; ! 253: pLog->bManualRefresh = FALSE ; ! 254: ! 255: // let's not give it a filename ! 256: ! 257: /*!! ! 258: FileCombine (pLog->szFilePath, ! 259: szDefaultLogDirectory, szDefaultLogFileName) ; ! 260: !!*/ ! 261: strclr (pLog->szFilePath) ; ! 262: ! 263: pLog->pSystemFirst = NULL; ! 264: pLog->lFileSize = 0L ; ! 265: pLog->iIntervalMSecs = iDefaultLogIntervalSecs * 1000 ; ! 266: ! 267: pLog->pPerfData = (PPERFDATA) MemoryAllocate (STARTING_SYSINFO_SIZE) ; ! 268: pLog->pLogData = (PPERFDATA) MemoryAllocate (STARTING_SYSINFO_SIZE) ; ! 269: pLog->dwDetailLevel = PERF_DETAIL_WIZARD ; ! 270: LogEntriesChanged (hWndLogEntries) ; ! 271: ! 272: return (pLog) ; ! 273: } // AllocateLogData ! 274: ! 275: ! 276: void FreeLogData (PLOG pLog) ! 277: { // FreeLogData ! 278: MemoryFree (pLog->pPerfData) ; ! 279: MemoryFree (pLog->pLogData) ; ! 280: } // FreeLogData ! 281: ! 282: ! 283: void UpdateLogSize (HWND hWnd) ! 284: /* ! 285: Effect: Set the size value to the current size. Also change the ! 286: size entry in the status line. ! 287: */ ! 288: { // UpdateLogSize ! 289: PLOG pLog ; ! 290: TCHAR szSize [ShortTextLen + 1] ; ! 291: ! 292: pLog = LogData (hWnd) ; ! 293: ! 294: LongToCommaString (pLog->lFileSize, szSize) ; ! 295: SetDlgItemText (hWnd, IDD_LOGSIZE, szSize) ; ! 296: ! 297: if (!PlayingBackLog()) ! 298: { ! 299: StatusUpdateIcons (hWndStatus) ; ! 300: } ! 301: } // UpdateLogSize ! 302: ! 303: ! 304: HANDLE LogAppendSetup(PLOG pLog, PLOGHEADER pLogFileHeader) ! 305: { // LogAppendSetup ! 306: PLOGHEADER pHeader ; ! 307: LOGPOSITION LP ; ! 308: DWORD lPreviousIndexBlock ; ! 309: DWORD lNextIndexBlock ; ! 310: PLOGHEADER pPlaybackLogHeader ; ! 311: HANDLE hMapHandle ; ! 312: ! 313: pHeader = (PLOGHEADER) FileMap(pLog->hFile, &hMapHandle) ; ! 314: if (!pHeader || ! 315: !strsame(pHeader->szSignature, LogFileSignature) || ! 316: pHeader->wVersion != LogFileVersion || ! 317: pHeader->wRevision != LogFileRevision) ! 318: { ! 319: if (pHeader) ! 320: { ! 321: FileUnMap((LPVOID)pHeader, hMapHandle) ; ! 322: } ! 323: return 0 ; ! 324: } ! 325: ! 326: *pLogFileHeader = *pHeader ; ! 327: ! 328: ! 329: LP.pIndexBlock = FirstIndexBlock(pHeader) ; ! 330: LP.iIndex = 0 ; ! 331: LP.iPosition = 0 ; ! 332: lPreviousIndexBlock = pHeader->iLength ; ! 333: lNextIndexBlock = LP.pIndexBlock->lNextBlockOffset ; ! 334: ! 335: // since inside NextReLogIndexPosition would eventually call ! 336: // PlaybackSeek for large log file, we have to temporarily ! 337: // setup PlaybackLog.pHeader. Not a good fix but it works... ! 338: pPlaybackLogHeader = PlaybackLog.pHeader ; ! 339: PlaybackLog.pHeader = pHeader ; ! 340: while (NextReLogIndexPosition(&LP)) ! 341: { ! 342: if (LP.pIndexBlock->lNextBlockOffset != lNextIndexBlock) ! 343: { ! 344: lPreviousIndexBlock = lNextIndexBlock ; ! 345: lNextIndexBlock = LP.pIndexBlock->lNextBlockOffset ; ! 346: } ! 347: } ! 348: ! 349: PlaybackLog.pHeader = pPlaybackLogHeader ; ! 350: if (!pLogIndexBlock) ! 351: { ! 352: pLogIndexBlock = (LOGINDEXBLOCK *) MemoryAllocate (sizeof(LOGINDEXBLOCK)) ; ! 353: } ! 354: *pLogIndexBlock = *LP.pIndexBlock ; ! 355: pLog->lIndexBlockOffset = lPreviousIndexBlock ; ! 356: pLog->iIndex = ++LP.iIndex ; ! 357: pLog->lFileSize = FileSeekEnd(pLog->hFile, 0) ; ! 358: ! 359: FileUnMap((LPVOID)pHeader, hMapHandle) ; ! 360: return pLog->hFile ; ! 361: } // LogAppendSetup ! 362: ! 363: void LogRemoveCounterName (PLOG pLog) ! 364: { ! 365: PPERFSYSTEM pSystem ; ! 366: ! 367: if (pLog->pBaseCounterName) ! 368: { ! 369: MemoryFree (pLog->pBaseCounterName) ; ! 370: } ! 371: pLog->pBaseCounterName = 0 ; ! 372: pLog->lBaseCounterNameSize = 0 ; ! 373: pLog->lBaseCounterNameOffset = 0 ; ! 374: ! 375: // clear all the system marker to indicate they have not been ! 376: // saved ! 377: for (pSystem = pLog->pSystemFirst ; ! 378: pSystem ; ! 379: pSystem = pSystem->pSystemNext) ! 380: { ! 381: pSystem->bSystemCounterNameSaved = FALSE ; ! 382: } ! 383: } ! 384: ! 385: int CreateLogFile (PLOG pLog, BOOL bCreateFile, BOOL bSameFile) ! 386: { // CreateLogFile ! 387: HANDLE returnHandle ; ! 388: LOGHEADER LogFileHeader ; ! 389: long lCurPosition ; ! 390: LOGFILECOUNTERNAME CounterNameRecord ; ! 391: ! 392: pLog->lFileSize = 0 ; ! 393: ! 394: if (!pLogIndexBlock) ! 395: { ! 396: pLogIndexBlock = (LOGINDEXBLOCK *) MemoryAllocate (sizeof(LOGINDEXBLOCK)) ; ! 397: } ! 398: ! 399: lstrcpy (pLogIndexBlock->szSignature, LogIndexSignature) ; ! 400: pLog->hFile = FileHandleOpen (pLog->szFilePath) ; ! 401: if (pLog->hFile != INVALID_HANDLE_VALUE) ! 402: { ! 403: // if this is a pre-existing log file, set up to append to it ! 404: returnHandle = LogAppendSetup(pLog, &LogFileHeader) ; ! 405: if (!returnHandle) ! 406: { ! 407: // this is not a log file... ! 408: CloseHandle (pLog->hFile) ; ! 409: return (ERR_BAD_LOG_FILE) ; ! 410: } ! 411: ! 412: pLog->hFile = returnHandle ; ! 413: } ! 414: ! 415: if (bCreateFile && (!pLog->hFile || pLog->hFile == INVALID_HANDLE_VALUE)) ! 416: { ! 417: // Create a new log file if needed. ! 418: pLog->hFile = FileHandleCreate (pLog->szFilePath) ; ! 419: if (!pLog->hFile) ! 420: return (ERR_LOG_FILE) ; ! 421: lstrcpy (LogFileHeader.szSignature, LogFileSignature) ; ! 422: LogFileHeader.wVersion = LogFileVersion ; ! 423: LogFileHeader.wRevision = LogFileRevision ; ! 424: LogFileHeader.iLength = sizeof (LOGHEADER) ; ! 425: LogFileHeader.lBaseCounterNameOffset = 0 ; ! 426: if (!FileWrite (pLog->hFile, &LogFileHeader, sizeof (LogFileHeader))) ! 427: { ! 428: CloseHandle (pLog->hFile) ; ! 429: return (ERR_LOG_FILE) ; ! 430: } ! 431: ! 432: pLog->iIndex = 0 ; ! 433: pLog->lIndexBlockOffset = FileTell (pLog->hFile) ; ! 434: FileSeekCurrent (pLog->hFile, sizeof (LOGINDEXBLOCK)) ; ! 435: pLog->lFileSize = sizeof(LOGHEADER) + sizeof (LOGINDEXBLOCK) ; ! 436: pLogIndexBlock->iNumIndexes = 0 ; ! 437: pLogIndexBlock->lNextBlockOffset = 0 ; ! 438: ! 439: // get rid of any previous counter names and get ready for start ! 440: if (!bSameFile) ! 441: { ! 442: LogRemoveCounterName (pLog) ; ! 443: } ! 444: } ! 445: else if (bCreateFile) ! 446: { ! 447: // this is an existing log file, setup the counter names ! 448: // LogFileHeader already has the header info filled in ! 449: // by LogAppendSetup ! 450: if (!bSameFile || !pLog->pBaseCounterName) ! 451: { ! 452: // get rid of any previous counter names ! 453: LogRemoveCounterName (pLog) ; ! 454: ! 455: // read the new names and get ready for start ! 456: lCurPosition = FileTell (pLog->hFile) ; ! 457: ! 458: FileSeekBegin (pLog->hFile, ! 459: LogFileHeader.lBaseCounterNameOffset) ; ! 460: ! 461: if (!(FileRead (pLog->hFile, ! 462: &CounterNameRecord, ! 463: sizeof (CounterNameRecord)))) ! 464: { ! 465: FileSeekBegin (pLog->hFile, ! 466: lCurPosition) ; ! 467: goto EXIT ; ! 468: } ! 469: ! 470: FileSeekBegin (pLog->hFile, ! 471: CounterNameRecord.lCurrentCounterNameOffset) ; ! 472: ! 473: if (!(pLog->pBaseCounterName = MemoryAllocate ( ! 474: CounterNameRecord.lUnmatchCounterNames))) ! 475: { ! 476: FileSeekBegin (pLog->hFile, ! 477: lCurPosition) ; ! 478: goto EXIT ; ! 479: } ! 480: if (!(FileRead (pLog->hFile, ! 481: pLog->pBaseCounterName, ! 482: CounterNameRecord.lUnmatchCounterNames))) ! 483: { ! 484: MemoryFree (pLog->pBaseCounterName) ; ! 485: pLog->pBaseCounterName = NULL ; ! 486: FileSeekBegin (pLog->hFile, ! 487: lCurPosition) ; ! 488: goto EXIT ; ! 489: } ! 490: // we got the data, fill in other info ! 491: pLog->lBaseCounterNameSize = ! 492: CounterNameRecord.lUnmatchCounterNames ; ! 493: pLog->lBaseCounterNameOffset = ! 494: LogFileHeader.lBaseCounterNameOffset ; ! 495: ! 496: FileSeekBegin (pLog->hFile, ! 497: lCurPosition) ; ! 498: } ! 499: } ! 500: ! 501: EXIT: ! 502: ! 503: return (0) ; ! 504: ! 505: } // CreateLogFile ! 506: ! 507: ! 508: BOOL LogGetSystemPerfData (PLOG pLog, ! 509: HKEY hKey) ! 510: { ! 511: long lError ; ! 512: DWORD dwSize; ! 513: ! 514: while (TRUE) ! 515: { ! 516: dwSize = MemorySize (pLog->pPerfData); ! 517: lError = GetSystemPerfData (hKey, L"Global", pLog->pPerfData, ! 518: &dwSize) ; ! 519: ! 520: if (!lError) ! 521: return (TRUE) ; ! 522: ! 523: if (lError == ERROR_MORE_DATA) ! 524: { ! 525: pLog->pPerfData = MemoryResize (pLog->pPerfData, ! 526: MemorySize (pLog->pPerfData) + ! 527: dwPerfDataIncrease) ; ! 528: if (!pLog->pPerfData) ! 529: return (FALSE) ; ! 530: } ! 531: else ! 532: { ! 533: return (FALSE) ; ! 534: } ! 535: } // while ! 536: } ! 537: ! 538: void LogWriteIndexBlock (PLOG pLog) ! 539: { ! 540: FileSeekBegin (pLog->hFile, ! 541: pLog->lIndexBlockOffset) ; ! 542: pLogIndexBlock->lNextBlockOffset = 0 ; ! 543: FileWrite (pLog->hFile, ! 544: (LPSTR) pLogIndexBlock, ! 545: sizeof (LOGINDEXBLOCK)) ; ! 546: } // LogWriteIndexBlock ! 547: ! 548: ! 549: BOOL LogWriteIndex (PLOG pLog, ! 550: UINT uFlags, ! 551: SYSTEMTIME *pSystemTime, ! 552: LONG lDataOffset, ! 553: int iSystemsLogged) ! 554: { // LogWriteIndex ! 555: LOGINDEX Index ; ! 556: long lNextBlockOffset ; ! 557: BOOL WriteOK ; ! 558: //=============================// ! 559: // Add Index Block Entry // ! 560: //=============================// ! 561: //=============================// ! 562: // Index Block Full? // ! 563: //=============================// ! 564: ! 565: WriteOK = TRUE ; ! 566: ! 567: if (pLog->iIndex == LogFileBlockMaxIndexes - 1) ! 568: { ! 569: lNextBlockOffset = FileTell (pLog->hFile) ; ! 570: pLogIndexBlock->lNextBlockOffset = lNextBlockOffset ; ! 571: FileSeekBegin (pLog->hFile, ! 572: pLog->lIndexBlockOffset) ; ! 573: WriteOK = FileWrite (pLog->hFile, ! 574: (LPSTR) pLogIndexBlock, ! 575: sizeof (LOGINDEXBLOCK)) ; ! 576: if (WriteOK) ! 577: { ! 578: FileSeekBegin (pLog->hFile, ! 579: lNextBlockOffset) ; ! 580: // Fake file end until we really write the block ! 581: pLogIndexBlock->iNumIndexes = 0 ; ! 582: pLogIndexBlock->lNextBlockOffset = 0 ; ! 583: WriteOK = FileWrite (pLog->hFile, ! 584: (LPSTR) pLogIndexBlock, ! 585: sizeof (LOGINDEXBLOCK)) ; ! 586: if (WriteOK) ! 587: { ! 588: pLog->lIndexBlockOffset = lNextBlockOffset ; ! 589: pLog->iIndex = 0 ; ! 590: pLog->lFileSize += sizeof (LOGINDEXBLOCK) ; ! 591: } ! 592: } ! 593: } // if ! 594: ! 595: //=============================// ! 596: // Add Index Block Entry // ! 597: //=============================// ! 598: ! 599: Index.uFlags = uFlags ; ! 600: Index.SystemTime = *pSystemTime ; ! 601: Index.lDataOffset = lDataOffset ; ! 602: Index.iSystemsLogged = iSystemsLogged ; ! 603: ! 604: pLogIndexBlock->aIndexes [pLog->iIndex] = Index ; ! 605: pLog->iIndex++ ; ! 606: pLogIndexBlock->iNumIndexes++ ; ! 607: ! 608: // write out the index block if the log interval if too large ! 609: if (pLog->iIntervalMSecs >= LARGE_INTERVAL * 1000 ) ! 610: { ! 611: LONG lCurPosition ; ! 612: ! 613: // save the current file position ! 614: lCurPosition = FileTell (pLog->hFile) ; ! 615: ! 616: // flush the index block to the file ! 617: LogWriteIndexBlock (pLog) ; ! 618: ! 619: // restore previous file position since ! 620: // LogWriteIndexBlock has messed it up ! 621: FileSeekBegin (pLog->hFile, lCurPosition) ; ! 622: } ! 623: return (WriteOK) ; ! 624: } // LogWriteIndex ! 625: ! 626: ! 627: ! 628: BOOL LogWritePerfData (HWND hWnd, ! 629: PLOG pLog, ! 630: PPERFDATA pPerfData, ! 631: SYSTEMTIME *pSystemTime, ! 632: DWORD iNumSystems, ! 633: BOOL bWriteIndex) ! 634: { // LogWritePerfData ! 635: LONG lSize ; ! 636: BOOL WriteOK ; ! 637: LONG lCurPosition ; ! 638: ! 639: lSize = pPerfData->TotalByteLength ; ! 640: ! 641: lCurPosition = FileTell (pLog->hFile) ; ! 642: ! 643: //=============================// ! 644: // Write Perf Data // ! 645: //=============================// ! 646: ! 647: WriteOK = FileWrite (pLog->hFile, (LPSTR) pPerfData, lSize) ; ! 648: if (WriteOK) ! 649: { ! 650: pLog->lFileSize += lSize ; ! 651: ! 652: if (bWriteIndex) ! 653: { ! 654: WriteOK = LogWriteIndex (pLog, ! 655: LogFileIndexData, ! 656: pSystemTime, ! 657: lCurPosition, ! 658: iNumSystems) ; ! 659: } ! 660: } ! 661: if ( !WriteOK ) ! 662: { ! 663: CloseLog (hWnd, pLog) ; ! 664: PrepareMenu (GetMenu (hWndMain)) ; ! 665: UpdateLogDisplay (hWnd) ; ! 666: DlgErrorBox (hWnd, ERR_LOG_FILE, pLog->szFilePath) ; ! 667: } ! 668: return (WriteOK) ; ! 669: } // LogWritePerfData ! 670: ! 671: ! 672: //==========================================================================// ! 673: // Message Handlers // ! 674: //==========================================================================// ! 675: ! 676: ! 677: void static OnSize (HWND hDlg, ! 678: int xWidth, ! 679: int yHeight) ! 680: /* ! 681: Effect: Perform any actions necessary when the log window (dialog) ! 682: is resized. In particular, move and resize some of the ! 683: dialogs controls. ! 684: ! 685: Internals: The rightmost control, the log status, contains one of ! 686: only several values. These values are all within ! 687: xStatusWidth, computed at init time. Put this control ! 688: one scroll width away from the right edge at fixed ! 689: width. Move its associated text prompt with it. Then ! 690: use the remaining space for the filename control, which ! 691: can probably use it. ! 692: ! 693: To Do: Need to consider minimum first. ! 694: */ ! 695: { // OnSize ! 696: int xStatusPos ; ! 697: int xStatusTextPos ; ! 698: int xNameWidth ; ! 699: int xMinWidth ; ! 700: ! 701: //=============================// ! 702: // Enough space for minimums? // ! 703: //=============================// ! 704: ! 705: xMinWidth = ! 706: xScrollWidth + // margin before prompt ! 707: DialogWidth (hDlg, IDD_LOGFILETEXT) + // width of prompt ! 708: xNameMinWidth + // width of name ! 709: xScrollWidth + ! 710: DialogWidth (hDlg, IDD_LOGSTATUSTEXT) + ! 711: DialogWidth (hDlg, IDD_LOGSTATUS) + ! 712: xScrollWidth ; ! 713: ! 714: ! 715: xStatusPos = xWidth - xStatusWidth - xScrollWidth ; ! 716: DialogMove (hDlg, IDD_LOGSTATUS, ! 717: xStatusPos, NOCHANGE, ! 718: xStatusWidth, NOCHANGE) ; ! 719: ! 720: xStatusTextPos = xStatusPos - ! 721: DialogWidth (hDlg, IDD_LOGSTATUSTEXT) - ! 722: xScrollWidth ; ! 723: DialogMove (hDlg, IDD_LOGSTATUSTEXT, ! 724: xStatusTextPos, NOCHANGE, ! 725: NOCHANGE, NOCHANGE) ; ! 726: ! 727: xNameWidth = xStatusTextPos - ! 728: DialogWidth (hDlg, IDD_LOGFILETEXT) - ! 729: 2 * xScrollWidth ; ! 730: DialogMove (hDlg, IDD_LOGFILE, ! 731: NOCHANGE, NOCHANGE, ! 732: xNameWidth, NOCHANGE) ; ! 733: ! 734: DialogMove (hDlg, IDD_LOGSIZE, ! 735: DialogXPos (hDlg, IDD_LOGFILE), NOCHANGE, ! 736: DialogWidth (hDlg, IDD_LOGFILE), NOCHANGE) ; ! 737: ! 738: DialogMove (hDlg, IDD_LOGINTERVALTEXT, ! 739: DialogXPos (hDlg, IDD_LOGSTATUSTEXT), NOCHANGE, ! 740: DialogWidth (hDlg, IDD_LOGSTATUSTEXT), NOCHANGE) ; ! 741: ! 742: DialogMove (hDlg, IDD_LOGINTERVAL, ! 743: DialogXPos (hDlg, IDD_LOGSTATUS), NOCHANGE, ! 744: DialogWidth (hDlg, IDD_LOGSTATUS), NOCHANGE) ; ! 745: ! 746: DialogMove (hDlg, IDD_LOGENTRIESTEXT, ! 747: xScrollWidth, NOCHANGE, NOCHANGE, NOCHANGE) ; ! 748: ! 749: DialogMove (hDlg, IDD_LOGENTRIES, ! 750: xScrollWidth, NOCHANGE, ! 751: xWidth - 2 * xScrollWidth, ! 752: yHeight - DialogYPos (hDlg, IDD_LOGENTRIES) - yScrollHeight) ; ! 753: WindowInvalidate (hDlg) ; ! 754: } // OnSize ! 755: ! 756: ! 757: int OnCtlColor (HWND hDlg, ! 758: HDC hDC) ! 759: { ! 760: SetTextColor (hDC, crBlack) ; ! 761: SetBkColor (hDC, crLightGray) ; ! 762: return ((int) hbLightGray) ; ! 763: } ! 764: ! 765: ! 766: void static OnInitDialog (HWND hDlg) ! 767: { ! 768: HDC hDC ; ! 769: PLOG pLog ; ! 770: ! 771: hWndLogEntries = DialogControl (hDlg, IDD_LOGENTRIES) ; ! 772: ! 773: pLog = AllocateLogData (hDlg) ; ! 774: if (!pLog) ! 775: return ; ! 776: ! 777: StringLoad (IDS_CLOSED, szClosed) ; ! 778: // StringLoad (IDS_PAUSED, szPaused) ; ! 779: StringLoad (IDS_COLLECTING, szCollecting) ; ! 780: UpdateLogDisplay (hDlg) ; ! 781: ! 782: hDC = GetDC (hDlg) ; ! 783: xStatusWidth = max (TextWidth (hDC, szClosed), ! 784: TextWidth (hDC, szCollecting)) ; ! 785: // max (TextWidth (hDC, szPaused), ! 786: // TextWidth (hDC, szCollecting))) ; ! 787: xStatusWidth += xScrollWidth ; ! 788: ! 789: xNameMinWidth = TextAvgWidth (hDC, LogNameMinLen) ; ! 790: ReleaseDC (hDlg, hDC) ; ! 791: } ! 792: ! 793: ! 794: ! 795: void static OnDestroy (HWND hWnd) ! 796: /* ! 797: Effect: Perform any actions necessary when a LogDisplay window ! 798: is being destroyed. In particular, free the instance ! 799: data for the log. ! 800: ! 801: Since we really only have one log window and one global ! 802: log data structure, we don't free the structure. We do, ! 803: however, delete the objects allocated within the structure. ! 804: */ ! 805: { // OnDestroy ! 806: PLOG pLog ; ! 807: ! 808: pLog = LogData (hWnd) ; ! 809: FreeLogData (pLog) ; ! 810: } // OnDestroy ! 811: ! 812: ! 813: void static OnDrawItem (HWND hWnd, LPDRAWITEMSTRUCT lpDI) ! 814: { // OnDrawItem ! 815: HDC hDC ; ! 816: RECT rectComputer, rectObject ; ! 817: PLOGENTRY pLogEntry ; ! 818: PLOG pLog ; ! 819: COLORREF preBkColor ; ! 820: COLORREF preTextColor ; ! 821: ! 822: pLog = LogData (hWnd) ; ! 823: ! 824: pLogEntry = LogEntryN (hWndLogEntries, DIIndex (lpDI)) ; ! 825: ! 826: // LogEntryN (SendMessage) will return LB_ERR for error, have to ! 827: // check for that case ! 828: if (!pLogEntry || pLogEntry == (PLOGENTRY)LB_ERR) ! 829: { ! 830: return ; ! 831: } ! 832: ! 833: hDC = lpDI->hDC ; ! 834: ! 835: SelectFont (hDC, hFontScales) ; ! 836: ! 837: if (DISelected (lpDI)) ! 838: { // if ! 839: preTextColor = SetTextColor (hDC, GetSysColor (COLOR_HIGHLIGHTTEXT)) ; ! 840: preBkColor = SetBkColor (hDC, GetSysColor (COLOR_HIGHLIGHT)) ; ! 841: } // if ! 842: ! 843: rectObject.left = lpDI->rcItem.left ; ! 844: rectObject.top = lpDI->rcItem.top ; ! 845: rectObject.right = rectObject.left + pLog->xCol1Width ; ! 846: rectObject.bottom = lpDI->rcItem.bottom ; ! 847: ! 848: ExtTextOut (hDC, ! 849: rectObject.left + xScrollWidth, rectObject.top, ! 850: ETO_OPAQUE, ! 851: &rectObject, ! 852: pLogEntry->szObject, ! 853: lstrlen (pLogEntry->szObject), ! 854: NULL) ; ! 855: ! 856: ! 857: rectComputer.left = rectObject.right ; ! 858: rectComputer.top = lpDI->rcItem.top ; ! 859: rectComputer.right = lpDI->rcItem.right ; ! 860: rectComputer.bottom = lpDI->rcItem.bottom ; ! 861: ! 862: ExtTextOut (hDC, ! 863: rectComputer.left, rectComputer.top, ! 864: ETO_OPAQUE, ! 865: &rectComputer, ! 866: pLogEntry->szComputer, ! 867: lstrlen (pLogEntry->szComputer), ! 868: NULL) ; ! 869: ! 870: if (DIFocus (lpDI)) ! 871: DrawFocusRect (hDC, &(lpDI->rcItem)) ; ! 872: ! 873: if (DISelected (lpDI)) ! 874: { // if ! 875: preTextColor = SetTextColor (hDC, preTextColor) ; ! 876: preBkColor = SetBkColor (hDC, preBkColor) ; ! 877: } // if ! 878: // RestoreDC (hDC, -1) ; ! 879: } // OnDrawItem ! 880: ! 881: ! 882: ! 883: //==========================================================================// ! 884: // Exported Functions // ! 885: //==========================================================================// ! 886: ! 887: ! 888: int APIENTRY LogDisplayDlgProc (HWND hDlg, ! 889: unsigned iMessage, ! 890: WPARAM wParam, ! 891: LONG lParam) ! 892: /* ! 893: Note: This function must be exported in the application's ! 894: linker-definition file, perfmon.def. ! 895: */ ! 896: { // LogDisplayDlgProc ! 897: // HDC hDC ; ! 898: ! 899: switch (iMessage) ! 900: { ! 901: case WM_INITDIALOG: ! 902: OnInitDialog (hDlg) ; ! 903: break ; ! 904: ! 905: case WM_CTLCOLORDLG: ! 906: case WM_CTLCOLOREDIT: ! 907: case WM_CTLCOLORBTN: ! 908: case WM_CTLCOLORSTATIC: ! 909: return (OnCtlColor (hDlg, (HDC) wParam)) ; ! 910: break ; ! 911: ! 912: case WM_DRAWITEM: ! 913: OnDrawItem (hDlg, (LPDRAWITEMSTRUCT) lParam) ; ! 914: break ; ! 915: ! 916: case WM_LBUTTONDBLCLK: ! 917: SendMessage (hWndMain, WM_LBUTTONDBLCLK, wParam, lParam) ; ! 918: break ; ! 919: ! 920: case WM_LBUTTONDOWN: ! 921: DoWindowDrag (lParam) ; ! 922: break ; ! 923: ! 924: case WM_SIZE: ! 925: OnSize (hDlg, LOWORD (lParam), HIWORD (lParam)) ; ! 926: break ; ! 927: ! 928: case WM_TIMER: ! 929: LogTimer (hDlg, FALSE) ; ! 930: break ; ! 931: ! 932: case WM_DESTROY: ! 933: OnDestroy (hDlg) ; ! 934: return (FALSE) ; ! 935: break ; ! 936: ! 937: default: ! 938: return (FALSE) ; ! 939: } // switch ! 940: ! 941: return (TRUE) ; ! 942: } // LogDisplayDlgProc ! 943: ! 944: ! 945: #if 0 ! 946: PLOG LogData (HWND hWndLog) ! 947: { ! 948: return (&Log) ; ! 949: } ! 950: #endif ! 951: ! 952: HWND CreateLogWindow (HWND hWndParent) ! 953: /* ! 954: Effect: Create the Log window. This window is a child of ! 955: hWndMain. ! 956: ! 957: Note: We dont worry about the size here, as this window ! 958: will be resized whenever the main window is resized. ! 959: ! 960: */ ! 961: { // CreateLogWindow ! 962: HWND hWnd ; ! 963: hWnd = CreateDialog (hInstance, ! 964: MAKEINTRESOURCE (idDlgLogDisplay), ! 965: hWndParent, ! 966: (DLGPROC) LogDisplayDlgProc) ; ! 967: ! 968: return (hWnd) ; ! 969: } // CreateLogWindow ! 970: ! 971: ! 972: ! 973: void UpdateLogDisplay (HWND hWnd) ! 974: /* ! 975: Effect: Set the values for the various controls in the log ! 976: display. ! 977: ! 978: Called By: OnInitDialog, any other routines that change these ! 979: values. ! 980: */ ! 981: { // UpdateLogDisplay ! 982: PLOG pLog ; ! 983: WCHAR szSize [MiscTextLen + 1] ; ! 984: ! 985: pLog = LogData (hWnd) ; ! 986: ! 987: DialogSetString (hWnd, IDD_LOGFILE, pLog->szFilePath) ; ! 988: ! 989: // position the cursor at the end of the text ! 990: EditSetTextEndPos (hWnd, IDD_LOGFILE) ; ! 991: ! 992: ! 993: DialogSetString (hWnd, IDD_LOGSTATUS, StatusText (pLog->iStatus)) ; ! 994: ! 995: LongToCommaString (pLog->lFileSize, szSize) ; ! 996: DialogSetString (hWnd, IDD_LOGSIZE, szSize) ; ! 997: ! 998: DialogSetInterval (hWnd, IDD_LOGINTERVAL, pLog->iIntervalMSecs) ; ! 999: } // UpdateLogDisplay ! 1000: ! 1001: ! 1002: BOOL LogInitializeApplication (void) ! 1003: { ! 1004: return (TRUE) ; ! 1005: } // LogInitializeApplication ! 1006: ! 1007: ! 1008: void SetLogTimer (HWND hWnd, ! 1009: int iIntervalMSecs) ! 1010: { ! 1011: PLOG pLog ; ! 1012: ! 1013: pLog = LogData (hWnd) ; ! 1014: pLog->iIntervalMSecs = iIntervalMSecs ; ! 1015: ! 1016: KillTimer (hWnd, LogTimerID) ; ! 1017: SetTimer (hWnd, LogTimerID, pLog->iIntervalMSecs, NULL) ; ! 1018: } ! 1019: ! 1020: ! 1021: void ClearLogTimer (HWND hWnd) ! 1022: { ! 1023: KillTimer (hWnd, LogTimerID) ; ! 1024: } ! 1025: ! 1026: ! 1027: ! 1028: BOOL CloseLogStopTimer (HWND hWnd, PLOG pLog) ! 1029: { ! 1030: CloseHandle (pLog->hFile) ; ! 1031: ! 1032: pLog->hFile = 0 ; ! 1033: pLog->iStatus = iPMStatusClosed ; ! 1034: ! 1035: ClearLogTimer (hWnd) ; ! 1036: ! 1037: return (TRUE) ; ! 1038: } ! 1039: ! 1040: ! 1041: BOOL CloseLog (HWND hWnd, PLOG pLog) ! 1042: { // CloseLog ! 1043: LogWriteIndexBlock (pLog) ; ! 1044: CloseLogStopTimer (hWnd, pLog) ; ! 1045: WindowInvalidate (hWndStatus) ; ! 1046: return (TRUE) ; ! 1047: } // CloseLog ! 1048: ! 1049: BOOL StartLog (HWND hWnd, PLOG pLog, BOOL bSameFile) ! 1050: { ! 1051: int RetCode ; ! 1052: SYSTEMTIME SystemTime ; ! 1053: ! 1054: if ((RetCode = CreateLogFile (pLog, TRUE, bSameFile)) == 0) ! 1055: { ! 1056: pLog->iStatus = iPMStatusCollecting ; ! 1057: ! 1058: GetLocalTime (&SystemTime) ; ! 1059: ! 1060: // write a dummy record. ! 1061: // this is needed because when playingback log ! 1062: // it will skip the first index from the first ! 1063: // index block. ! 1064: LogWriteIndex (pLog, 0, &SystemTime, 0, 0) ; ! 1065: ! 1066: if (!PlayingBackLog()) ! 1067: { ! 1068: // write out a bookmark to indicate start of new data ! 1069: LogWriteStartBookmark (hWnd, &SystemTime) ; ! 1070: } ! 1071: ! 1072: if (!PlayingBackLog () && !(pLog->bManualRefresh)) ! 1073: { ! 1074: SetLogTimer (hWnd, pLog->iIntervalMSecs) ; ! 1075: WindowInvalidate (hWndStatus) ; ! 1076: } ! 1077: ! 1078: // write counter names if needed ! 1079: LogWriteSystemCounterNames (hWnd, pLog) ; ! 1080: ! 1081: return (TRUE) ; ! 1082: } ! 1083: ! 1084: pLog->hFile = 0 ; ! 1085: CloseLogStopTimer(hWnd, pLog); ! 1086: PrepareMenu (GetMenu (hWndMain)) ; ! 1087: UpdateLogDisplay (hWnd) ; ! 1088: DlgErrorBox (hWnd, RetCode, pLog->szFilePath); ! 1089: return (FALSE) ; ! 1090: } ! 1091: ! 1092: ! 1093: ! 1094: DWORD LogFindEntry(LPTSTR lpszComputer, DWORD ObjectTitleIndex) ! 1095: /* ! 1096: Effect: Returns the index of the specified Computer/Object ! 1097: if it already exists in the Entries List Box, ! 1098: otherwise returns LOG_ENTRY_NOT_FOUND ! 1099: */ ! 1100: { ! 1101: DWORD iLogEntry ; ! 1102: DWORD iLogNum ; ! 1103: PLOGENTRY pLogEntry ; ! 1104: ! 1105: iLogNum = (DWORD) LBNumItems(hWndLogEntries) ; ! 1106: for (iLogEntry = 0; ! 1107: iLogEntry < iLogNum ; ! 1108: iLogEntry++) ! 1109: { ! 1110: pLogEntry = (PLOGENTRY) LBData(hWndLogEntries, iLogEntry) ; ! 1111: if (pLogEntry->ObjectTitleIndex == ObjectTitleIndex && ! 1112: strsamei(pLogEntry->szComputer, lpszComputer)) ! 1113: { ! 1114: return iLogEntry ; ! 1115: } ! 1116: } ! 1117: return (DWORD) LOG_ENTRY_NOT_FOUND; ! 1118: } ! 1119: ! 1120: ! 1121: ! 1122: BOOL LogAddEntry (HWND hWndLog, ! 1123: LPTSTR lpszComputer, ! 1124: LPTSTR lpszObject, ! 1125: DWORD ObjectTitleIndex) ! 1126: /* ! 1127: Effect: Add an entry in the log structure for the computer and ! 1128: object to be logged. ! 1129: ! 1130: Returns: Whether the operation could be performed. ! 1131: */ ! 1132: { // LogAddEntry ! 1133: PLOG pLog ; ! 1134: PLOGENTRY pLogEntry ; ! 1135: UINT iIndex ; ! 1136: ! 1137: ! 1138: pLog = LogData (hWndLog) ; ! 1139: ! 1140: SystemAdd (&(pLog->pSystemFirst), lpszComputer) ; ! 1141: ! 1142: pLogEntry = MemoryAllocate (sizeof (LOGENTRY)) ; ! 1143: if (!pLogEntry) ! 1144: return (FALSE) ; ! 1145: ! 1146: lstrcpy (pLogEntry->szComputer, lpszComputer) ; ! 1147: lstrcpy (pLogEntry->szObject, lpszObject) ; ! 1148: pLogEntry->ObjectTitleIndex = ObjectTitleIndex ; ! 1149: ! 1150: iIndex = LBAdd (hWndLogEntries, pLogEntry) ; ! 1151: ! 1152: if (iIndex == LB_ERR) ! 1153: { ! 1154: iIndex = 0 ; ! 1155: } ! 1156: ! 1157: LBSetSelection (hWndLogEntries, iIndex) ; ! 1158: LBSetVisible (hWndLogEntries, iIndex) ; ! 1159: ! 1160: LogEntriesChanged (hWndLogEntries) ; ! 1161: ! 1162: LogAddEntryToList (&(pLog->pLogEntryFirst), pLogEntry) ; ! 1163: ! 1164: ! 1165: } // LogAddEntry ! 1166: ! 1167: ! 1168: ! 1169: ! 1170: BOOL ToggleLogRefresh (HWND hWnd) ! 1171: { // ToggleLogRefresh ! 1172: PLOG pLog ; ! 1173: ! 1174: pLog = LogData (hWnd) ; ! 1175: ! 1176: if (pLog->bManualRefresh) ! 1177: SetLogTimer (hWnd, pLog->iIntervalMSecs) ; ! 1178: else ! 1179: ClearLogTimer (hWnd) ; ! 1180: ! 1181: pLog->bManualRefresh = !pLog->bManualRefresh ; ! 1182: return (pLog->bManualRefresh) ; ! 1183: } // ToggleLogRefresh ! 1184: ! 1185: BOOL LogRefresh (HWND hWnd) ! 1186: { // LogRefresh ! 1187: PLOG pLog ; ! 1188: ! 1189: pLog = LogData (hWnd) ; ! 1190: ! 1191: return (pLog->bManualRefresh) ; ! 1192: } // LogRefresh ! 1193: ! 1194: ! 1195: int SelectLogObjects(LPTSTR lpszComputer, ! 1196: PPERFDATA pPerfData, ! 1197: PPERFDATA *ppLogData) ! 1198: /* ! 1199: Effect: This routine copies the header from pPerfData ! 1200: to pLogData and initializes the byte length and the ! 1201: number of objects. It then copies the previously ! 1202: selected objects from pPerfData to pLogData. If ! 1203: pLogData must be enlarged to accomodate the new data, ! 1204: this routine will enlarge it. ! 1205: ! 1206: Returns: An updated pLogData, and TRUE if at least one object ! 1207: was copied. ! 1208: ! 1209: */ ! 1210: ! 1211: { ! 1212: PLOGENTRY pLogEntry ; ! 1213: PPERF_OBJECT_TYPE ! 1214: pObject ; ! 1215: DWORD TotalBytes ; ! 1216: DWORD NumObjects ; ! 1217: PBYTE pNextObject ; ! 1218: DWORD MaxLogDataSize ; ! 1219: PLOG pLog ; ! 1220: ! 1221: if (!*ppLogData || !pPerfData) ! 1222: return -1 ; ! 1223: ! 1224: memcpy (*ppLogData, pPerfData, pPerfData->HeaderLength) ; ! 1225: TotalBytes = pPerfData->HeaderLength ; ! 1226: MaxLogDataSize = MemorySize(*ppLogData) ; ! 1227: NumObjects = 0; ! 1228: ! 1229: ! 1230: pLog = LogData (hWndLog) ; ! 1231: ! 1232: for (pLogEntry = pLog->pLogEntryFirst ; ! 1233: pLogEntry ; ! 1234: pLogEntry = pLogEntry->pNextLogEntry) ! 1235: { // for ! 1236: if (strsamei(pLogEntry->szComputer, lpszComputer)) ! 1237: { ! 1238: pObject = GetObjectDefByTitleIndex(pPerfData, ! 1239: pLogEntry->ObjectTitleIndex) ; ! 1240: ! 1241: if (pObject) ! 1242: { ! 1243: ! 1244: if (MaxLogDataSize < TotalBytes + pObject->TotalByteLength) ! 1245: { ! 1246: *ppLogData = MemoryResize(*ppLogData, ! 1247: TotalBytes + pObject->TotalByteLength) ; ! 1248: if (!*ppLogData) ! 1249: return -1 ; ! 1250: ! 1251: } ! 1252: ! 1253: pNextObject = (PBYTE) *ppLogData + TotalBytes ; ! 1254: memcpy (pNextObject, pObject, pObject->TotalByteLength); ! 1255: TotalBytes += pObject->TotalByteLength ; ! 1256: NumObjects++; ! 1257: } ! 1258: else ! 1259: { ! 1260: } ! 1261: } ! 1262: } // for ! 1263: ! 1264: if (!NumObjects) ! 1265: return 1 ; ! 1266: ! 1267: (*ppLogData)->TotalByteLength = TotalBytes ; ! 1268: (*ppLogData)->NumObjectTypes = NumObjects ; ! 1269: ! 1270: return 0 ; ! 1271: } ! 1272: ! 1273: ! 1274: void LogTimer (HWND hWnd, BOOL bForce) ! 1275: /* ! 1276: Effect: Perform all actions necessary when the log window ! 1277: receives a timer tic. In particular, if we are ! 1278: collecting data, get a new perf_data_block and add a ! 1279: header entry. If the header block is full, write the ! 1280: data to disk. ! 1281: ! 1282: Called By: LogDisplayDlgProc, in response to a WM_TIMER message. ! 1283: */ ! 1284: { // OnTimer ! 1285: PLOG pLog ; ! 1286: PPERFSYSTEM pSystem ; ! 1287: BOOL bWriteIndex ; ! 1288: DWORD iNumSystems ; ! 1289: SYSTEMTIME SystemTime ; ! 1290: int iNoUseSystemDetected = 0 ; ! 1291: ! 1292: pLog = LogData (hWnd) ; ! 1293: ! 1294: if (pLog->iStatus != iPMStatusCollecting) ! 1295: return ; ! 1296: ! 1297: if (bForce || !pLog->bManualRefresh) ! 1298: { ! 1299: iNumSystems = SystemCount(pLog->pSystemFirst) ; ! 1300: bWriteIndex = TRUE ; ! 1301: for (pSystem = pLog->pSystemFirst ; ! 1302: pSystem ; ! 1303: pSystem = pSystem->pSystemNext) ! 1304: { // for ! 1305: if (UpdateSystemData (pSystem, &pLog->pPerfData)) ! 1306: { ! 1307: if (bWriteIndex) ! 1308: { ! 1309: GetLocalTime (&SystemTime) ; ! 1310: } ! 1311: ! 1312: if (SelectLogObjects(pSystem->sysName, ! 1313: pLog->pPerfData, ! 1314: &pLog->pLogData) == 0) ! 1315: { ! 1316: if ( !LogWritePerfData (hWnd, pLog, pLog->pLogData, &SystemTime, ! 1317: iNumSystems, bWriteIndex) ) ! 1318: { ! 1319: CloseLogStopTimer(hWnd, pLog) ; ! 1320: return ; ! 1321: } ! 1322: // write an index for only the first system ! 1323: bWriteIndex = FALSE ; ! 1324: } ! 1325: else ! 1326: { ! 1327: if (!bAddLineInProgress) ! 1328: { ! 1329: pSystem->bSystemNoLongerNeeded = TRUE ; ! 1330: iNoUseSystemDetected ++ ; ! 1331: } ! 1332: } ! 1333: } ! 1334: } // for ! 1335: ! 1336: if (!bWriteIndex) ! 1337: { ! 1338: UpdateLogSize (hWnd) ; ! 1339: } ! 1340: } // if ! 1341: ! 1342: if (iNoUseSystemDetected) ! 1343: { ! 1344: DeleteUnusedSystems (&(pLog->pSystemFirst), iNoUseSystemDetected) ; ! 1345: } ! 1346: } // LogTimer ! 1347: ! 1348: ! 1349: ! 1350: BOOL NextIntervalIndexPosition (PLOG pLog, PLOGPOSITION pLP, int *pNumTics) ! 1351: { ! 1352: SYSTEMTIME SystemTime1 ; ! 1353: SYSTEMTIME SystemTime2 ; ! 1354: LOGPOSITION LP ; ! 1355: PLOGINDEX pIndex ; ! 1356: DWORD TimeDiff ; ! 1357: ! 1358: LogPositionSystemTime (pLP, &SystemTime1) ; ! 1359: ! 1360: LP = *pLP ; ! 1361: ! 1362: while (NextReLogIndexPosition (&LP)) ! 1363: { // while ! 1364: ! 1365: *pNumTics = *pNumTics - 1 ; ! 1366: ! 1367: pIndex = IndexFromPosition (&LP) ; ! 1368: if (pIndex && IsBookmarkIndex (pIndex)) ! 1369: { ! 1370: *pLP = LP ; ! 1371: return TRUE ; ! 1372: } ! 1373: LogPositionSystemTime (&LP, &SystemTime2) ; ! 1374: TimeDiff = (DWORD) SystemTimeDifference (&SystemTime1, &SystemTime2) ; ! 1375: if (TimeDiff * 1000 >= pLog->iIntervalMSecs) ! 1376: { // if ! 1377: *pLP = LP ; ! 1378: return (TRUE) ; ! 1379: } // if ! 1380: } // while ! 1381: ! 1382: return (FALSE) ; ! 1383: } // NextIntervalIndexPosition ! 1384: ! 1385: ! 1386: ! 1387: BOOL ReLogTimer (HWND hWnd, ! 1388: PLOG pLog, ! 1389: LOGPOSITION lp, ! 1390: BOOL *pWriteBookmark) ! 1391: { // ReLogTimer ! 1392: PPERFSYSTEM pSystem ; ! 1393: BOOL bWriteIndex ; ! 1394: DWORD iNumSystems ; ! 1395: SYSTEMTIME SystemTime ; ! 1396: PPERFDATA pPerfData ; ! 1397: ! 1398: bWriteIndex = TRUE ; ! 1399: ! 1400: // First count number of systems to be logged ! 1401: ! 1402: iNumSystems = 0; ! 1403: ! 1404: for (pSystem = pLog->pSystemFirst ; ! 1405: pSystem ; ! 1406: pSystem = pSystem->pSystemNext) ! 1407: { // for ! 1408: pPerfData = LogDataFromPosition (pSystem, &lp) ; ! 1409: if (pPerfData) ! 1410: { ! 1411: if (SelectLogObjects(pSystem->sysName, ! 1412: pPerfData, ! 1413: &pLog->pLogData) == 0) ! 1414: { ! 1415: iNumSystems++; ! 1416: } ! 1417: } ! 1418: } // for ! 1419: ! 1420: // Now we can log the data ! 1421: ! 1422: for (pSystem = pLog->pSystemFirst ; ! 1423: pSystem ; ! 1424: pSystem = pSystem->pSystemNext) ! 1425: { // for ! 1426: pPerfData = LogDataFromPosition (pSystem, &lp) ; ! 1427: if (pPerfData) ! 1428: { ! 1429: // write an index for only the first system ! 1430: LogPositionSystemTime (&lp, &SystemTime) ; ! 1431: if (SelectLogObjects(pSystem->sysName, ! 1432: pPerfData, ! 1433: &pLog->pLogData) == 0) ! 1434: { ! 1435: if (*pWriteBookmark) ! 1436: { ! 1437: // only need to write the start bookmark once. ! 1438: *pWriteBookmark = FALSE ; ! 1439: LogWriteStartBookmark (hWnd, &SystemTime) ; ! 1440: } ! 1441: if ( !LogWritePerfData (hWnd, pLog, pLog->pLogData, &SystemTime, ! 1442: iNumSystems, bWriteIndex) ) ! 1443: { ! 1444: CloseLogStopTimer(hWnd, pLog) ; ! 1445: return FALSE ; ! 1446: } ! 1447: else ! 1448: { ! 1449: // write the index for only the first system logged ! 1450: bWriteIndex = FALSE ; ! 1451: } ! 1452: } ! 1453: } ! 1454: } // for ! 1455: ! 1456: return TRUE ; ! 1457: } // ReLogTimer ! 1458: ! 1459: ! 1460: void ReLog (HWND hWndLog, BOOL bSameFile) ! 1461: { // PlaybackLog ! 1462: PLOG pLog ; ! 1463: LOGPOSITION lp ; ! 1464: // SYSTEMTIME SystemTime ; ! 1465: PLOGINDEX pIndex ; ! 1466: PBOOKMARK pBookmark; ! 1467: int iDisplayTics ; ! 1468: ! 1469: // bWriteBookmark tell relogtimer to write start bookmark ! 1470: BOOL bWriteBookmark = TRUE ; ! 1471: ! 1472: pLog = LogData (hWndLog) ; ! 1473: StartLog (hWndLog, pLog, bSameFile) ; ! 1474: ! 1475: lp = PlaybackLog.StartIndexPos ; ! 1476: iDisplayTics = PlaybackLog.iSelectedTics; ! 1477: ! 1478: while (iDisplayTics > 0) ! 1479: { ! 1480: pIndex = IndexFromPosition (&lp) ; ! 1481: if (pIndex) ! 1482: { ! 1483: if (IsBookmarkIndex (pIndex)) ! 1484: { ! 1485: pBookmark = (PBOOKMARK) PlaybackSeek (pIndex->lDataOffset) ; ! 1486: if (!LogWriteBookmarkData (hWndLog, pBookmark)) ! 1487: break; ! 1488: } ! 1489: else if (!ReLogTimer (hWndLog, pLog, lp, &bWriteBookmark)) ! 1490: break ; ! 1491: } ! 1492: ! 1493: if (!NextIntervalIndexPosition (pLog, &lp, &iDisplayTics)) ! 1494: break ; ! 1495: ! 1496: } // while ! 1497: UpdateLogSize (hWndLog) ; ! 1498: CloseLog (hWndLog, pLog) ; ! 1499: } // ReLog ! 1500: ! 1501: // SaveLog is diff than other because we are not saving a "Line" ! 1502: // We are actually saving an entry in the hWndLogEntries listbox. ! 1503: // It only contains the system & object name. ! 1504: BOOL SaveLog (HWND hWndLog, HANDLE hInputFile, BOOL bGetFileName) ! 1505: { ! 1506: int iIndex, iIndexNum ; ! 1507: PLOG pLog ; ! 1508: PLOGENTRY pLogEntry ; ! 1509: LOGENTRY tempLogEntry ; ! 1510: HANDLE hFile ; ! 1511: DISKLOG DiskLog ; ! 1512: PERFFILEHEADER FileHeader ; ! 1513: TCHAR szFileName [256] ; ! 1514: BOOL newFileName = FALSE ; ! 1515: ! 1516: pLog = LogData (hWndLog) ; ! 1517: if (!pLog) ! 1518: { ! 1519: return (FALSE) ; ! 1520: } ! 1521: ! 1522: if (hInputFile) ! 1523: { ! 1524: // use the input file handle if it is available ! 1525: // this is the case for saving workspace data ! 1526: hFile = hInputFile ; ! 1527: } ! 1528: else ! 1529: { ! 1530: if (pLogFullFileName) ! 1531: { ! 1532: lstrcpy (szFileName, pLogFullFileName) ; ! 1533: } ! 1534: if (bGetFileName || pLogFullFileName == NULL) ! 1535: { ! 1536: // if (pLogFullFileName == NULL) ! 1537: // { ! 1538: // StringLoad (IDS_LOG_FNAME, szFileName) ; ! 1539: // } ! 1540: ! 1541: if (!FileGetName (hWndLog, IDS_LOGFILE, szFileName)) ! 1542: { ! 1543: return (FALSE) ; ! 1544: } ! 1545: newFileName = TRUE ; ! 1546: } ! 1547: ! 1548: hFile = FileHandleCreate (szFileName) ; ! 1549: ! 1550: if (hFile && newFileName) ! 1551: { ! 1552: ChangeSaveFileName (szFileName, IDM_VIEWLOG) ; ! 1553: } ! 1554: else if (!hFile) ! 1555: { ! 1556: DlgErrorBox (hWndLog, ERR_CANT_OPEN, szFileName) ; ! 1557: } ! 1558: } ! 1559: ! 1560: if (!hFile) ! 1561: return (FALSE) ; ! 1562: ! 1563: iIndexNum = LBNumItems (hWndLogEntries) ; ! 1564: ! 1565: if (!hInputFile) ! 1566: { ! 1567: memset (&FileHeader, 0, sizeof (FileHeader)) ; ! 1568: lstrcpy (FileHeader.szSignature, szPerfLogSignature) ; ! 1569: FileHeader.dwMajorVersion = LogMajorVersion ; ! 1570: FileHeader.dwMinorVersion = LogMinorVersion ; ! 1571: ! 1572: if (!FileWrite (hFile, &FileHeader, sizeof (PERFFILEHEADER))) ! 1573: { ! 1574: goto Exit0 ; ! 1575: } ! 1576: } ! 1577: ! 1578: DiskLog.dwIntervalSecs = pLog->iIntervalMSecs ; ! 1579: DiskLog.dwNumLines = iIndexNum ; ! 1580: DiskLog.bManualRefresh = pLog->bManualRefresh ; ! 1581: DiskLog.perfmonOptions = Options ; ! 1582: ! 1583: if (!FileWrite (hFile, &DiskLog, sizeof (DISKLOG))) ! 1584: { ! 1585: goto Exit0 ; ! 1586: } ! 1587: ! 1588: for (iIndex = 0 ; ! 1589: iIndex < iIndexNum ; ! 1590: iIndex++) ! 1591: { // for ! 1592: pLogEntry = LogEntryN (hWndLogEntries, iIndex) ; ! 1593: if (pstrsamei (pLogEntry->szComputer, LocalComputerName)) ! 1594: { ! 1595: tempLogEntry = *pLogEntry ; ! 1596: lstrcpy (tempLogEntry.szComputer, LOCAL_SYS_CODE_NAME) ; ! 1597: if (!FileWrite (hFile, ! 1598: &tempLogEntry, ! 1599: sizeof(LOGENTRY)-sizeof(pLogEntry->pNextLogEntry))) ! 1600: { ! 1601: goto Exit0 ; ! 1602: } ! 1603: } ! 1604: else ! 1605: { ! 1606: if (!FileWrite (hFile, ! 1607: pLogEntry, ! 1608: sizeof(LOGENTRY)-sizeof(pLogEntry->pNextLogEntry))) ! 1609: { ! 1610: goto Exit0 ; ! 1611: } ! 1612: } ! 1613: } // for ! 1614: ! 1615: if (!hInputFile) ! 1616: { ! 1617: CloseHandle (hFile) ; ! 1618: } ! 1619: ! 1620: return (TRUE) ; ! 1621: ! 1622: Exit0: ! 1623: if (!hInputFile) ! 1624: { ! 1625: CloseHandle (hFile) ; ! 1626: ! 1627: // only need to report error if not workspace ! 1628: DlgErrorBox (hWndLog, ERR_SETTING_FILE, szFileName) ; ! 1629: } ! 1630: return (FALSE) ; ! 1631: } ! 1632: ! 1633: BOOL OpenLogVer1 (HWND hWndLog, HANDLE hFile, DISKLOG *pDiskLog, PLOG ! 1634: pLog, DWORD dwMinorVersion) ! 1635: { ! 1636: int iIndex, iIndexNum ; ! 1637: PLOGENTRY pLogEntry ; ! 1638: LOGENTRY LogEntry ; ! 1639: PPERFSYSTEM pSystem; ! 1640: ! 1641: pLog->iIntervalMSecs = pDiskLog->dwIntervalSecs ; ! 1642: if (dwMinorVersion < 3) ! 1643: { ! 1644: pLog->iIntervalMSecs *= 1000 ; ! 1645: } ! 1646: ! 1647: pLog->bManualRefresh = pDiskLog->bManualRefresh ; ! 1648: iIndexNum = pDiskLog->dwNumLines ; ! 1649: ! 1650: LBSetRedraw (hWndLogEntries, FALSE) ; ! 1651: ! 1652: for (iIndex = 0 ; iIndex < iIndexNum ; iIndex++) ! 1653: { ! 1654: if (!FileRead (hFile, ! 1655: &LogEntry, ! 1656: sizeof(LOGENTRY)-sizeof(LogEntry.pNextLogEntry))) ! 1657: { ! 1658: break ; ! 1659: } ! 1660: ! 1661: if (pstrsame (LogEntry.szComputer, LOCAL_SYS_CODE_NAME)) ! 1662: { ! 1663: // convert it back to the local name ! 1664: lstrcpy (LogEntry.szComputer, LocalComputerName) ; ! 1665: } ! 1666: ! 1667: LogAddEntry (hWndLog, ! 1668: LogEntry.szComputer, ! 1669: LogEntry.szObject, ! 1670: LogEntry.ObjectTitleIndex) ; ! 1671: } ! 1672: ! 1673: LBSetRedraw (hWndLogEntries, TRUE) ; ! 1674: ! 1675: for (pSystem = pLog->pSystemFirst ; ! 1676: pSystem ; ! 1677: pSystem = pSystem->pSystemNext) ! 1678: { ! 1679: if (pSystem) ! 1680: { ! 1681: RemoveObjectsFromSystem (pSystem); ! 1682: } ! 1683: } ! 1684: ! 1685: ! 1686: for (iIndex = 0 ; ! 1687: iIndex < iIndexNum ; ! 1688: iIndex++) ! 1689: { // for all items in the list ! 1690: pLogEntry = LogEntryN (hWndLogEntries, iIndex) ; ! 1691: ! 1692: pSystem = SystemGet (pLog->pSystemFirst, pLogEntry->szComputer); ! 1693: if (pSystem) { ! 1694: AppendObjectToValueList ( ! 1695: pLogEntry->ObjectTitleIndex, ! 1696: pSystem->lpszValue); ! 1697: } ! 1698: } // for ! 1699: ! 1700: return (TRUE) ; ! 1701: } ! 1702: ! 1703: BOOL OpenLog (HWND hWndLog, ! 1704: HANDLE hFile, ! 1705: DWORD dwMajorVersion, ! 1706: DWORD dwMinorVersion, ! 1707: BOOL bLogFile) ! 1708: { ! 1709: PLOG pLog ; ! 1710: DISKLOG DiskLog ; ! 1711: BOOL bSuccess = TRUE ; ! 1712: ! 1713: pLog = LogData (hWndLog) ; ! 1714: if (!pLog) ! 1715: { ! 1716: bSuccess = FALSE ; ! 1717: goto Exit0 ; ! 1718: } ! 1719: ! 1720: if (!FileRead (hFile, &DiskLog, sizeof (DISKLOG))) ! 1721: { ! 1722: bSuccess = FALSE ; ! 1723: goto Exit0 ; ! 1724: } ! 1725: ! 1726: switch (dwMajorVersion) ! 1727: { ! 1728: case (1): ! 1729: ! 1730: SetHourglassCursor() ; ! 1731: ! 1732: ResetLogView (hWndLog) ; ! 1733: ! 1734: OpenLogVer1 (hWndLog, hFile, &DiskLog, pLog, dwMinorVersion) ; ! 1735: ! 1736: // change to log view if we are opening a ! 1737: // log file ! 1738: if (bLogFile && iPerfmonView != IDM_VIEWLOG) ! 1739: { ! 1740: SendMessage (hWndMain, WM_COMMAND, (LONG)IDM_VIEWLOG, 0L) ; ! 1741: } ! 1742: ! 1743: if (iPerfmonView == IDM_VIEWLOG) ! 1744: { ! 1745: SetPerfmonOptions (&DiskLog.perfmonOptions) ; ! 1746: } ! 1747: ! 1748: UpdateLogDisplay (hWndLog) ; ! 1749: ! 1750: SetArrowCursor() ; ! 1751: ! 1752: break ; ! 1753: } ! 1754: ! 1755: Exit0: ! 1756: ! 1757: if (bLogFile) ! 1758: { ! 1759: CloseHandle (hFile) ; ! 1760: } ! 1761: ! 1762: return (bSuccess) ; ! 1763: } // OpenLog ! 1764: ! 1765: ! 1766: BOOL LogCollecting (HWND hWndLog) ! 1767: /* ! 1768: Effect: Return whether the log associated with hWndLog is currently ! 1769: collecting data (writing performance values to disk). ! 1770: */ ! 1771: { // LogCollecting ! 1772: PLOG pLog ; ! 1773: ! 1774: pLog = LogData (hWndLog) ; ! 1775: ! 1776: return (pLog->iStatus == iPMStatusCollecting) ; ! 1777: } // LogCollecting ! 1778: ! 1779: ! 1780: int LogFileSize (HWND hWndLog) ! 1781: { ! 1782: PLOG pLog ; ! 1783: ! 1784: pLog = LogData (hWndLog) ; ! 1785: ! 1786: return (pLog->lFileSize) ; ! 1787: } ! 1788: ! 1789: BOOL LogWriteStartBookmark (HWND hWnd, SYSTEMTIME *pSystemTime) ! 1790: { ! 1791: BOOKMARK Bookmark ; ! 1792: TCHAR NewDataBookmark [MiscTextLen] ; ! 1793: ! 1794: memset (&Bookmark, 0, sizeof (BOOKMARK)) ; ! 1795: ! 1796: NewDataBookmark [0] = TEXT('\0') ; ! 1797: StringLoad (IDS_NEWDATA_BOOKMARK, NewDataBookmark) ; ! 1798: Bookmark.SystemTime = *pSystemTime ; ! 1799: lstrcpy (Bookmark.szComment, NewDataBookmark) ; ! 1800: ! 1801: return (LogWriteBookmarkData (hWndLog, &Bookmark)) ; ! 1802: } ! 1803: ! 1804: BOOL LogWriteBookmarkData (HWND hWnd, PBOOKMARK pBookmark) ! 1805: { ! 1806: PLOG pLog ; ! 1807: LONG lDataOffset ; ! 1808: BOOL WriteOK ; ! 1809: ! 1810: pLog = LogData (hWndLog) ; ! 1811: if (!pLog) ! 1812: return (FALSE) ; ! 1813: ! 1814: lDataOffset = FileTell (pLog->hFile) ; ! 1815: WriteOK = FileWrite (pLog->hFile, pBookmark, sizeof (BOOKMARK)) ; ! 1816: if ( WriteOK ) ! 1817: { ! 1818: pLog->lFileSize += sizeof (BOOKMARK) ; ! 1819: UpdateLogSize (hWndLog) ; ! 1820: ! 1821: WriteOK = LogWriteIndex (pLog, LogFileIndexBookmark, ! 1822: &(pBookmark->SystemTime), ! 1823: lDataOffset, ! 1824: 0) ; ! 1825: } ! 1826: if ( !WriteOK ) ! 1827: { ! 1828: CloseLog (hWndLog, pLog) ; ! 1829: PrepareMenu (GetMenu (hWndMain)) ; ! 1830: UpdateLogDisplay (hWndLog) ; ! 1831: DlgErrorBox (hWndLog, ERR_LOG_FILE, pLog->szFilePath); ! 1832: } ! 1833: } ! 1834: ! 1835: ! 1836: ! 1837: BOOL LogWriteBookmark (HWND hWndLog, ! 1838: LPCTSTR lpszComment) ! 1839: { // LogWriteBookmark ! 1840: BOOKMARK Bookmark ; ! 1841: ! 1842: memset (&Bookmark, 0, sizeof (BOOKMARK)) ; ! 1843: ! 1844: GetLocalTime (&Bookmark.SystemTime) ; ! 1845: lstrcpy (Bookmark.szComment, lpszComment) ; ! 1846: ! 1847: return (LogWriteBookmarkData (hWndLog, &Bookmark)) ; ! 1848: } // LogWriteBookmark ! 1849: ! 1850: ! 1851: BOOL AnyLogLine (void) ! 1852: { // CurrentLogLine ! 1853: int iIndex ; ! 1854: ! 1855: iIndex = LBSelection (hWndLogEntries) ; ! 1856: if (iIndex == LB_ERR) ! 1857: { ! 1858: return (FALSE) ; ! 1859: } ! 1860: else ! 1861: { ! 1862: return (TRUE) ; ! 1863: } ! 1864: } ! 1865: ! 1866: void ResetLogView (HWND hWndLog) ! 1867: { ! 1868: PLOG pLog ; ! 1869: ! 1870: pLog = LogData (hWndLog) ; ! 1871: ! 1872: ChangeSaveFileName (NULL, IDM_VIEWLOG) ; ! 1873: ! 1874: if (pLog && pLog->pSystemFirst) ! 1875: { ! 1876: ResetLog (hWndLog) ; ! 1877: } ! 1878: } // ResetLogView ! 1879: ! 1880: BOOL ResetLog (HWND hWndLog) ! 1881: { ! 1882: int iIndex ; ! 1883: PLOG pLog ; ! 1884: int iEntriesNum ; ! 1885: ! 1886: pLog = LogData (hWndLog) ; ! 1887: ! 1888: if (LogCollecting (hWndLog)) ! 1889: { ! 1890: CloseLog (hWndLog, pLog) ; ! 1891: } ! 1892: ! 1893: LBSetRedraw (hWndLogEntries, FALSE) ; ! 1894: iEntriesNum = LBNumItems (hWndLogEntries) ; ! 1895: ! 1896: // only need to zero out the list head ! 1897: // each item will be deleted by LogDeleteIndex via the listbox ! 1898: pLog->pLogEntryFirst = NULL ; ! 1899: ! 1900: // delete each line ! 1901: for (iIndex = iEntriesNum - 1 ; ! 1902: iIndex >= 0 ; ! 1903: iIndex-- ) ! 1904: { ! 1905: LogDeleteIndex (hWndLogEntries, iIndex) ; ! 1906: } ! 1907: ! 1908: LBSetRedraw (hWndLogEntries, TRUE) ; ! 1909: ! 1910: if (pLog->pSystemFirst) ! 1911: { ! 1912: FreeSystems (pLog->pSystemFirst) ; ! 1913: pLog->pSystemFirst = NULL ; ! 1914: } ! 1915: ! 1916: MemoryFree (pLog->pPerfData) ; ! 1917: MemoryFree (pLog->pLogData) ; ! 1918: ! 1919: pLog->pPerfData = (PPERFDATA) MemoryAllocate (STARTING_SYSINFO_SIZE) ; ! 1920: pLog->pLogData = (PPERFDATA) MemoryAllocate (STARTING_SYSINFO_SIZE) ; ! 1921: ! 1922: LogEntriesChanged (hWndLogEntries) ; ! 1923: ! 1924: pLog->iStatus = iPMStatusClosed ; ! 1925: UpdateLogDisplay (hWndLog) ; ! 1926: ! 1927: return (TRUE) ; ! 1928: } ! 1929: ! 1930: BOOL LogDeleteEntry (HWND hWndLog) ! 1931: { ! 1932: int iIndex ; ! 1933: PLOG pLog ; ! 1934: BOOL retCode ; ! 1935: int iEntriesNum ; ! 1936: ! 1937: pLog = LogData (hWndLog) ; ! 1938: ! 1939: iIndex = LBSelection (hWndLogEntries) ; ! 1940: ! 1941: if (iIndex == LB_ERR) ! 1942: { ! 1943: retCode = FALSE ; ! 1944: } ! 1945: else ! 1946: { ! 1947: // remove the current selection ! 1948: LogDeleteIndex (hWndLogEntries, iIndex) ; ! 1949: ! 1950: iEntriesNum = LBNumItems (hWndLogEntries) ; ! 1951: ! 1952: if (iEntriesNum == 0 || iEntriesNum == LB_ERR) ! 1953: { ! 1954: // delete the last line or something bad happened, ! 1955: // then reset the window. ! 1956: ResetLog (hWndLog) ; ! 1957: } ! 1958: else ! 1959: { ! 1960: // set selection on the item above the deleted item. ! 1961: iIndex-- ; ! 1962: if (iIndex < 0) ! 1963: { ! 1964: iIndex = 0 ; ! 1965: } ! 1966: LBSetSelection (hWndLogEntries, iIndex) ; ! 1967: LBSetVisible (hWndLogEntries, iIndex) ; ! 1968: } ! 1969: ! 1970: LogEntriesChanged (hWndLogEntries) ; ! 1971: retCode = TRUE ; ! 1972: } ! 1973: return (retCode) ; ! 1974: } ! 1975: ! 1976: ! 1977: void ExportLog (void) ! 1978: { ! 1979: HANDLE hFile ; ! 1980: PLOG pLog ; ! 1981: PLOGENTRY pLogEntry ; ! 1982: int iIndex ; ! 1983: int iIndexNum ; ! 1984: CHAR TempBuff [LongTextLen] ; ! 1985: TCHAR UnicodeBuff [LongTextLen] ; ! 1986: TCHAR UnicodeBuff1 [MiscTextLen] ; ! 1987: int StringLen ; ! 1988: LPTSTR pFileName = NULL ; ! 1989: INT ErrCode = 0 ; ! 1990: ! 1991: if (!(pLog = LogData (hWndLog))) ! 1992: { ! 1993: return ; ! 1994: } ! 1995: ! 1996: // see if there is anything to export.. ! 1997: iIndexNum = LBNumItems (hWndLogEntries) ; ! 1998: if (iIndexNum == 0 || iIndexNum == LB_ERR) ! 1999: { ! 2000: return ; ! 2001: } ! 2002: ! 2003: if (!FileGetName (hWndLog, IDS_EXPORTFILE, UnicodeBuff)) ! 2004: { ! 2005: // user cancel ! 2006: return ; ! 2007: } ! 2008: ! 2009: pFileName = StringAllocate (UnicodeBuff) ; ! 2010: ! 2011: // open the file.. ! 2012: if (!(hFile = FileHandleCreate (UnicodeBuff))) ! 2013: { ! 2014: // can't open the file ! 2015: ErrCode = ERR_CANT_OPEN ; ! 2016: return ; ! 2017: } ! 2018: ! 2019: ! 2020: SetHourglassCursor() ; ! 2021: ! 2022: // get header ! 2023: StringLoad (IDS_REPORT_HEADER, UnicodeBuff) ; ! 2024: ConvertUnicodeStr (TempBuff, UnicodeBuff) ; ! 2025: StringLen = strlen (TempBuff) ; ! 2026: ConvertUnicodeStr (&TempBuff[StringLen], LocalComputerName) ; ! 2027: strcat (TempBuff, LineEndStr) ; ! 2028: ! 2029: if (!FileWrite (hFile, TempBuff, strlen(TempBuff))) ! 2030: { ! 2031: ErrCode = ERR_EXPORT_FILE ; ! 2032: goto Exit0 ; ! 2033: } ! 2034: ! 2035: if (!(strempty(pLog->szFilePath))) ! 2036: { ! 2037: // export filename is there is one ! 2038: StringLoad (IDS_REPORT_LOGFILE, UnicodeBuff) ; ! 2039: ConvertUnicodeStr (TempBuff, UnicodeBuff) ; ! 2040: StringLen = strlen (TempBuff) ; ! 2041: ConvertUnicodeStr (&TempBuff[StringLen], pLog->szFilePath) ; ! 2042: strcat (TempBuff, LineEndStr) ; ! 2043: ! 2044: if (!FileWrite (hFile, TempBuff, strlen(TempBuff))) ! 2045: { ! 2046: ErrCode = ERR_EXPORT_FILE ; ! 2047: goto Exit0 ; ! 2048: } ! 2049: } ! 2050: ! 2051: // export interval ! 2052: StringLoad (IDS_CHARTINT_FORMAT, UnicodeBuff1) ; ! 2053: TSPRINTF (UnicodeBuff, UnicodeBuff1, ! 2054: (FLOAT) pLog->iIntervalMSecs / (FLOAT) 1000.0) ; ! 2055: ConvertUnicodeStr (TempBuff, UnicodeBuff) ; ! 2056: strcat (TempBuff, LineEndStr) ; ! 2057: strcat (TempBuff, LineEndStr) ; ! 2058: ! 2059: if (!FileWrite (hFile, TempBuff, strlen(TempBuff))) ! 2060: { ! 2061: ErrCode = ERR_EXPORT_FILE ; ! 2062: goto Exit0 ; ! 2063: } ! 2064: ! 2065: // export Labels ! 2066: StringLoad (IDS_LABELOBJECT, UnicodeBuff) ; ! 2067: ConvertUnicodeStr (TempBuff, UnicodeBuff) ; ! 2068: strcat (TempBuff, pDelimiter) ; ! 2069: ! 2070: if (!FileWrite (hFile, TempBuff, strlen(TempBuff))) ! 2071: { ! 2072: ErrCode = ERR_EXPORT_FILE ; ! 2073: goto Exit0 ; ! 2074: } ! 2075: ! 2076: StringLoad (IDS_LABELSYSTEM, UnicodeBuff) ; ! 2077: ConvertUnicodeStr (TempBuff, UnicodeBuff) ; ! 2078: strcat (TempBuff, LineEndStr) ; ! 2079: ! 2080: if (!FileWrite (hFile, TempBuff, strlen(TempBuff))) ! 2081: { ! 2082: ErrCode = ERR_EXPORT_FILE ; ! 2083: goto Exit0 ; ! 2084: } ! 2085: ! 2086: ! 2087: // export each counter ! 2088: for (iIndex = 0 ; iIndex < iIndexNum ; iIndex++) ! 2089: { // for ! 2090: ! 2091: pLogEntry = LogEntryN (hWndLogEntries, iIndex) ; ! 2092: ! 2093: if (!pLogEntry || pLogEntry == (PLOGENTRY)LB_ERR) ! 2094: { ! 2095: continue ; ! 2096: } ! 2097: ! 2098: ConvertUnicodeStr (TempBuff, pLogEntry->szObject) ; ! 2099: strcat (TempBuff, pDelimiter) ; ! 2100: ! 2101: if (!FileWrite (hFile, TempBuff, strlen(TempBuff))) ! 2102: { ! 2103: ErrCode = ERR_EXPORT_FILE ; ! 2104: break ; ! 2105: } ! 2106: ! 2107: ConvertUnicodeStr (TempBuff, pLogEntry->szComputer) ; ! 2108: strcat (TempBuff, LineEndStr) ; ! 2109: ! 2110: if (!FileWrite (hFile, TempBuff, strlen(TempBuff))) ! 2111: { ! 2112: ErrCode = ERR_EXPORT_FILE ; ! 2113: break ; ! 2114: } ! 2115: } ! 2116: ! 2117: Exit0: ! 2118: ! 2119: SetArrowCursor() ; ! 2120: CloseHandle (hFile) ; ! 2121: ! 2122: if (pFileName) ! 2123: { ! 2124: if (ErrCode) ! 2125: { ! 2126: DlgErrorBox (hWndGraph, ErrCode, pFileName) ; ! 2127: } ! 2128: MemoryFree (pFileName) ; ! 2129: } ! 2130: ! 2131: } // ExportLog ! 2132: ! 2133: ! 2134: LPTSTR MatchSystemCounters (LPTSTR pBaseSysCounter, ! 2135: long lBaseSysSize, ! 2136: LPTSTR pSysCounter, ! 2137: long lSysSize, ! 2138: long *pMatchPortion) ! 2139: { ! 2140: LPTSTR pNotMatch = NULL ; ! 2141: long i, lSizeToCompare ; ! 2142: ! 2143: *pMatchPortion = 0 ; ! 2144: lSizeToCompare = min (lBaseSysSize, lSysSize) / sizeof (TCHAR) ; ! 2145: ! 2146: for (i = 0 ; i < lSizeToCompare ; i++, pBaseSysCounter++, pSysCounter++) ! 2147: { ! 2148: if (*pBaseSysCounter != *pSysCounter) ! 2149: { ! 2150: pNotMatch = pSysCounter ; ! 2151: break ; ! 2152: } ! 2153: } ! 2154: ! 2155: if (pNotMatch == NULL) ! 2156: { ! 2157: if (lBaseSysSize < lSysSize) ! 2158: { ! 2159: // the new system has longer counter names than base system ! 2160: // setup the extra portion. ! 2161: pNotMatch = pSysCounter ; ! 2162: } ! 2163: else ! 2164: { ! 2165: // new system counter name is shorter than or equal to ! 2166: // the base system counter names ! 2167: *pMatchPortion = lSysSize ; ! 2168: } ! 2169: } ! 2170: ! 2171: return (pNotMatch) ; ! 2172: ! 2173: } ! 2174: ! 2175: void LogWriteSystemCounterNames (HWND hWnd, PLOG pLog) ! 2176: { ! 2177: long dwArraySize ; ! 2178: PPERFSYSTEM pSystem = pLog->pSystemFirst ; ! 2179: LPTSTR pMatchLen ; ! 2180: LPTSTR pCounterName ; ! 2181: long lMatchLen, lMatchPortion ; ! 2182: ! 2183: for (pSystem = pLog->pSystemFirst ; ! 2184: pSystem ; ! 2185: pSystem = pSystem->pSystemNext) ! 2186: { ! 2187: if (pSystem->bSystemCounterNameSaved == TRUE) ! 2188: { ! 2189: // we have wrote out the counter name for ! 2190: // this system, skip it then. ! 2191: continue ; ! 2192: } ! 2193: ! 2194: dwArraySize = (pSystem->CounterInfo.dwLastId + 1 ) ; ! 2195: ! 2196: if (!pLog->lBaseCounterNameOffset) ! 2197: { ! 2198: LogWriteCounterName (hWnd, pSystem, pLog, ! 2199: (LPTSTR)(pSystem->CounterInfo.TextString + dwArraySize), ! 2200: 0, ! 2201: pSystem->CounterInfo.dwCounterSize, ! 2202: 0 ) ; ! 2203: } ! 2204: else ! 2205: { ! 2206: // check for matched characters between this system and the ! 2207: // base system ! 2208: pCounterName = (LPTSTR)(pSystem->CounterInfo.TextString + dwArraySize) ; ! 2209: pMatchLen = MatchSystemCounters (pLog->pBaseCounterName, ! 2210: pLog->lBaseCounterNameSize, ! 2211: pCounterName, ! 2212: pSystem->CounterInfo.dwCounterSize, ! 2213: &lMatchPortion) ; ! 2214: ! 2215: if (pMatchLen) ! 2216: { ! 2217: // This system matches part of the base system ! 2218: // (all if it has more names) ! 2219: lMatchLen = (long) (pMatchLen - pCounterName) * sizeof (TCHAR) ; ! 2220: LogWriteCounterName (hWnd, pSystem, pLog, ! 2221: pMatchLen, ! 2222: lMatchLen, ! 2223: pSystem->CounterInfo.dwCounterSize - lMatchLen, ! 2224: 0 ) ; ! 2225: } ! 2226: else ! 2227: { ! 2228: // This system matches the based system ! 2229: LogWriteCounterName (hWnd, pSystem, pLog, ! 2230: NULL, ! 2231: lMatchPortion, ! 2232: 0, ! 2233: 0 ) ; ! 2234: } ! 2235: } ! 2236: } ! 2237: } // LogWriteSystemCounterNames ! 2238: ! 2239: ! 2240: BOOL LogWriteCounterName (HWND hWnd, ! 2241: PPERFSYSTEM pSystem, ! 2242: PLOG pLog, ! 2243: LPTSTR pCounterName, ! 2244: long sizeMatched, ! 2245: long sizeOfData, ! 2246: BOOL bBaseCounterName) ! 2247: { ! 2248: BOOL ReadOK ; ! 2249: BOOL WriteOK ; ! 2250: SYSTEMTIME SystemTime ; ! 2251: LOGFILECOUNTERNAME CounterNameRecord ; ! 2252: LOGHEADER LogFileHeader ; ! 2253: long lDataOffset, lCurPosition ; ! 2254: TCHAR Dummy [sizeof(DWORD)] ; ! 2255: int PatchBytes ; ! 2256: ! 2257: if (pSystem->bSystemCounterNameSaved == TRUE) ! 2258: return FALSE ; ! 2259: ! 2260: GetLocalTime (&SystemTime) ; ! 2261: ! 2262: lCurPosition = FileTell (pLog->hFile) ; ! 2263: ! 2264: lstrcpy (CounterNameRecord.szComputer, pSystem->sysName) ; ! 2265: CounterNameRecord.lBaseCounterNameOffset = pLog->lBaseCounterNameOffset ; ! 2266: CounterNameRecord.lCurrentCounterNameOffset = ! 2267: lCurPosition + sizeof (LOGFILECOUNTERNAME) ; ! 2268: CounterNameRecord.lMatchLength = sizeMatched ; ! 2269: CounterNameRecord.lUnmatchCounterNames = sizeOfData ; ! 2270: CounterNameRecord.dwLastCounterId = pSystem->CounterInfo.dwLastId ; ! 2271: CounterNameRecord.dwLangId = pSystem->CounterInfo.dwLangId ; ! 2272: WriteOK = FileWrite (pLog->hFile, &CounterNameRecord, ! 2273: sizeof (CounterNameRecord)) ; ! 2274: ! 2275: if (WriteOK) ! 2276: { ! 2277: pLog->lFileSize += sizeof (LOGFILECOUNTERNAME) ; ! 2278: ! 2279: if (sizeOfData) ! 2280: { ! 2281: ! 2282: WriteOK = FileWrite (pLog->hFile, pCounterName, sizeOfData) ; ! 2283: ! 2284: if (WriteOK && (PatchBytes = sizeOfData % sizeof(DWORD)) > 0) ! 2285: { ! 2286: // ensure the file is in DWORD boundary. ! 2287: WriteOK = FileWrite (pLog->hFile, Dummy, PatchBytes) ; ! 2288: } ! 2289: ! 2290: if (WriteOK) ! 2291: { ! 2292: pLog->lFileSize += sizeOfData + PatchBytes ; ! 2293: ! 2294: if (!pLog->lBaseCounterNameOffset) ! 2295: { ! 2296: // this is the first counter name data block ! 2297: // then update the log file header ! 2298: lDataOffset = FileTell (pLog->hFile) ; ! 2299: ! 2300: FileSeekBegin (pLog->hFile, 0L) ; ! 2301: ! 2302: ReadOK = FileRead (pLog->hFile, ! 2303: &LogFileHeader, ! 2304: sizeof (LogFileHeader)) ; ! 2305: ! 2306: if (ReadOK) ! 2307: { ! 2308: LogFileHeader.lBaseCounterNameOffset = lCurPosition ; ! 2309: FileSeekBegin (pLog->hFile, 0L) ; ! 2310: WriteOK = FileWrite (pLog->hFile, ! 2311: &LogFileHeader, ! 2312: sizeof (LogFileHeader)) ; ! 2313: } ! 2314: else ! 2315: { ! 2316: // flag an error ! 2317: WriteOK = FALSE ; ! 2318: } ! 2319: ! 2320: // retore back to current file position ! 2321: FileSeekBegin (pLog->hFile, lDataOffset) ; ! 2322: ! 2323: if (ReadOK && WriteOK) ! 2324: { ! 2325: // allocate memory to save the base system counter names ! 2326: if (pLog->pBaseCounterName) ! 2327: { ! 2328: MemoryFree (pLog->pBaseCounterName) ; ! 2329: } ! 2330: if (pLog->pBaseCounterName = MemoryAllocate (sizeOfData)) ! 2331: { ! 2332: memcpy (pLog->pBaseCounterName, ! 2333: pCounterName, ! 2334: sizeOfData) ; ! 2335: pLog->lBaseCounterNameOffset = lCurPosition ; ! 2336: pLog->lBaseCounterNameSize = sizeOfData ; ! 2337: } ! 2338: } ! 2339: } // if (!pLog->lBaseCounterNameOffset) ! 2340: } ! 2341: } // if (sizeOfData) ! 2342: } ! 2343: ! 2344: if ( WriteOK ) ! 2345: { ! 2346: WriteOK = LogWriteIndex (pLog, LogFileIndexCounterName, ! 2347: &SystemTime, ! 2348: lCurPosition, ! 2349: 0) ; ! 2350: } ! 2351: ! 2352: if ( !WriteOK ) ! 2353: { ! 2354: CloseLog (hWndLog, pLog) ; ! 2355: PrepareMenu (GetMenu (hWndMain)) ; ! 2356: UpdateLogDisplay (hWndLog) ; ! 2357: DlgErrorBox (hWndLog, ERR_LOG_FILE, pLog->szFilePath); ! 2358: } ! 2359: else ! 2360: { ! 2361: UpdateLogSize (hWnd) ; ! 2362: pSystem->bSystemCounterNameSaved = TRUE ; ! 2363: } ! 2364: ! 2365: return (TRUE) ; ! 2366: } ! 2367: ! 2368:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.