Annotation of mstools/samples/sdktools/perfmon/log.c, revision 1.1.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.