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