Annotation of mstools/samples/sdktools/perfmon/log.c, revision 1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.