|
|
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.