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

1.1     ! root        1: //==========================================================================//
        !             2: //                                  Includes                                //
        !             3: //==========================================================================//
        !             4: 
        !             5: 
        !             6: #include <string.h>     // strupr
        !             7: #include <stdio.h>   // for sprintf.
        !             8: #include <stdlib.h>   // for wcstoul.
        !             9: #include "perfmon.h"
        !            10: #include "utils.h"
        !            11: 
        !            12: #include "pmemory.h"        // for MemoryXXX (mallloc-type) routines
        !            13: #include "playback.h"   // for PlayingBackLog
        !            14: #include "perfdata.h"   // external declarations for this file
        !            15: #include "system.h"     // for DeleteUnusedSystems
        !            16: 
        !            17: //==========================================================================//
        !            18: //                                  Constants                               //
        !            19: //==========================================================================//
        !            20: 
        !            21: const LPWSTR NamesKey = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib";
        !            22: const LPWSTR Counters = L"Counters";
        !            23: const LPWSTR Help = L"Help";
        !            24: const LPWSTR LastHelp = L"Last Help";
        !            25: const LPWSTR LastCounter = L"Last Counter";
        !            26: const LPWSTR Slash = L"\\";
        !            27: 
        !            28: #define szPerfSubkey      (NULL)
        !            29: WCHAR   NULL_NAME[] = L" ";
        !            30: #define RESERVED    0L
        !            31: 
        !            32: TCHAR          DefaultLangId[10] ;
        !            33: TCHAR          EnglishLangId[10] ;
        !            34: 
        !            35: //==========================================================================//
        !            36: //                                   Macros                                 //
        !            37: //==========================================================================//
        !            38: 
        !            39: 
        !            40: 
        !            41: //==========================================================================//
        !            42: //                                Local Data                                //
        !            43: //==========================================================================//
        !            44: 
        !            45: 
        !            46: // When the conversion of this code is complete, this will be the *only*
        !            47: // allocated copy of the performance data.  It will monotonically grow
        !            48: // to hold the largest of the system's performance data.
        !            49: 
        !            50: PPERFDATA      pPerfData ;
        !            51: 
        !            52: //==========================================================================//
        !            53: //                              Local Functions                             //
        !            54: //==========================================================================//
        !            55: 
        !            56: NTSTATUS  AddNamesToArray (LPTSTR pNames,
        !            57:    DWORD    dwLastID,
        !            58:    LPWSTR   *lpCounterId) ;
        !            59: 
        !            60: //======================================//
        !            61: // Object Accessors                     //
        !            62: //======================================//
        !            63: 
        !            64: #if 0
        !            65: PPERFOBJECT FirstObject (PPERFDATA pPerfData)
        !            66:    {
        !            67:    return ((PPERFOBJECT) ((PBYTE) pPerfData + pPerfData->HeaderLength)) ;
        !            68:    }
        !            69: 
        !            70: 
        !            71: PPERFOBJECT NextObject (PPERFOBJECT pObject)
        !            72:    {  // NextObject
        !            73:    return ((PPERFOBJECT) ((PBYTE) pObject + pObject->TotalByteLength)) ;
        !            74:    }  // NextObject
        !            75: #endif
        !            76: 
        !            77: void ObjectName (PPERFSYSTEM pSystem,
        !            78:                  PPERFOBJECT pObject, 
        !            79:                  LPTSTR lpszName, 
        !            80:                  int iLen)
        !            81:    {  // ObjectName
        !            82:    strclr (lpszName) ;
        !            83:    QueryPerformanceName (pSystem, 
        !            84:                          pObject->ObjectNameTitleIndex, 
        !            85:                          0, iLen, lpszName, FALSE) ;
        !            86:    }  // ObjectName
        !            87: 
        !            88: 
        !            89: 
        !            90: //======================================//
        !            91: // Counter Accessors                    //
        !            92: //======================================//
        !            93: 
        !            94: #if 0
        !            95: PERF_COUNTER_DEFINITION *
        !            96: FirstCounter(
        !            97:     PERF_OBJECT_TYPE *pObjectDef)
        !            98: {
        !            99:     return (PERF_COUNTER_DEFINITION *)
        !           100:                ((PCHAR) pObjectDef + pObjectDef->HeaderLength);
        !           101: }
        !           102: 
        !           103: 
        !           104: PERF_COUNTER_DEFINITION *
        !           105: NextCounter(
        !           106:     PERF_COUNTER_DEFINITION *pCounterDef)
        !           107: {
        !           108:     return (PERF_COUNTER_DEFINITION *)
        !           109:                ((PCHAR) pCounterDef + pCounterDef->ByteLength);
        !           110: }
        !           111: #endif
        !           112: 
        !           113: PERF_INSTANCE_DEFINITION *
        !           114: FirstInstance(
        !           115:     PERF_OBJECT_TYPE *pObjectDef)
        !           116: {
        !           117:     return (PERF_INSTANCE_DEFINITION *)
        !           118:                ((PCHAR) pObjectDef + pObjectDef->DefinitionLength);
        !           119: }
        !           120: 
        !           121: 
        !           122: PERF_INSTANCE_DEFINITION *
        !           123: NextInstance(
        !           124:     PERF_INSTANCE_DEFINITION *pInstDef)
        !           125: {
        !           126:     PERF_COUNTER_BLOCK *pCounterBlock;
        !           127: 
        !           128:     pCounterBlock = (PERF_COUNTER_BLOCK *)
        !           129:                         ((PCHAR) pInstDef + pInstDef->ByteLength);
        !           130: 
        !           131:     return (PERF_INSTANCE_DEFINITION *)
        !           132:                ((PCHAR) pCounterBlock + pCounterBlock->ByteLength);
        !           133: }
        !           134: 
        !           135: 
        !           136: 
        !           137: // FIXFIX: The next should just be UNICODE, but for now, fake it
        !           138: 
        !           139: LPTSTR
        !           140: InstanceName(
        !           141: PERF_INSTANCE_DEFINITION *pInstDef)
        !           142: {
        !           143:     return (LPTSTR) ((PCHAR) pInstDef + pInstDef->NameOffset);
        !           144: }
        !           145: 
        !           146: 
        !           147: // FIXFIX: This next routine should just be Unicode.  This is *ugly*.
        !           148: //         It is required since remote data is unicode, local is not.
        !           149: 
        !           150: void
        !           151: GetInstanceName (PPERFINSTANCEDEF pInstance,
        !           152:                  LPTSTR lpszInstance)
        !           153:    {
        !           154:    LPSTR pSource;
        !           155: 
        !           156:    pSource = (LPSTR) InstanceName(pInstance) ;
        !           157: 
        !           158:    if (pSource[1] == '\0' && pSource[2] != '\0')
        !           159:       {
        !           160:       // Must be a multi-character Unicode string
        !           161: #ifdef UNICODE
        !           162:       wcsncpy ((LPTSTR)lpszInstance,
        !           163:                (LPTSTR) pSource,
        !           164:                pInstance->NameLength);
        !           165: #else
        !           166:       wcstombs((LPTSTR)lpszInstance,
        !           167:                (LPWSTR) pSource,
        !           168:                pInstance->NameLength/sizeof(WCHAR));
        !           169: #endif
        !           170:       }
        !           171:    else
        !           172:       {
        !           173:       // Must be ANSI (or a single Unicode character)
        !           174: #ifdef UNICODE
        !           175:       mbstowcs (lpszInstance,
        !           176:                 pSource,
        !           177:                 pInstance->NameLength);
        !           178: #else
        !           179:       strcpy (lpszInstance,
        !           180:                (LPSTR) pInstance + pInstance->NameOffset) ;
        !           181: #endif
        !           182:       }
        !           183:    }
        !           184: 
        !           185: 
        !           186: void
        !           187: GetPerfComputerName(PPERFDATA pPerfData,
        !           188:                     LPTSTR lpszComputerName)
        !           189:    {
        !           190:    lstrcpy(lpszComputerName, szComputerPrefix) ;
        !           191:    if (pPerfData)
        !           192:       {
        !           193: #ifdef UNICODE
        !           194:       wcsncpy (&lpszComputerName[2],
        !           195:                (LPWSTR)((PBYTE) pPerfData + pPerfData->SystemNameOffset),
        !           196:                pPerfData->SystemNameLength/sizeof(WCHAR)) ;
        !           197: #else
        !           198:       wcstombs((LPSTR)&lpszComputerName[2],
        !           199:                (LPWSTR)((PBYTE) pPerfData + pPerfData->SystemNameOffset),
        !           200:                pPerfData->SystemNameLength/sizeof(WCHAR)) ;
        !           201: #endif
        !           202:       }
        !           203:    else
        !           204:       {
        !           205:       lpszComputerName[0] = TEXT('\0') ;
        !           206:       }
        !           207:    }
        !           208: 
        !           209: 
        !           210: //==========================================================================//
        !           211: //                             Exported Functions                           //
        !           212: //==========================================================================//
        !           213: 
        !           214: 
        !           215: int CounterIndex (PPERFCOUNTERDEF pCounterToFind,
        !           216:                   PPERFOBJECT pObject)
        !           217: /*
        !           218:    Effect:        Return the index ("counter number") of pCounterToFind
        !           219:                   within pObject. If the counter doesnt belong to pObject,
        !           220:                   return -1.
        !           221: */
        !           222:    {  // CounterIndex
        !           223:    PPERFCOUNTERDEF   pCounter ;
        !           224:    UINT              iCounter ;
        !           225: 
        !           226:    for (iCounter = 0, pCounter = FirstCounter (pObject) ;
        !           227:         iCounter < pObject->NumCounters ;
        !           228:         iCounter++, pCounter = NextCounter (pCounter))
        !           229:       {  // for
        !           230:       if (pCounter->CounterNameTitleIndex == 
        !           231:           pCounterToFind->CounterNameTitleIndex)
        !           232:          return (iCounter) ;
        !           233:       }  // for
        !           234: 
        !           235:    return (-1) ;
        !           236:    }  // CounterIndex
        !           237: 
        !           238: 
        !           239: HKEY
        !           240: OpenSystemPerfData (
        !           241:     IN LPCTSTR lpszSystem
        !           242: )
        !           243: {  // OpenSystemPerfData
        !           244: 
        !           245:     HKEY    hKey ;
        !           246:     LONG    lStatus;
        !           247:     LPWSTR  lpSubKey;
        !           248: 
        !           249:     lpSubKey = L" ";
        !           250: 
        !           251:     lStatus = ERROR_CANTOPEN;   // default error if none is returned
        !           252: 
        !           253:     if (IsLocalComputer(lpszSystem) || PlayingBackLog()) {
        !           254:         SetLastError (ERROR_SUCCESS);
        !           255:         return HKEY_PERFORMANCE_DATA;
        !           256:     } else {
        !           257:         // Must be a remote system
        !           258:         try {
        !           259:             lStatus = RegConnectRegistry (
        !           260:                 (LPTSTR)lpszSystem,
        !           261:                 HKEY_PERFORMANCE_DATA,
        !           262:                 &hKey);
        !           263:         } finally {
        !           264:             if (lStatus != ERROR_SUCCESS) {
        !           265:                 SetLastError (lStatus);
        !           266:                 hKey = NULL;
        !           267:             }
        !           268:         }
        !           269:     }
        !           270:     return (hKey);
        !           271: 
        !           272: }  // OpenSystemPerfData
        !           273: 
        !           274: 
        !           275: LPWSTR
        !           276: *BuildNameTable(
        !           277:     HKEY          hKeyRegistry,   // handle to registry db with counter names
        !           278:     LPWSTR        lpszLangId,     // unicode value of Language subkey
        !           279:     PCOUNTERTEXT  pCounterInfo,
        !           280:     LANGID        iLangId         // lang ID of the lpszLangId
        !           281: )
        !           282: /*++
        !           283:    
        !           284: BuildNameTable
        !           285: 
        !           286: Arguments:
        !           287: 
        !           288:     hKeyRegistry
        !           289:             Handle to an open registry (this can be local or remote.) and
        !           290:             is the value returned by RegConnectRegistry or a default key.
        !           291: 
        !           292:     lpszLangId
        !           293:             The unicode id of the language to look up. (English is 0x409)
        !           294: 
        !           295: Return Value:
        !           296:      
        !           297:     pointer to an allocated table. (the caller must free it when finished!)
        !           298:     the table is an array of pointers to zero terminated strings. NULL is
        !           299:     returned if an error occured.
        !           300: 
        !           301: --*/
        !           302: {
        !           303: 
        !           304:     LPWSTR  *lpReturnValue;
        !           305: 
        !           306:     LPWSTR  *lpCounterId;
        !           307:     LPWSTR  lpCounterNames;
        !           308:     LPWSTR  lpHelpText;
        !           309: 
        !           310: 
        !           311:     LONG    lWin32Status;
        !           312:     DWORD   dwLastError;
        !           313:     DWORD   dwValueType;
        !           314:     DWORD   dwArraySize;
        !           315:     DWORD   dwBufferSize;
        !           316:     DWORD   dwCounterSize;
        !           317:     DWORD   dwHelpSize;
        !           318:     
        !           319:     NTSTATUS    Status;
        !           320: 
        !           321:     DWORD   dwLastHelp;
        !           322:     DWORD   dwLastCounter;
        !           323:     DWORD   dwLastId;
        !           324:     
        !           325:     HKEY    hKeyValue;
        !           326:     HKEY    hKeyNames;
        !           327:     
        !           328:     TCHAR   tempBuffer [LongTextLen] ;
        !           329:     TCHAR   subLangId [10] ;
        !           330: 
        !           331:     LPWSTR  lpValueNameString;
        !           332:     LANGID  LangIdUsed = iLangId;
        !           333: 
        !           334:     //initialize local variables
        !           335:     lpReturnValue = NULL;
        !           336:     hKeyValue = NULL;
        !           337:     hKeyNames = NULL;
        !           338: 
        !           339:     // check for null arguments and insert defaults if necessary
        !           340: 
        !           341:     if (!lpszLangId) {
        !           342:         lpszLangId = DefaultLangId;
        !           343:         LangIdUsed = iLanguage ;
        !           344:     }
        !           345: 
        !           346:     // open registry to get number of items for computing array size
        !           347: 
        !           348:     lWin32Status = RegOpenKeyEx (
        !           349:         hKeyRegistry,
        !           350:         NamesKey,
        !           351:         RESERVED,
        !           352:         KEY_READ,
        !           353:         &hKeyValue);
        !           354:     
        !           355:     if (lWin32Status != ERROR_SUCCESS) {
        !           356:         goto BNT_BAILOUT;
        !           357:     }
        !           358: 
        !           359:     // get number of items
        !           360:     
        !           361:     dwBufferSize = sizeof (dwLastHelp);
        !           362:     lWin32Status = RegQueryValueEx (
        !           363:         hKeyValue,
        !           364:         LastHelp,
        !           365:         RESERVED,
        !           366:         &dwValueType,
        !           367:         (LPBYTE)&dwLastHelp,
        !           368:         &dwBufferSize);
        !           369: 
        !           370:     if ((lWin32Status != ERROR_SUCCESS) || (dwValueType != REG_DWORD)) {
        !           371:         goto BNT_BAILOUT;
        !           372:     }
        !           373: 
        !           374:     dwBufferSize = sizeof (dwLastCounter);
        !           375:     lWin32Status = RegQueryValueEx (
        !           376:         hKeyValue,
        !           377:         LastCounter,
        !           378:         RESERVED,
        !           379:         &dwValueType,
        !           380:         (LPBYTE)&dwLastCounter,
        !           381:         &dwBufferSize);
        !           382: 
        !           383:     if ((lWin32Status != ERROR_SUCCESS) || (dwValueType != REG_DWORD)) {
        !           384:         goto BNT_BAILOUT;
        !           385:     }
        !           386: 
        !           387:     if (dwLastCounter >= dwLastHelp) {
        !           388:         dwLastId = dwLastCounter;
        !           389:     } else {
        !           390:         dwLastId = dwLastHelp;
        !           391:     }
        !           392: 
        !           393:     dwArraySize = (dwLastId + 1 ) * sizeof(LPWSTR);
        !           394: 
        !           395:     // get size of string buffer
        !           396:     lpValueNameString = tempBuffer ;
        !           397: 
        !           398:     lstrcpy (lpValueNameString, NamesKey);
        !           399:     lstrcat (lpValueNameString, Slash);
        !           400:     lstrcat (lpValueNameString, lpszLangId);
        !           401: 
        !           402:     lWin32Status = RegOpenKeyEx (
        !           403:         hKeyRegistry,
        !           404:         lpValueNameString,
        !           405:         RESERVED,
        !           406:         KEY_READ,
        !           407:         &hKeyNames);
        !           408: 
        !           409:     if (lWin32Status != ERROR_SUCCESS) {
        !           410:         // try take out the country ID
        !           411:         LangIdUsed = MAKELANGID (LangIdUsed & 0x0ff, LANG_NEUTRAL);
        !           412:         TSPRINTF (subLangId, TEXT("%03x"), LangIdUsed);
        !           413:         lstrcpy (lpValueNameString, NamesKey);
        !           414:         lstrcat (lpValueNameString, Slash);
        !           415:         lstrcat (lpValueNameString, subLangId);
        !           416: 
        !           417:         lWin32Status = RegOpenKeyEx (
        !           418:                 hKeyRegistry,
        !           419:                 lpValueNameString,
        !           420:                 RESERVED,
        !           421:                 KEY_READ,
        !           422:                 &hKeyNames);
        !           423:     }
        !           424: 
        !           425:     if (lWin32Status != ERROR_SUCCESS) {
        !           426:         // try the EnglishLangId 
        !           427:         if (!strsame(EnglishLangId, subLangId)) {
        !           428: 
        !           429:             lstrcpy (lpValueNameString, NamesKey);
        !           430:             lstrcat (lpValueNameString, Slash);
        !           431:             lstrcat (lpValueNameString, EnglishLangId);
        !           432: 
        !           433:             LangIdUsed = iEnglishLanguage ;
        !           434: 
        !           435:             lWin32Status = RegOpenKeyEx (
        !           436:                 hKeyRegistry,
        !           437:                 lpValueNameString,
        !           438:                 RESERVED,
        !           439:                 KEY_READ,
        !           440:                 &hKeyNames);
        !           441:         }
        !           442:     }
        !           443: 
        !           444:     // Fail, too bad...
        !           445:     if (lWin32Status != ERROR_SUCCESS) {
        !           446:         goto BNT_BAILOUT;
        !           447:     }
        !           448: 
        !           449:     // get size of counter names and add that to the arrays
        !           450:     
        !           451: 
        !           452:     dwBufferSize = 0;
        !           453:     lWin32Status = RegQueryValueEx (
        !           454:         hKeyNames,
        !           455:         Counters,
        !           456:         RESERVED,
        !           457:         &dwValueType,
        !           458:         NULL,
        !           459:         &dwBufferSize);
        !           460: 
        !           461:     if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT;
        !           462: 
        !           463:     dwCounterSize = dwBufferSize;
        !           464: 
        !           465:     // If ExplainText is needed, then
        !           466:     // get size of help text and add that to the arrays
        !           467:     
        !           468:     if (bExplainTextButtonHit) {
        !           469:         dwBufferSize = 0;
        !           470:         lWin32Status = RegQueryValueEx (
        !           471:               hKeyNames,
        !           472:               Help,
        !           473:               RESERVED,
        !           474:               &dwValueType,
        !           475:               NULL,
        !           476:               &dwBufferSize);
        !           477: 
        !           478:         if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT;
        !           479:    
        !           480:         dwHelpSize = dwBufferSize;
        !           481:      } else {
        !           482:         dwHelpSize = 0;
        !           483:      }
        !           484: 
        !           485:     lpReturnValue = MemoryAllocate (dwArraySize + dwCounterSize + dwHelpSize);
        !           486: 
        !           487:     if (!lpReturnValue) goto BNT_BAILOUT;
        !           488: 
        !           489:     // initialize pointers into buffer
        !           490: 
        !           491:     lpCounterId = lpReturnValue;
        !           492:     lpCounterNames = (LPWSTR)((LPBYTE)lpCounterId + dwArraySize);
        !           493:     lpHelpText = (LPWSTR)((LPBYTE)lpCounterNames + dwCounterSize);
        !           494: 
        !           495:     // read counters into memory
        !           496: 
        !           497:     dwBufferSize = dwCounterSize;
        !           498:     lWin32Status = RegQueryValueEx (
        !           499:         hKeyNames,
        !           500:         Counters,
        !           501:         RESERVED,
        !           502:         &dwValueType,
        !           503:         (LPVOID)lpCounterNames,
        !           504:         &dwBufferSize);
        !           505: 
        !           506:     if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT;
        !           507:  
        !           508:     if (bExplainTextButtonHit) {
        !           509:         dwBufferSize = dwHelpSize;
        !           510:         lWin32Status = RegQueryValueEx (
        !           511:             hKeyNames,
        !           512:             Help,
        !           513:             RESERVED,
        !           514:             &dwValueType,
        !           515:             (LPVOID)lpHelpText,
        !           516:             &dwBufferSize);
        !           517:                             
        !           518:         if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT;
        !           519:     }
        !           520: 
        !           521:     // load counter array items
        !           522:     Status = AddNamesToArray (lpCounterNames, dwLastId, lpCounterId) ;
        !           523:     if (Status != ERROR_SUCCESS) goto BNT_BAILOUT ;
        !           524: 
        !           525:     if (bExplainTextButtonHit) {
        !           526:         Status = AddNamesToArray (lpHelpText, dwLastId, lpCounterId) ;
        !           527:     }
        !           528: 
        !           529:     if (Status != ERROR_SUCCESS) goto BNT_BAILOUT ;
        !           530: 
        !           531:     if (pCounterInfo) {
        !           532:         pCounterInfo->dwLastId = dwLastId;
        !           533:         pCounterInfo->dwLangId = LangIdUsed;
        !           534:         pCounterInfo->dwHelpSize = dwHelpSize;
        !           535:         pCounterInfo->dwCounterSize = dwCounterSize;
        !           536:     }
        !           537: 
        !           538:     RegCloseKey (hKeyValue);
        !           539:     RegCloseKey (hKeyNames);
        !           540:     return lpReturnValue;
        !           541: 
        !           542: BNT_BAILOUT:
        !           543:     if (lWin32Status != ERROR_SUCCESS) {
        !           544:         dwLastError = GetLastError();
        !           545:     }
        !           546: 
        !           547:     if (lpReturnValue) {
        !           548:         MemoryFree ((LPVOID)lpReturnValue);
        !           549:     }
        !           550:     
        !           551:     if (hKeyValue) RegCloseKey (hKeyValue);
        !           552:     if (hKeyNames) RegCloseKey (hKeyNames);
        !           553: 
        !           554:     return NULL;
        !           555: }
        !           556: 
        !           557: DWORD GetSystemKey (PPERFSYSTEM pSysInfo, HKEY *phKeyMachine)
        !           558: {
        !           559:     DWORD   dwStatus;
        !           560: 
        !           561:    // connect to system registry
        !           562: 
        !           563:     if (IsLocalComputer(pSysInfo->sysName) ||
        !           564:        (PlayingBackLog() && PlaybackLog.pBaseCounterNames)) {
        !           565:         *phKeyMachine = HKEY_LOCAL_MACHINE;
        !           566:     } else {
        !           567:         try {
        !           568:             dwStatus = RegConnectRegistry (
        !           569:                 pSysInfo->sysName,
        !           570:                 HKEY_LOCAL_MACHINE,
        !           571:                 phKeyMachine);
        !           572: 
        !           573:             if (dwStatus != ERROR_SUCCESS) {
        !           574:                 if (PlayingBackLog()) {
        !           575:                     // If remote machine is not on and we are
        !           576:                     // playing back log, then, use the counters from
        !           577:                     // local machine.
        !           578:                     *phKeyMachine = HKEY_LOCAL_MACHINE;
        !           579:                 } else {
        !           580:                     return dwStatus;
        !           581:                 }
        !           582:             }
        !           583:         } finally {
        !           584:             ; // nothing
        !           585:         }
        !           586:     }
        !           587:     return 0;
        !           588: }
        !           589: 
        !           590: 
        !           591: DWORD GetSystemNames(PPERFSYSTEM pSysInfo)
        !           592: {
        !           593:     HKEY    hKeyMachine = 0;
        !           594:     DWORD   dwStatus;
        !           595: 
        !           596:     if (dwStatus = GetSystemKey (pSysInfo, &hKeyMachine)) {
        !           597:          return dwStatus;
        !           598:     }
        !           599: 
        !           600:     // if here, then hKeyMachine is an open key to the system's 
        !           601:     //  HKEY_LOCAL_MACHINE registry database
        !           602: 
        !           603:     // only one language is supported by this approach.
        !           604:     // multiple language support would:
        !           605:     //  1.  enumerate language keys 
        !           606:     //       and for each key:
        !           607:     //  2.  allocate memory for structures
        !           608:     //  3.  call BuildNameTable for each lang key.
        !           609: 
        !           610:     pSysInfo->CounterInfo.pNextTable = NULL;
        !           611:     pSysInfo->CounterInfo.dwLangId = iLanguage ;   // default Lang ID
        !           612: 
        !           613:     if (PlayingBackLog() && PlaybackLog.pBaseCounterNames) {
        !           614:         pSysInfo->CounterInfo.TextString = LogBuildNameTable (pSysInfo) ; 
        !           615:     } else {
        !           616:         pSysInfo->CounterInfo.TextString = BuildNameTable (
        !           617:               hKeyMachine,
        !           618:               NULL,                               // use default
        !           619:               &pSysInfo->CounterInfo,
        !           620:               0);
        !           621:     }
        !           622: 
        !           623:     if (hKeyMachine && hKeyMachine != HKEY_LOCAL_MACHINE) {
        !           624:         RegCloseKey (hKeyMachine) ;
        !           625:     }
        !           626: 
        !           627:     if (pSysInfo->CounterInfo.TextString == NULL) {
        !           628:         return GetLastError();
        !           629:     } else {
        !           630:         return ERROR_SUCCESS;
        !           631:     }
        !           632: }
        !           633: 
        !           634: BOOL  GetHelpText(
        !           635:     PPERFSYSTEM pSysInfo
        !           636:     )
        !           637: {
        !           638:     LPWSTR  *lpCounterId;
        !           639:     LPWSTR  lpHelpText;
        !           640:     LONG    lWin32Status;
        !           641:     DWORD   dwValueType;
        !           642:     DWORD   dwArraySize;
        !           643:     DWORD   dwBufferSize;
        !           644:     DWORD   dwCounterSize;
        !           645:     DWORD   dwHelpSize;
        !           646:     NTSTATUS    Status;
        !           647:     DWORD   dwLastId;
        !           648:      
        !           649:     HKEY    hKeyNames;
        !           650:     
        !           651:     TCHAR   SysLangId [ShortTextLen] ;
        !           652:     TCHAR   ValueNameString [LongTextLen] ;
        !           653:     HKEY    hKeyMachine = 0;
        !           654:     DWORD   dwStatus;
        !           655: 
        !           656:     SetHourglassCursor() ;
        !           657: 
        !           658:     //initialize local variables
        !           659:     lpHelpText = NULL;
        !           660:     hKeyNames = hKeyMachine = NULL;
        !           661: 
        !           662:     dwBufferSize = 0;
        !           663: 
        !           664:     if (dwStatus = GetSystemKey (pSysInfo, &hKeyMachine)) {
        !           665:          goto ERROR_EXIT;
        !           666:     }
        !           667: 
        !           668:     TSPRINTF (SysLangId, TEXT("%03x"), pSysInfo->CounterInfo.dwLangId) ;
        !           669:     
        !           670:     lstrcpy (ValueNameString, NamesKey);
        !           671:     lstrcat (ValueNameString, Slash);
        !           672:     lstrcat (ValueNameString, SysLangId);
        !           673: 
        !           674:     lWin32Status = RegOpenKeyEx (
        !           675:               hKeyMachine,
        !           676:               ValueNameString,
        !           677:               RESERVED,
        !           678:               KEY_READ,
        !           679:               &hKeyNames);
        !           680: 
        !           681:     if (lWin32Status != ERROR_SUCCESS) goto ERROR_EXIT;
        !           682: 
        !           683:     dwHelpSize = 0;
        !           684:     lWin32Status = RegQueryValueEx (
        !           685:               hKeyNames,
        !           686:               Help,
        !           687:               RESERVED,
        !           688:               &dwValueType,
        !           689:               NULL,
        !           690:               &dwHelpSize);
        !           691: 
        !           692:     if (lWin32Status != ERROR_SUCCESS || dwHelpSize == 0) goto ERROR_EXIT;
        !           693: 
        !           694:     dwLastId = pSysInfo->CounterInfo.dwLastId;
        !           695:     dwArraySize = (dwLastId + 1) * sizeof (LPWSTR);
        !           696:     dwCounterSize = pSysInfo->CounterInfo.dwCounterSize;
        !           697: 
        !           698:     // allocate another memory to get the help text
        !           699:     lpHelpText = MemoryAllocate (dwHelpSize);
        !           700:     if (!lpHelpText) goto ERROR_EXIT;
        !           701: 
        !           702:     dwBufferSize = dwHelpSize;
        !           703:     lWin32Status = RegQueryValueEx (
        !           704:         hKeyNames,
        !           705:         Help,
        !           706:         RESERVED,
        !           707:         &dwValueType,
        !           708:         (LPVOID)lpHelpText,
        !           709:         &dwBufferSize);
        !           710:                             
        !           711:     if (lWin32Status != ERROR_SUCCESS) goto ERROR_EXIT;
        !           712: 
        !           713:     // setup the help text pointers
        !           714:     lpCounterId = pSysInfo->CounterInfo.TextString;
        !           715:     Status = AddNamesToArray (lpHelpText, dwLastId, lpCounterId) ;
        !           716:     if (Status != ERROR_SUCCESS) goto ERROR_EXIT;
        !           717: 
        !           718:     pSysInfo->CounterInfo.dwHelpSize = dwHelpSize;
        !           719: 
        !           720:     RegCloseKey (hKeyNames);
        !           721: 
        !           722:     if (hKeyMachine && hKeyMachine != HKEY_LOCAL_MACHINE) {
        !           723:         RegCloseKey (hKeyMachine) ;
        !           724:     }
        !           725: 
        !           726:     pSysInfo->CounterInfo.HelpTextString = lpHelpText;
        !           727: 
        !           728:     SetArrowCursor() ;
        !           729: 
        !           730:     return TRUE;
        !           731: 
        !           732: ERROR_EXIT:
        !           733: 
        !           734:     SetArrowCursor() ;
        !           735: 
        !           736:     if (lpHelpText) {
        !           737:         MemoryFree ((LPVOID)lpHelpText);
        !           738:     }
        !           739:     
        !           740:     if (hKeyNames) {
        !           741:         RegCloseKey (hKeyNames);
        !           742:     }
        !           743:     if (hKeyMachine && hKeyMachine != HKEY_LOCAL_MACHINE) {
        !           744:         RegCloseKey (hKeyMachine) ;
        !           745:     }
        !           746: 
        !           747:     return FALSE;
        !           748: }
        !           749: 
        !           750: //
        !           751: //  QueryPerformanceName -     Get a title, given an index
        !           752: //
        !           753: //     Inputs:
        !           754: //
        !           755: //          pSysInfo        -   Pointer to sysinfo struct for the
        !           756: //                              system in question
        !           757: //
        !           758: //         dwTitleIndex    -   Index of Title entry
        !           759: //
        !           760: //          LangID          -   language in which title should be displayed
        !           761: //
        !           762: //         cbTitle         -   # of char in the lpTitle buffer
        !           763: //
        !           764: //         lpTitle         -   pointer to a buffer to receive the
        !           765: //                              Title
        !           766: //
        !           767: //          Help            -   TRUE is help is desired, else counter or
        !           768: //                              object is assumed
        !           769: DWORD
        !           770: QueryPerformanceName(
        !           771:     PPERFSYSTEM pSysInfo,
        !           772:     DWORD dwTitleIndex,
        !           773:     LANGID LangID,
        !           774:     DWORD cbTitle,
        !           775:     LPTSTR lpTitle,
        !           776:     BOOL Help
        !           777:     )
        !           778: {
        !           779:     LPWSTR  lpTitleFound;
        !           780:     NTSTATUS    Status;
        !           781:     BOOL    bGetTextSuccess = TRUE ;
        !           782: 
        !           783:     DBG_UNREFERENCED_PARAMETER(LangID);
        !           784: 
        !           785:     if (Help && pSysInfo->CounterInfo.dwHelpSize == 0) {
        !           786:         // we have not get the help text yet, go get it
        !           787:         bGetTextSuccess = GetHelpText (pSysInfo);
        !           788:     }
        !           789: 
        !           790:     if (!bGetTextSuccess) {
        !           791:         Status = ERROR_INVALID_NAME;
        !           792:         goto ErrorExit;
        !           793:     }
        !           794: 
        !           795:     if ((dwTitleIndex > 0) && (dwTitleIndex <= pSysInfo->CounterInfo.dwLastId)) {
        !           796:         // then title should be found in the array
        !           797:         lpTitleFound = pSysInfo->CounterInfo.TextString[dwTitleIndex];
        !           798:         if (!lpTitleFound) {
        !           799:             // no entry for this index
        !           800:             Status = ERROR_INVALID_NAME;
        !           801:         }
        !           802:         else if ((DWORD)lstrlen(lpTitleFound) < cbTitle) {
        !           803:             lstrcpy (lpTitle, lpTitleFound);
        !           804:             return (ERROR_SUCCESS);
        !           805:         } else {
        !           806:             Status = ERROR_MORE_DATA;
        !           807:         }
        !           808:     } else {
        !           809: 
        !           810:         Status = ERROR_INVALID_NAME;
        !           811:     }
        !           812: 
        !           813: ErrorExit:
        !           814:     // if here, then an error occured, so return a blank
        !           815: 
        !           816:     if ((DWORD)lstrlen (NULL_NAME) < cbTitle) {
        !           817:         lstrcpy (lpTitle, NULL_NAME);
        !           818:     }
        !           819: 
        !           820:     return Status;   // title not returned
        !           821: 
        !           822: }
        !           823: 
        !           824: 
        !           825: LONG
        !           826: GetSystemPerfData (
        !           827:     IN HKEY hKeySystem,
        !           828:     IN LPTSTR lpszValue,
        !           829:     OUT PPERFDATA pPerfData, 
        !           830:     OUT PDWORD pdwPerfDataLen
        !           831: )
        !           832:    {  // GetSystemPerfData
        !           833:    LONG     lError ;
        !           834:    DWORD    Type ;
        !           835: 
        !           836:    // have to pass in a Type to RegQueryValueEx(W) or else it
        !           837:    // will crash
        !           838:    lError = RegQueryValueEx (hKeySystem, lpszValue, NULL, &Type,
        !           839:                             (LPSTR) pPerfData, pdwPerfDataLen) ;
        !           840:    return (lError) ;
        !           841:    }  // GetSystemPerfData
        !           842: 
        !           843:             
        !           844: BOOL CloseSystemPerfData (HKEY hKeySystem)
        !           845:    {  // CloseSystemPerfData
        !           846:    return (TRUE) ;
        !           847:    }  // CloseSystemPerfData
        !           848: 
        !           849: 
        !           850: 
        !           851: int CBLoadObjects (HWND hWndCB,
        !           852:                    PPERFDATA pPerfData,
        !           853:                    PPERFSYSTEM pSysInfo,
        !           854:                    DWORD dwDetailLevel,
        !           855:                    LPTSTR lpszDefaultObject,
        !           856:                    BOOL bIncludeAll)
        !           857: /*
        !           858:    Effect:        Load into the combo box CB one item for each Object in
        !           859:                   pPerfData. For each item, look up the object's name in
        !           860:                   the registry strings associated with pSysInfo, and 
        !           861:                   attach the object to the data field of the CB item.
        !           862: 
        !           863:                   Dont add those objects that are more detailed than
        !           864:                   dwDetailLevel.      
        !           865: 
        !           866:                   Set the current selected CB item to the object named
        !           867:                   lpszDefaultObject, or to the default object specified in 
        !           868:                   pPerfData if lpszDefaultObject is NULL.
        !           869: */
        !           870:    {  // CBLoadObjects
        !           871:    UINT           i ;
        !           872:    int            iIndex ;
        !           873:    PPERFOBJECT    pObject ;
        !           874:    TCHAR          szObject [PerfObjectLen + 1] ;
        !           875:    TCHAR          szDefaultObject [PerfObjectLen + 1] ;
        !           876: 
        !           877:    CBReset (hWndCB) ;
        !           878:    strclr (szDefaultObject) ;
        !           879: 
        !           880:    pObject = FirstObject (pPerfData) ;
        !           881: 
        !           882:    for (i = 0, pObject = FirstObject (pPerfData) ;
        !           883:         i < pPerfData->NumObjectTypes ;
        !           884:         i++, pObject = NextObject (pObject))
        !           885:       {  // for
        !           886:       if (pObject->DetailLevel <= dwDetailLevel)
        !           887:          {  // if
        !           888:          strclr (szObject) ;
        !           889:          QueryPerformanceName (pSysInfo, pObject->ObjectNameTitleIndex, 
        !           890:                                0, PerfObjectLen, szObject, FALSE) ;
        !           891: 
        !           892:          // if szObject not empty, add it to the Combo-box
        !           893:          if (!strsame(szObject, NULL_NAME))
        !           894:             {
        !           895:             iIndex = CBAdd (hWndCB, szObject) ;
        !           896:             CBSetData (hWndCB, iIndex, (DWORD) pObject) ;
        !           897: 
        !           898:             if ((LONG)pObject->ObjectNameTitleIndex == pPerfData->DefaultObject)
        !           899:                lstrcpy (szDefaultObject, szObject) ;
        !           900:             } // if szObject not empty
        !           901:          }  // if
        !           902:       }  // for
        !           903: 
        !           904: 
        !           905:    if (bIncludeAll)
        !           906:       {
        !           907:       StringLoad (IDS_ALLOBJECTS, szObject) ;
        !           908:       CBInsert (hWndCB, 0, szObject) ;
        !           909:       // assume "ALL" is default unless overridden
        !           910:       lstrcpy (szDefaultObject, szObject) ;
        !           911:       }
        !           912:       
        !           913:    if (lpszDefaultObject)
        !           914:       lstrcpy (szDefaultObject, lpszDefaultObject) ;
        !           915: 
        !           916:    iIndex = CBFind (hWndCB, szDefaultObject) ;
        !           917:    CBSetSelection (hWndCB, (iIndex != CB_ERR) ? iIndex : 0) ;
        !           918: 
        !           919:    return (i) ;
        !           920:    }  // CBLoadObjects
        !           921:          
        !           922: 
        !           923: int LBLoadObjects (HWND hWndLB,
        !           924:                    PPERFDATA pPerfData,
        !           925:                    PPERFSYSTEM pSysInfo,
        !           926:                    DWORD dwDetailLevel,
        !           927:                    LPTSTR lpszDefaultObject,
        !           928:                    BOOL bIncludeAll)
        !           929: /*
        !           930:    Effect:        Load into the list box LB one item for each Object in
        !           931:                   pPerfData. For each item, look up the object's name in
        !           932:                   the registry strings associated with pSysInfo, and 
        !           933:                   attach the object to the data field of the LB item.
        !           934: 
        !           935:                   Dont add those objects that are more detailed than
        !           936:                   dwDetailLevel.      
        !           937: 
        !           938:                   Set the current selected LB item to the object named
        !           939:                   lpszDefaultObject, or to the default object specified in 
        !           940:                   pPerfData if lpszDefaultObject is NULL.
        !           941: */
        !           942:    {  // LBLoadObjects
        !           943:    UINT           i ;
        !           944:    int            iIndex ;
        !           945:    PPERFOBJECT    pObject ;
        !           946:    TCHAR          szObject [PerfObjectLen + 1] ;
        !           947:    TCHAR          szDefaultObject [PerfObjectLen + 1] ;
        !           948: 
        !           949:    LBReset (hWndLB) ;
        !           950:    strclr (szDefaultObject) ;
        !           951: 
        !           952:    pObject = FirstObject (pPerfData) ;
        !           953: 
        !           954:    for (i = 0, pObject = FirstObject (pPerfData) ;
        !           955:         i < pPerfData->NumObjectTypes ;
        !           956:         i++, pObject = NextObject (pObject))
        !           957:       {  // for
        !           958:       if (pObject->DetailLevel <= dwDetailLevel)
        !           959:          {  // if
        !           960:          strclr (szObject) ;
        !           961:          QueryPerformanceName (pSysInfo, pObject->ObjectNameTitleIndex, 
        !           962:                                0, PerfObjectLen, szObject, FALSE) ;
        !           963: 
        !           964:          // if szObject is not empty, add it to the listbox
        !           965:          if (!strsame(szObject, NULL_NAME))
        !           966:             {
        !           967:             iIndex = LBAdd (hWndLB, szObject) ;
        !           968:             LBSetData (hWndLB, iIndex, (DWORD) pObject) ;
        !           969: 
        !           970:             if ((LONG)pObject->ObjectNameTitleIndex == pPerfData->DefaultObject)
        !           971:                lstrcpy (szDefaultObject, szObject) ;
        !           972:             } // if szObject is not empty
        !           973:          }
        !           974:       }  // for
        !           975: 
        !           976: 
        !           977:    if (bIncludeAll)
        !           978:       {
        !           979:       StringLoad (IDS_ALLOBJECTS, szObject) ;
        !           980:       LBInsert (hWndLB, 0, szObject) ;
        !           981:          LBSetData (hWndLB, iIndex, (DWORD) NULL) ;
        !           982:       // assume "ALL" is default unless overridden
        !           983:       lstrcpy (szDefaultObject, szObject) ;
        !           984:       }
        !           985: 
        !           986:    if (lpszDefaultObject)
        !           987:       {
        !           988:       lstrcpy (szDefaultObject, lpszDefaultObject) ;
        !           989:       iIndex = LBFind (hWndLB, szDefaultObject) ;
        !           990:       LBSetSelection (hWndLB, (iIndex != LB_ERR) ? iIndex : 0) ;
        !           991:       }
        !           992: 
        !           993:    return (i) ;
        !           994:    }  // LBLoadObjects
        !           995:          
        !           996: 
        !           997: /***************************************************************************\
        !           998: * GetObjectDef()
        !           999: *
        !          1000: * Entry: pointer to data block and the number of the object type
        !          1001: * Exit:  returns a pointer to the specified object type definition
        !          1002: *
        !          1003: \***************************************************************************/
        !          1004: 
        !          1005: PERF_OBJECT_TYPE *GetObjectDef(
        !          1006:     PERF_DATA_BLOCK *pDataBlock,
        !          1007:     DWORD NumObjectType)
        !          1008: {
        !          1009:     DWORD NumTypeDef;
        !          1010: 
        !          1011:     PERF_OBJECT_TYPE *pObjectDef;
        !          1012: 
        !          1013:     pObjectDef = FirstObject(pDataBlock);
        !          1014: 
        !          1015:     for ( NumTypeDef = 0;
        !          1016:          NumTypeDef < pDataBlock->NumObjectTypes;
        !          1017:          NumTypeDef++ ) {
        !          1018: 
        !          1019:        if ( NumTypeDef == NumObjectType ) {
        !          1020: 
        !          1021:            return pObjectDef;
        !          1022:        }
        !          1023:         pObjectDef = NextObject(pObjectDef);
        !          1024:     }
        !          1025:     return 0;
        !          1026: }
        !          1027: 
        !          1028: /***************************************************************************\
        !          1029: * GetObjectDefByTitleIndex()
        !          1030: *
        !          1031: * Entry: pointer to data block and the title index of the object type
        !          1032: * Exit:  returns a pointer to the specified object type definition
        !          1033: *
        !          1034: \***************************************************************************/
        !          1035: 
        !          1036: PERF_OBJECT_TYPE *GetObjectDefByTitleIndex(
        !          1037:     PERF_DATA_BLOCK *pDataBlock,
        !          1038:     DWORD ObjectTypeTitleIndex)
        !          1039: {
        !          1040:     DWORD NumTypeDef;
        !          1041: 
        !          1042:     PERF_OBJECT_TYPE *pObjectDef;
        !          1043: 
        !          1044:     pObjectDef = FirstObject(pDataBlock);
        !          1045: 
        !          1046:     for ( NumTypeDef = 0;
        !          1047:          NumTypeDef < pDataBlock->NumObjectTypes;
        !          1048:          NumTypeDef++ ) {
        !          1049: 
        !          1050:         if ( pObjectDef->ObjectNameTitleIndex == ObjectTypeTitleIndex ) {
        !          1051: 
        !          1052:            return pObjectDef;
        !          1053:        }
        !          1054:         pObjectDef = NextObject(pObjectDef);
        !          1055:     }
        !          1056:     return 0;
        !          1057: }
        !          1058: 
        !          1059: /***************************************************************************\
        !          1060: * GetObjectDefByName()
        !          1061: *
        !          1062: * Entry: pointer to data block and the name of the object type
        !          1063: * Exit:  returns a pointer to the specified object type definition
        !          1064: *
        !          1065: \***************************************************************************/
        !          1066: 
        !          1067: PERF_OBJECT_TYPE *GetObjectDefByName(
        !          1068:     PPERFSYSTEM pSystem,
        !          1069:     PERF_DATA_BLOCK *pDataBlock,
        !          1070:     LPTSTR pObjectName)
        !          1071: {
        !          1072:     DWORD NumTypeDef;
        !          1073:     TCHAR szObjectName [PerfObjectLen + 1] ;
        !          1074: 
        !          1075:     PERF_OBJECT_TYPE *pObjectDef;
        !          1076: 
        !          1077:     pObjectDef = FirstObject(pDataBlock);
        !          1078:     for ( NumTypeDef = 0;
        !          1079:          NumTypeDef < pDataBlock->NumObjectTypes;
        !          1080:          NumTypeDef++ ) {
        !          1081: 
        !          1082:         ObjectName (pSystem, pObjectDef, szObjectName, PerfObjectLen) ;
        !          1083:         if (strsame (szObjectName, pObjectName) ) {
        !          1084: 
        !          1085:            return pObjectDef;
        !          1086:        }
        !          1087:         pObjectDef = NextObject(pObjectDef);
        !          1088:     }
        !          1089:     return 0;
        !          1090: }
        !          1091: 
        !          1092: /***************************************************************************\
        !          1093: * GetCounterDef()
        !          1094: *
        !          1095: * Entry: pointer to object type definition the number of the Counter
        !          1096: *       definition
        !          1097: * Exit:  returns a pointer to the specified Counter definition
        !          1098: *
        !          1099: \***************************************************************************/
        !          1100: 
        !          1101: PERF_COUNTER_DEFINITION *GetCounterDef(
        !          1102:     PERF_OBJECT_TYPE *pObjectDef,
        !          1103:     DWORD NumCounter)
        !          1104: {
        !          1105:     DWORD NumCtrDef;
        !          1106: 
        !          1107:     PERF_COUNTER_DEFINITION *pCounterDef;
        !          1108: 
        !          1109:     pCounterDef = FirstCounter(pObjectDef);
        !          1110: 
        !          1111:     for ( NumCtrDef = 0;
        !          1112:          NumCtrDef < pObjectDef->NumCounters;
        !          1113:          NumCtrDef++ ) {
        !          1114: 
        !          1115:        if ( NumCtrDef == NumCounter ) {
        !          1116: 
        !          1117:            return pCounterDef;
        !          1118:        }
        !          1119:         pCounterDef = NextCounter(pCounterDef);
        !          1120:     }
        !          1121:     return 0;
        !          1122: }
        !          1123: 
        !          1124: /***************************************************************************\
        !          1125: * GetCounterNumByTitleIndex()
        !          1126: *
        !          1127: * Entry: pointer to object type definition and the title index of
        !          1128: *        the name of the Counter definition
        !          1129: * Exit:  returns the number of the specified Counter definition
        !          1130: *
        !          1131: \***************************************************************************/
        !          1132: 
        !          1133: LONG GetCounterNumByTitleIndex(
        !          1134:     PERF_OBJECT_TYPE *pObjectDef,
        !          1135:     DWORD CounterTitleIndex)
        !          1136: {
        !          1137:     DWORD NumCtrDef;
        !          1138: 
        !          1139:     PERF_COUNTER_DEFINITION *pCounterDef;
        !          1140: 
        !          1141:     pCounterDef = FirstCounter(pObjectDef);
        !          1142: 
        !          1143:     for ( NumCtrDef = 0;
        !          1144:          NumCtrDef < pObjectDef->NumCounters;
        !          1145:          NumCtrDef++ ) {
        !          1146: 
        !          1147:         if ( pCounterDef->CounterNameTitleIndex == CounterTitleIndex ) {
        !          1148: 
        !          1149:            return NumCtrDef;
        !          1150:        }
        !          1151:         pCounterDef = NextCounter(pCounterDef);
        !          1152:     }
        !          1153:     return 0;
        !          1154: }
        !          1155: 
        !          1156: /***************************************************************************\
        !          1157: * GetCounterData()
        !          1158: *
        !          1159: * Entry: pointer to object definition and number of counter, must be
        !          1160: *       an object with no instances
        !          1161: * Exit:  returns a pointer to the data
        !          1162: *
        !          1163: \***************************************************************************/
        !          1164: 
        !          1165: PVOID GetCounterData(
        !          1166:     PERF_OBJECT_TYPE *pObjectDef,
        !          1167:     PERF_COUNTER_DEFINITION *pCounterDef)
        !          1168: {
        !          1169: 
        !          1170:     PERF_COUNTER_BLOCK *pCtrBlock;
        !          1171: 
        !          1172:     pCtrBlock = (PERF_COUNTER_BLOCK *)((PCHAR)pObjectDef +
        !          1173:                                              pObjectDef->DefinitionLength);
        !          1174: 
        !          1175:     return (PVOID)((PCHAR)pCtrBlock + pCounterDef->CounterOffset);
        !          1176: }
        !          1177: 
        !          1178: /***************************************************************************\
        !          1179: * GetInstanceCounterData()
        !          1180: *
        !          1181: * Entry: pointer to object definition and number of counter, and a pointer
        !          1182: *        to the instance for which the data is to be retrieved
        !          1183: * Exit:  returns a pointer to the data
        !          1184: *
        !          1185: \***************************************************************************/
        !          1186: 
        !          1187: PVOID GetInstanceCounterData(
        !          1188:     PERF_OBJECT_TYPE *pObjectDef,
        !          1189:     PERF_INSTANCE_DEFINITION *pInstanceDef,
        !          1190:     PERF_COUNTER_DEFINITION *pCounterDef)
        !          1191: {
        !          1192: 
        !          1193:     PERF_COUNTER_BLOCK *pCtrBlock;
        !          1194: 
        !          1195:     pCtrBlock = (PERF_COUNTER_BLOCK *)((PCHAR)pInstanceDef +
        !          1196:                                              pInstanceDef->ByteLength);
        !          1197: 
        !          1198:     return (PVOID)((PCHAR)pCtrBlock + pCounterDef->CounterOffset);
        !          1199: }
        !          1200: 
        !          1201: /***************************************************************************\
        !          1202: * GetNextInstance()
        !          1203: *
        !          1204: * Entry: pointer to instance definition
        !          1205: * Exit:  returns a pointer to the next instance definition.  If none,
        !          1206: *        points to byte past this instance
        !          1207: *
        !          1208: \***************************************************************************/
        !          1209: 
        !          1210: PERF_INSTANCE_DEFINITION *GetNextInstance(
        !          1211:     PERF_INSTANCE_DEFINITION *pInstDef)
        !          1212: {
        !          1213:     PERF_COUNTER_BLOCK *pCtrBlock;
        !          1214: 
        !          1215:     pCtrBlock = (PERF_COUNTER_BLOCK *)
        !          1216:                 ((PCHAR) pInstDef + pInstDef->ByteLength);
        !          1217: 
        !          1218:     return (PERF_INSTANCE_DEFINITION *)
        !          1219:            ((PCHAR) pCtrBlock + pCtrBlock->ByteLength);
        !          1220: }
        !          1221: 
        !          1222: /***************************************************************************\
        !          1223: * GetInstance()
        !          1224: *
        !          1225: * Entry: pointer to object type definition, the name of the instance,
        !          1226: *       the name of the parent object type, and the parent instance index.
        !          1227: *       The name of the parent object type is NULL if no parent.
        !          1228: * Exit:  returns a pointer to the specified instance definition
        !          1229: *
        !          1230: \***************************************************************************/
        !          1231: 
        !          1232: PERF_INSTANCE_DEFINITION *GetInstance(
        !          1233:     PERF_OBJECT_TYPE *pObjectDef,
        !          1234:     LONG InstanceNumber)
        !          1235: {
        !          1236: 
        !          1237:    PERF_INSTANCE_DEFINITION *pInstanceDef;
        !          1238:    LONG NumInstance;
        !          1239: 
        !          1240:    if (!pObjectDef)
        !          1241:       {
        !          1242:       return 0;
        !          1243:       }
        !          1244: 
        !          1245:    pInstanceDef = FirstInstance(pObjectDef);
        !          1246:    
        !          1247:    for ( NumInstance = 0;
        !          1248:       NumInstance < pObjectDef->NumInstances;
        !          1249:       NumInstance++ )
        !          1250:       {
        !          1251:        if ( InstanceNumber == NumInstance )
        !          1252:          {
        !          1253:          return pInstanceDef;
        !          1254:          }
        !          1255:       pInstanceDef = GetNextInstance(pInstanceDef);
        !          1256:       }
        !          1257: 
        !          1258:    return 0;
        !          1259: }
        !          1260: 
        !          1261: /***************************************************************************\
        !          1262: * GetInstanceByUniqueID()
        !          1263: *
        !          1264: * Entry: pointer to object type definition, and
        !          1265: *        the unique ID of the instance.
        !          1266: * Exit:  returns a pointer to the specified instance definition
        !          1267: *
        !          1268: \***************************************************************************/
        !          1269: 
        !          1270: PERF_INSTANCE_DEFINITION *GetInstanceByUniqueID(
        !          1271:     PERF_OBJECT_TYPE *pObjectDef,
        !          1272:     LONG UniqueID)
        !          1273: {
        !          1274: 
        !          1275:     PERF_INSTANCE_DEFINITION *pInstanceDef;
        !          1276: 
        !          1277:     LONG NumInstance;
        !          1278: 
        !          1279:     pInstanceDef = FirstInstance(pObjectDef);
        !          1280: 
        !          1281:     for ( NumInstance = 0;
        !          1282:          NumInstance < pObjectDef->NumInstances;
        !          1283:          NumInstance++ ) {
        !          1284: 
        !          1285:         if ( pInstanceDef->UniqueID == UniqueID ) {
        !          1286: 
        !          1287:            return pInstanceDef;
        !          1288:        }
        !          1289:         pInstanceDef = GetNextInstance(pInstanceDef);
        !          1290:     }
        !          1291:     return 0;
        !          1292: }
        !          1293: 
        !          1294: 
        !          1295: /***************************************************************************\
        !          1296: * GetInstanceByNameUsingParentTitleIndex()
        !          1297: *
        !          1298: * Entry: pointer to object type definition, the name of the instance,
        !          1299: *       and the name of the parent instance.
        !          1300: *       The name of the parent instance is NULL if no parent.
        !          1301: * Exit:  returns a pointer to the specified instance definition
        !          1302: *
        !          1303: \***************************************************************************/
        !          1304: 
        !          1305: PERF_INSTANCE_DEFINITION *GetInstanceByNameUsingParentTitleIndex(
        !          1306:     PERF_DATA_BLOCK *pDataBlock,
        !          1307:     PERF_OBJECT_TYPE *pObjectDef,
        !          1308:     LPTSTR pInstanceName,
        !          1309:     LPTSTR pParentName)
        !          1310: {
        !          1311:    BOOL fHaveParent;
        !          1312:    PERF_OBJECT_TYPE *pParentObj;
        !          1313: 
        !          1314:     PERF_INSTANCE_DEFINITION  *pParentInst,
        !          1315:                             *pInstanceDef;
        !          1316: 
        !          1317:    LONG   NumInstance;
        !          1318:    
        !          1319:    // FIXFIX: remove when Unicode
        !          1320:    TCHAR  InstanceName[256];
        !          1321: 
        !          1322:    fHaveParent = FALSE;
        !          1323:    pInstanceDef = FirstInstance(pObjectDef);
        !          1324: 
        !          1325:    for ( NumInstance = 0;
        !          1326:       NumInstance < pObjectDef->NumInstances;
        !          1327:       NumInstance++ )
        !          1328:       {
        !          1329: 
        !          1330:       //FIXFIX: remove when Unicode
        !          1331:       
        !          1332:       GetInstanceName(pInstanceDef,InstanceName);
        !          1333:       
        !          1334:       if ( lstrcmp(InstanceName, pInstanceName) == 0 )
        !          1335:          {
        !          1336: 
        !          1337:          // Instance name matches
        !          1338: 
        !          1339:          if ( pParentName == NULL )
        !          1340:             {
        !          1341: 
        !          1342:             // No parent, we're done
        !          1343: 
        !          1344:             return pInstanceDef;
        !          1345: 
        !          1346:             }
        !          1347:          else
        !          1348:             {
        !          1349: 
        !          1350:             // Must match parent as well
        !          1351: 
        !          1352:             pParentObj = GetObjectDefByTitleIndex(
        !          1353:                pDataBlock,
        !          1354:                pInstanceDef->ParentObjectTitleIndex);
        !          1355: 
        !          1356:             if (!pParentObj)
        !          1357:                {
        !          1358:                // can't locate the parent, forget it
        !          1359:                break ;
        !          1360:                }
        !          1361: 
        !          1362:             // Object type of parent found; now find parent
        !          1363:             // instance
        !          1364: 
        !          1365:             pParentInst = GetInstance(pParentObj,
        !          1366:                pInstanceDef->ParentObjectInstance);
        !          1367: 
        !          1368:             if (!pParentInst)
        !          1369:                {
        !          1370:                // can't locate the parent instance, forget it
        !          1371:                break ;
        !          1372:                }
        !          1373: 
        !          1374:             //FIXFIX: remove when Unicode
        !          1375:             GetInstanceName(pParentInst,InstanceName);
        !          1376:             if ( lstrcmp(InstanceName, pParentName) == 0 )
        !          1377:                {
        !          1378: 
        !          1379:                // Parent Instance Name matches that passed in
        !          1380: 
        !          1381:                return pInstanceDef;
        !          1382:                }
        !          1383:             }
        !          1384:          }
        !          1385:       pInstanceDef = GetNextInstance(pInstanceDef);
        !          1386:       }
        !          1387:    return 0;
        !          1388: }
        !          1389: 
        !          1390: /***************************************************************************\
        !          1391: * GetInstanceByName()
        !          1392: *
        !          1393: * Entry: pointer to object type definition, the name of the instance,
        !          1394: *       and the name of the parent instance.
        !          1395: *       The name of the parent instance is NULL if no parent.
        !          1396: * Exit:  returns a pointer to the specified instance definition
        !          1397: *
        !          1398: \***************************************************************************/
        !          1399: 
        !          1400: PERF_INSTANCE_DEFINITION *GetInstanceByName(
        !          1401:     PERF_DATA_BLOCK *pDataBlock,
        !          1402:     PERF_OBJECT_TYPE *pObjectDef,
        !          1403:     LPTSTR pInstanceName,
        !          1404:     LPTSTR pParentName)
        !          1405: {
        !          1406:     BOOL fHaveParent;
        !          1407: 
        !          1408:     PERF_OBJECT_TYPE *pParentObj;
        !          1409: 
        !          1410:     PERF_INSTANCE_DEFINITION *pParentInst,
        !          1411:                             *pInstanceDef;
        !          1412: 
        !          1413:      LONG  NumInstance;
        !          1414: //    DWORD  LBInstanceName,
        !          1415: //       NumInstance,
        !          1416: //       NumParent,
        !          1417: //       ParentInst;
        !          1418: 
        !          1419:     // FIXFIX: remove when Unicode
        !          1420:     TCHAR  InstanceName[256];
        !          1421: 
        !          1422:     fHaveParent = FALSE;
        !          1423:     pInstanceDef = FirstInstance(pObjectDef);
        !          1424: 
        !          1425:     for ( NumInstance = 0;
        !          1426:          NumInstance < pObjectDef->NumInstances;
        !          1427:          NumInstance++ ) {
        !          1428: 
        !          1429:         //FIXFIX: remove when Unicode
        !          1430:         GetInstanceName(pInstanceDef,InstanceName);
        !          1431:         if ( lstrcmp(InstanceName, pInstanceName) == 0 ) {
        !          1432: 
        !          1433:            // Instance name matches
        !          1434: 
        !          1435:            if ( !pInstanceDef->ParentObjectTitleIndex ) {
        !          1436: 
        !          1437:                // No parent, we're done
        !          1438: 
        !          1439:                return pInstanceDef;
        !          1440: 
        !          1441:            } else {
        !          1442: 
        !          1443:                // Must match parent as well
        !          1444: 
        !          1445:                 pParentObj = GetObjectDefByTitleIndex(
        !          1446:                                 pDataBlock,
        !          1447:                                  pInstanceDef->ParentObjectTitleIndex);
        !          1448: 
        !          1449:                // Object type of parent found; now find parent
        !          1450:                // instance
        !          1451: 
        !          1452:                pParentInst = GetInstance(pParentObj,
        !          1453:                                          pInstanceDef->ParentObjectInstance);
        !          1454: 
        !          1455:                 //FIXFIX: remove when Unicode
        !          1456:                 GetInstanceName(pParentInst, InstanceName);
        !          1457:                 if ( lstrcmp(InstanceName, pParentName) == 0 ) {
        !          1458: 
        !          1459:                    // Parent Instance Name matches that passed in
        !          1460: 
        !          1461:                    return pInstanceDef;
        !          1462:                }
        !          1463:            }
        !          1464:        }
        !          1465:         pInstanceDef = GetNextInstance(pInstanceDef);
        !          1466:     }
        !          1467:     return 0;
        !          1468: }  // GetInstanceByName
        !          1469: 
        !          1470: 
        !          1471: BOOL FailedLineData (PPERFDATA pPerfData,
        !          1472:                      PLINE pLine)
        !          1473: /*
        !          1474:         This routine handles the case where there is no data for a
        !          1475:         system.
        !          1476: */
        !          1477: 
        !          1478: {  // FailedLineData
        !          1479:    LARGE_INTEGER     liDummy ;
        !          1480: 
        !          1481:    // System no longer exists.
        !          1482:    liDummy.LowPart = liDummy.HighPart = 0;
        !          1483:    if (pLine->lnCounterType == PERF_COUNTER_TIMER_INV)
        !          1484:    {
        !          1485:       // Timer inverse with Performance Counter as timer
        !          1486:       pLine->lnaOldCounterValue[0] = pLine->lnOldTime ;
        !          1487:       pLine->lnaCounterValue[0] = pLine->lnNewTime ;
        !          1488:    } else if (pLine->lnCounterType == PERF_100NSEC_TIMER_INV ||
        !          1489:               pLine->lnCounterType == PERF_100NSEC_MULTI_TIMER_INV)
        !          1490:    {
        !          1491:       // Timer inverse with System Time as timer
        !          1492:       pLine->lnaOldCounterValue[0] = pLine->lnOldTime100Ns ;
        !          1493:       pLine->lnaCounterValue[0] = pLine->lnNewTime100Ns ;
        !          1494:    } else
        !          1495:    {
        !          1496:       // Normal timer
        !          1497:       pLine->lnaOldCounterValue[0] =
        !          1498:       pLine->lnaCounterValue[0] =
        !          1499:       pLine->lnaOldCounterValue[1] =
        !          1500:       pLine->lnaCounterValue[1] = liDummy ;
        !          1501:    }
        !          1502:    return TRUE ;
        !          1503: 
        !          1504: }  // FailedLineData
        !          1505: 
        !          1506: 
        !          1507: BOOL UpdateLineData (PPERFDATA pPerfData, 
        !          1508:                      PLINE pLine)
        !          1509: /*
        !          1510:    Assert:        pPerfData holds the performance data for the same
        !          1511:                   system as pLine.
        !          1512: */
        !          1513: {  // UpdateLineData
        !          1514:    PPERFOBJECT       pObject ;
        !          1515:    PPERFINSTANCEDEF  pInstanceDef ;
        !          1516:    PPERFCOUNTERDEF   pCounterDef ;
        !          1517:    PPERFCOUNTERDEF   pCounterDef2 ;
        !          1518:    PDWORD            pCounterValue ;
        !          1519:    PDWORD            pCounterValue2 ;
        !          1520:    UINT              iCounterIndex ;
        !          1521:    LARGE_INTEGER     liDummy[2] ;
        !          1522: 
        !          1523:    // Use Object time units if available, otherwise use system
        !          1524:    // performance timer
        !          1525: 
        !          1526:    pLine->lnOldTime = pLine->lnNewTime;
        !          1527: 
        !          1528:    pLine->lnOldTime100Ns = pLine->lnNewTime100Ns;
        !          1529:    pLine->lnNewTime100Ns = pPerfData->PerfTime100nSec;
        !          1530: 
        !          1531:    pLine->lnPerfFreq = pPerfData->PerfFreq ;
        !          1532: 
        !          1533:    pObject = GetObjectDefByTitleIndex(
        !          1534:                 pPerfData,
        !          1535:                 pLine->lnObject.ObjectNameTitleIndex);
        !          1536: 
        !          1537:    if (!pObject)
        !          1538:    {
        !          1539:       // Object Type no longer exists.  This is possible if we are
        !          1540:       // looking at a log file which has not always collected all
        !          1541:       // the same data, such as appending measurements of different
        !          1542:       // object types.
        !          1543: 
        !          1544:       pCounterValue =
        !          1545:       pCounterValue2 = (PDWORD) liDummy;
        !          1546:       liDummy[0].LowPart = liDummy[0].HighPart = 0;
        !          1547: 
        !          1548: 
        !          1549:       pLine->lnNewTime = pPerfData->PerfTime;
        !          1550: 
        !          1551:       if (pLine->lnCounterType == PERF_COUNTER_TIMER_INV)
        !          1552:       {
        !          1553:          // Timer inverse with Performance Counter as timer
        !          1554:          pLine->lnaOldCounterValue[0] = pLine->lnOldTime ;
        !          1555:          pLine->lnaCounterValue[0] = pLine->lnNewTime ;
        !          1556:       } else if (pLine->lnCounterType == PERF_100NSEC_TIMER_INV ||
        !          1557:                  pLine->lnCounterType == PERF_100NSEC_MULTI_TIMER_INV)
        !          1558:       {
        !          1559:          // Timer inverse with System Time as timer
        !          1560:          pLine->lnaOldCounterValue[0] = pLine->lnOldTime100Ns ;
        !          1561:          pLine->lnaCounterValue[0] = pLine->lnNewTime100Ns ;
        !          1562:       } else
        !          1563:       {
        !          1564:          // Normal timer or counter
        !          1565:          pLine->lnaOldCounterValue[0] =
        !          1566:          pLine->lnaCounterValue[0] =
        !          1567:          pLine->lnaOldCounterValue[1] =
        !          1568:          pLine->lnaCounterValue[1] = liDummy[0] ;
        !          1569:       }
        !          1570:       return TRUE ;
        !          1571:    }
        !          1572:    else
        !          1573:    {
        !          1574:       pCounterDef = &pLine->lnCounterDef ;
        !          1575: 
        !          1576: //      if (LargeIntegerGreaterThanZero( pObject->PerfFreq )) {
        !          1577:       if (pCounterDef->CounterType & PERF_OBJECT_TIMER) {
        !          1578:          pLine->lnNewTime = pObject->PerfTime;
        !          1579:       } else {
        !          1580:          pLine->lnNewTime = pPerfData->PerfTime;
        !          1581:       }
        !          1582:     
        !          1583:       iCounterIndex = CounterIndex (pCounterDef, pObject) ;
        !          1584: 
        !          1585:       // Get second counter, only if we are not at
        !          1586:       // the end of the counters; some computations
        !          1587:       // require a second counter
        !          1588: 
        !          1589:       if (iCounterIndex < pObject->NumCounters-1 && iCounterIndex != -1) {
        !          1590:           pCounterDef2 = GetCounterDef(pObject, iCounterIndex+1);
        !          1591:       } else {
        !          1592:           pCounterDef2 = NULL;
        !          1593:       }
        !          1594: 
        !          1595:       if (pObject->NumInstances > 0)
        !          1596:       {
        !          1597: 
        !          1598:           if ( pLine->lnUniqueID != PERF_NO_UNIQUE_ID ) {
        !          1599:               pInstanceDef = GetInstanceByUniqueID(pObject,
        !          1600:                                                pLine->lnUniqueID);
        !          1601:           } else {
        !          1602: 
        !          1603:               pInstanceDef =
        !          1604:                   GetInstanceByNameUsingParentTitleIndex(
        !          1605:                       pPerfData,
        !          1606:                       pObject,
        !          1607:                       pLine->lnInstanceName,
        !          1608:                       pLine->lnPINName);
        !          1609:           }
        !          1610: 
        !          1611:           if (pInstanceDef) {
        !          1612:               pLine->lnInstanceDef = *pInstanceDef;
        !          1613:               pCounterValue = GetInstanceCounterData(pObject,
        !          1614:                                                pInstanceDef,
        !          1615:                                                pCounterDef);
        !          1616:               if ( pCounterDef2 ) {
        !          1617:                   pCounterValue2 = GetInstanceCounterData(pObject,
        !          1618:                                                     pInstanceDef,
        !          1619:                                                     pCounterDef2);
        !          1620:               }
        !          1621:           } else {
        !          1622:               pCounterValue =
        !          1623:               pCounterValue2 = (PDWORD) liDummy;
        !          1624:               liDummy[0].LowPart = liDummy[0].HighPart = 0;
        !          1625:               liDummy[1].LowPart = liDummy[1].HighPart = 0;
        !          1626:           }
        !          1627: 
        !          1628:           // Got everything...
        !          1629: 
        !          1630:       } // instances exist, look at them for counter blocks
        !          1631: 
        !          1632:       else
        !          1633:       {
        !          1634:           pCounterValue = GetCounterData(pObject, pCounterDef);
        !          1635:           if (pCounterDef2)
        !          1636:           {
        !          1637:               pCounterValue2 = GetCounterData(pObject, pCounterDef2);
        !          1638:           }
        !          1639: 
        !          1640:       } // counter def search when no instances
        !          1641:    }
        !          1642: 
        !          1643:    pLine->lnaOldCounterValue[0] = pLine->lnaCounterValue[0] ;
        !          1644: 
        !          1645:    if (pLine->lnCounterLength <= 4)
        !          1646:    {
        !          1647:        // HighPart was initialize to 0
        !          1648:        pLine->lnaCounterValue[0].LowPart = *pCounterValue;
        !          1649:    }
        !          1650:    else
        !          1651:    {
        !          1652:        pLine->lnaCounterValue[0] = *(LARGE_INTEGER *) pCounterValue;
        !          1653:    }
        !          1654: 
        !          1655:    // Get second counter, only if we are not at
        !          1656:    // the end of the counters; some computations
        !          1657:    // require a second counter
        !          1658: 
        !          1659:    if ( pCounterDef2 ) {
        !          1660:        pLine->lnaOldCounterValue[1] =
        !          1661:            pLine->lnaCounterValue[1] ;
        !          1662:        if (pCounterDef2->CounterSize <= 4)
        !          1663:        {
        !          1664:            // HighPart was initialize to 0
        !          1665:            pLine->lnaCounterValue[1].LowPart = *pCounterValue2;
        !          1666:        }
        !          1667:        else
        !          1668:            pLine->lnaCounterValue[1] =
        !          1669:                *((LARGE_INTEGER *) pCounterValue2);
        !          1670:       }
        !          1671:    return (TRUE) ;
        !          1672: }  // UpdateLineData
        !          1673: 
        !          1674: 
        !          1675: 
        !          1676: BOOL UpdateSystemData (PPERFSYSTEM pSystem, 
        !          1677:                        PPERFDATA *ppPerfData)
        !          1678:    {  // UpdateSystemData
        !          1679:    #define        PERF_SYSTEM_TIMEOUT (60L * 1000L)
        !          1680:    long           lError ;
        !          1681:    DWORD          Status ;
        !          1682:    DWORD          Size;
        !          1683: 
        !          1684:    if (!ppPerfData)
        !          1685:       return (FALSE) ;
        !          1686: 
        !          1687:    while (TRUE)
        !          1688:       {
        !          1689:       if (pSystem->FailureTime)
        !          1690:          {
        !          1691:          if (GetTickCount() > pSystem->FailureTime + PERF_SYSTEM_TIMEOUT)
        !          1692:             {
        !          1693:             // free any memory hanging off this system
        !          1694:             SystemFree (pSystem, FALSE) ;
        !          1695: 
        !          1696:             // get the registry info
        !          1697:             pSystem->sysDataKey = OpenSystemPerfData(pSystem->sysName) ;
        !          1698: 
        !          1699:             Status = !ERROR_SUCCESS ;
        !          1700:             if (pSystem->sysDataKey) 
        !          1701:                {
        !          1702:                Status = GetSystemNames(pSystem);
        !          1703:                }
        !          1704: 
        !          1705:             if (Status != ERROR_SUCCESS)
        !          1706:                {
        !          1707:                // something wrong in getting the registry info,
        !          1708:                // remote system must be still down (??)
        !          1709:                pSystem->FailureTime = GetTickCount();
        !          1710: 
        !          1711:                // Free any memory that may have created
        !          1712:                SystemFree (pSystem, FALSE) ;
        !          1713: 
        !          1714:                return (FALSE) ;
        !          1715:                }
        !          1716: 
        !          1717:             // time to check again
        !          1718:             pSystem->FailureTime = 0 ;
        !          1719:             }
        !          1720:          else
        !          1721:             {
        !          1722:             // not time to check again
        !          1723:             return (FALSE) ;
        !          1724:             }
        !          1725:          }
        !          1726: 
        !          1727:       if (pSystem->FailureTime == 0 )
        !          1728:          {
        !          1729:          Size = MemorySize (*ppPerfData); 
        !          1730:          lError = GetSystemPerfData (pSystem->sysDataKey,
        !          1731:                                      pSystem->lpszValue,
        !          1732:                                      *ppPerfData,
        !          1733:                                      &Size) ;
        !          1734:          if ((!lError) &&
        !          1735:             (Size > 0) &&
        !          1736:             (*ppPerfData)->Signature[0] == (WCHAR)'P' &&
        !          1737:             (*ppPerfData)->Signature[1] == (WCHAR)'E' &&
        !          1738:             (*ppPerfData)->Signature[2] == (WCHAR)'R' &&
        !          1739:             (*ppPerfData)->Signature[3] == (WCHAR)'F' )
        !          1740:                return (TRUE) ;
        !          1741: 
        !          1742:          if (lError == ERROR_MORE_DATA)
        !          1743:             {
        !          1744:             *ppPerfData = MemoryResize (*ppPerfData, 
        !          1745:                                         MemorySize (*ppPerfData) +
        !          1746:                                         dwPerfDataIncrease) ;
        !          1747:             if (!*ppPerfData)
        !          1748:                {
        !          1749:                pSystem->FailureTime = GetTickCount();
        !          1750:                return (FALSE) ;
        !          1751:                }
        !          1752:             }
        !          1753:          else
        !          1754:             {
        !          1755:             pSystem->FailureTime = GetTickCount();
        !          1756:             return (FALSE) ;
        !          1757:             }  // else
        !          1758:          } // if
        !          1759:       }  // while
        !          1760:    }  // UpdateSystemData
        !          1761: 
        !          1762: 
        !          1763: 
        !          1764: void FailedLinesForSystem (LPTSTR lpszSystem,
        !          1765:                            PPERFDATA pPerfData, 
        !          1766:                            PLINE pLineFirst)
        !          1767:    {  // FailedLinesForSystem
        !          1768:    PLINE          pLine ;
        !          1769: 
        !          1770:    for (pLine = pLineFirst ;
        !          1771:         pLine ;
        !          1772:         pLine = pLine->pLineNext)
        !          1773:       {  // for pLine
        !          1774:       if (strsamei (lpszSystem, pLine->lnSystemName))
        !          1775:          {
        !          1776:          FailedLineData (pPerfData, pLine) ;
        !          1777:          if (pLine->bFirstTime)
        !          1778:             {
        !          1779:             pLine->bFirstTime-- ;
        !          1780:             }
        !          1781:          }
        !          1782:       }  // for pLine
        !          1783:    }
        !          1784: 
        !          1785: 
        !          1786: BOOL UpdateLinesForSystem (LPTSTR lpszSystem, 
        !          1787:                            PPERFDATA pPerfData, 
        !          1788:                            PLINE pLineFirst)
        !          1789:    {  // UpdateLinesForSystem
        !          1790:    PLINE          pLine ;
        !          1791:    BOOL           bMatchFound = FALSE ;   // no line from this system
        !          1792: 
        !          1793:    for (pLine = pLineFirst ;
        !          1794:         pLine ;
        !          1795:         pLine = pLine->pLineNext)
        !          1796:       {  // for pLine
        !          1797:       if (strsamei (lpszSystem, pLine->lnSystemName))
        !          1798:          {
        !          1799:          UpdateLineData (pPerfData, pLine) ;
        !          1800:          if (pLine->bFirstTime)
        !          1801:             {
        !          1802:             pLine->bFirstTime-- ;
        !          1803:             }
        !          1804:          bMatchFound = TRUE ; // one or more lines from this system
        !          1805:          }
        !          1806:       }  // for pLine
        !          1807: 
        !          1808:    return (bMatchFound) ;
        !          1809:    }
        !          1810: 
        !          1811: 
        !          1812: BOOL UpdateLines (PPPERFSYSTEM ppSystemFirst,
        !          1813:                   PLINE pLineFirst)
        !          1814:    {
        !          1815:    PPERFSYSTEM       pSystem ;
        !          1816:    int               iNoUseSystemDetected = 0 ;
        !          1817: 
        !          1818:    //=============================//
        !          1819:    // Update Each System          //
        !          1820:    //=============================//
        !          1821: 
        !          1822:    for (pSystem = *ppSystemFirst ;
        !          1823:         pSystem ;
        !          1824:         pSystem = pSystem->pSystemNext)
        !          1825:        {  // for
        !          1826: 
        !          1827:        //=============================//
        !          1828:        // Update Each Line            //
        !          1829:        //=============================//
        !          1830: 
        !          1831:        if (!UpdateSystemData (pSystem, &pPerfData))
        !          1832:           {
        !          1833:           FailedLinesForSystem (pSystem->sysName, pPerfData, pLineFirst) ;
        !          1834:           }
        !          1835:        else
        !          1836:           { 
        !          1837:           if (!UpdateLinesForSystem (pSystem->sysName, pPerfData, pLineFirst))
        !          1838:              {
        !          1839:              if (!bAddLineInProgress)
        !          1840:                 { 
        !          1841:                 // mark this system as no-longer-needed
        !          1842:                 iNoUseSystemDetected++ ;
        !          1843:                 pSystem->bSystemNoLongerNeeded = TRUE ;
        !          1844:                 }
        !          1845:              }
        !          1846:           }
        !          1847:        }  // for
        !          1848: 
        !          1849:    if (iNoUseSystemDetected)
        !          1850:        {
        !          1851:        // some unused system(s) detected.
        !          1852:        DeleteUnusedSystems (ppSystemFirst, iNoUseSystemDetected) ;
        !          1853:        }
        !          1854: 
        !          1855:    return (TRUE) ;
        !          1856:    }  // UpdateLines
        !          1857:                      
        !          1858: 
        !          1859: 
        !          1860: BOOL PerfDataInitializeInstance (void)
        !          1861:    {
        !          1862:    pPerfData = MemoryAllocate (STARTING_SYSINFO_SIZE) ;
        !          1863:    return (pPerfData != NULL) ;
        !          1864:    }
        !          1865: 
        !          1866: NTSTATUS  AddNamesToArray (LPTSTR lpNames,
        !          1867:    DWORD    dwLastId,
        !          1868:    LPWSTR   *lpCounterId)
        !          1869:    {
        !          1870:    LPWSTR      lpThisName;
        !          1871:    LPWSTR      lpStopString;
        !          1872:    DWORD       dwThisCounter;
        !          1873: //   UNICODE_STRING  usTemp;
        !          1874:    NTSTATUS    Status = ERROR_SUCCESS;
        !          1875:    
        !          1876:    for (lpThisName = lpNames;
        !          1877:         *lpThisName;
        !          1878:         lpThisName += (lstrlen(lpThisName)+1) )
        !          1879:       {
        !          1880: 
        !          1881:       // first string should be an integer (in decimal unicode digits)
        !          1882: 
        !          1883: //      usTemp.Length = lstrlen(lpThisName) * sizeof (WCHAR);
        !          1884: //      usTemp.MaximumLength = usTemp.Length + sizeof (UNICODE_NULL);
        !          1885: //      usTemp.Buffer = lpThisName;
        !          1886: 
        !          1887: //      Status = RtlUnicodeStringToInteger (
        !          1888: //         &usTemp,
        !          1889: //         10L,
        !          1890: //         &dwThisCounter);
        !          1891: 
        !          1892:       dwThisCounter = wcstoul(lpThisName, &lpStopString, 10);
        !          1893: 
        !          1894:       if ((dwThisCounter == 0) || (dwThisCounter == ULONG_MAX))
        !          1895:       {
        !          1896:          Status += 1;
        !          1897:          goto ADD_BAILOUT;  // bad entry
        !          1898:       }
        !          1899:         
        !          1900:       // point to corresponding counter name
        !          1901: 
        !          1902:       lpThisName += (lstrlen(lpThisName)+1);  
        !          1903: 
        !          1904:       if (dwThisCounter <= dwLastId)
        !          1905:          {
        !          1906: 
        !          1907:          // and load array element;
        !          1908: 
        !          1909:          lpCounterId[dwThisCounter] = lpThisName;
        !          1910: 
        !          1911:          }
        !          1912:       }
        !          1913: 
        !          1914: ADD_BAILOUT:
        !          1915:    return (Status) ;
        !          1916:    }
        !          1917: 
        !          1918: 

unix.superglobalmegacorp.com

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