|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.