cmd: Remove unused declarations of echo_mode.
[wine] / programs / taskmgr / perfdata.c
1 /*
2  *  ReactOS Task Manager
3  *
4  *  perfdata.c
5  *
6  *  Copyright (C) 1999 - 2001  Brian Palmer  <brianp@reactos.org>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22     
23 #define WIN32_LEAN_AND_MEAN    /* Exclude rarely-used stuff from Windows headers */
24 #include <windows.h>
25 #include <commctrl.h>
26 #include <stdlib.h>
27 #include <memory.h>
28 #include <tchar.h>
29 #include <stdio.h>
30 #include <winnt.h>
31 #include "taskmgr.h"
32 #include "perfdata.h"
33
34 static PROCNTQSI                       NtQuerySystemInformation = NULL;
35 static PROCGGR                         pGetGuiResources = NULL;
36 static PROCGPIC                        pGetProcessIoCounters = NULL;
37 static CRITICAL_SECTION                PerfDataCriticalSection;
38 static PPERFDATA                       pPerfDataOld = NULL;    /* Older perf data (saved to establish delta values) */
39 static PPERFDATA                       pPerfData = NULL;    /* Most recent copy of perf data */
40 static ULONG                           ProcessCountOld = 0;
41 static ULONG                           ProcessCount = 0;
42 static double                          dbIdleTime;
43 static double                          dbKernelTime;
44 static double                          dbSystemTime;
45 static LARGE_INTEGER                   liOldIdleTime = {{0,0}};
46 static double                          OldKernelTime = 0;
47 static LARGE_INTEGER                   liOldSystemTime = {{0,0}};
48 static SYSTEM_PERFORMANCE_INFORMATION  SystemPerfInfo;
49 static SYSTEM_BASIC_INFORMATION        SystemBasicInfo;
50 static SYSTEM_CACHE_INFORMATION        SystemCacheInfo;
51 static SYSTEM_HANDLE_INFORMATION       SystemHandleInfo;
52 static PSYSTEM_PROCESSORTIME_INFO      SystemProcessorTimeInfo = NULL;
53
54 BOOL PerfDataInitialize(void)
55 {
56     LONG    status;
57     static const WCHAR wszNtdll[] = {'n','t','d','l','l','.','d','l','l',0};
58     static const WCHAR wszUser32[] = {'u','s','e','r','3','2','.','d','l','l',0};
59     static const WCHAR wszKernel32[] = {'k','e','r','n','e','l','3','2','.','d','l','l',0};
60
61     NtQuerySystemInformation = (PROCNTQSI)GetProcAddress(GetModuleHandleW(wszNtdll), "NtQuerySystemInformation");
62     pGetGuiResources = (PROCGGR)GetProcAddress(GetModuleHandleW(wszUser32), "GetGuiResources");
63     pGetProcessIoCounters = (PROCGPIC)GetProcAddress(GetModuleHandleW(wszKernel32), "GetProcessIoCounters");
64     
65     InitializeCriticalSection(&PerfDataCriticalSection);
66     
67     if (!NtQuerySystemInformation)
68         return FALSE;
69     
70     /*
71      * Get number of processors in the system
72      */
73     status = NtQuerySystemInformation(SystemBasicInformation, &SystemBasicInfo, sizeof(SystemBasicInfo), NULL);
74     if (status != NO_ERROR)
75         return FALSE;
76     
77     return TRUE;
78 }
79
80 void PerfDataUninitialize(void)
81 {
82     NtQuerySystemInformation = NULL;
83
84     DeleteCriticalSection(&PerfDataCriticalSection);
85 }
86
87 void PerfDataRefresh(void)
88 {
89     ULONG                            ulSize;
90     LONG                            status;
91     LPBYTE                            pBuffer;
92     ULONG                            BufferSize;
93     PSYSTEM_PROCESS_INFORMATION        pSPI;
94     PPERFDATA                        pPDOld;
95     ULONG                            Idx, Idx2;
96     HANDLE                            hProcess;
97     HANDLE                            hProcessToken;
98     WCHAR                            wszTemp[MAX_PATH];
99     DWORD                            dwSize;
100     SYSTEM_PERFORMANCE_INFORMATION    SysPerfInfo;
101     SYSTEM_TIME_INFORMATION            SysTimeInfo;
102     SYSTEM_CACHE_INFORMATION        SysCacheInfo;
103     LPBYTE                            SysHandleInfoData;
104     PSYSTEM_PROCESSORTIME_INFO        SysProcessorTimeInfo;
105     double                            CurrentKernelTime;
106
107
108     if (!NtQuerySystemInformation)
109         return;
110
111     /* Get new system time */
112     status = NtQuerySystemInformation(SystemTimeInformation, &SysTimeInfo, sizeof(SysTimeInfo), 0);
113     if (status != NO_ERROR)
114         return;
115
116     /* Get new CPU's idle time */
117     status = NtQuerySystemInformation(SystemPerformanceInformation, &SysPerfInfo, sizeof(SysPerfInfo), NULL);
118     if (status != NO_ERROR)
119         return;
120
121     /* Get system cache information */
122     status = NtQuerySystemInformation(SystemCacheInformation, &SysCacheInfo, sizeof(SysCacheInfo), NULL);
123     if (status != NO_ERROR)
124         return;
125
126     /* Get processor time information */
127     SysProcessorTimeInfo = HeapAlloc(GetProcessHeap(), 0,
128                                 sizeof(SYSTEM_PROCESSORTIME_INFO) * SystemBasicInfo.bKeNumberProcessors);
129     status = NtQuerySystemInformation(SystemProcessorTimeInformation, SysProcessorTimeInfo, sizeof(SYSTEM_PROCESSORTIME_INFO) * SystemBasicInfo.bKeNumberProcessors, &ulSize);
130     if (status != NO_ERROR) {
131         HeapFree(GetProcessHeap(), 0, SysProcessorTimeInfo);
132         return;
133     }
134
135     /* Get handle information
136      * We don't know how much data there is so just keep
137      * increasing the buffer size until the call succeeds
138      */
139     BufferSize = 0;
140     do
141     {
142         BufferSize += 0x10000;
143         SysHandleInfoData = HeapAlloc(GetProcessHeap(), 0, BufferSize);
144
145         status = NtQuerySystemInformation(SystemHandleInformation, SysHandleInfoData, BufferSize, &ulSize);
146
147         if (status == 0xC0000004 /*STATUS_INFO_LENGTH_MISMATCH*/) {
148             HeapFree(GetProcessHeap(), 0, SysHandleInfoData);
149         }
150
151     } while (status == 0xC0000004 /*STATUS_INFO_LENGTH_MISMATCH*/);
152
153     /* Get process information
154      * We don't know how much data there is so just keep
155      * increasing the buffer size until the call succeeds
156      */
157     BufferSize = 0;
158     do
159     {
160         BufferSize += 0x10000;
161         pBuffer = HeapAlloc(GetProcessHeap(), 0, BufferSize);
162
163         status = NtQuerySystemInformation(SystemProcessInformation, pBuffer, BufferSize, &ulSize);
164
165         if (status == 0xC0000004 /*STATUS_INFO_LENGTH_MISMATCH*/) {
166             HeapFree(GetProcessHeap(), 0, pBuffer);
167         }
168
169     } while (status == 0xC0000004 /*STATUS_INFO_LENGTH_MISMATCH*/);
170
171     EnterCriticalSection(&PerfDataCriticalSection);
172
173     /*
174      * Save system performance info
175      */
176     memcpy(&SystemPerfInfo, &SysPerfInfo, sizeof(SYSTEM_PERFORMANCE_INFORMATION));
177
178     /*
179      * Save system cache info
180      */
181     memcpy(&SystemCacheInfo, &SysCacheInfo, sizeof(SYSTEM_CACHE_INFORMATION));
182     
183     /*
184      * Save system processor time info
185      */
186     HeapFree(GetProcessHeap(), 0, SystemProcessorTimeInfo);
187     SystemProcessorTimeInfo = SysProcessorTimeInfo;
188     
189     /*
190      * Save system handle info
191      */
192     memcpy(&SystemHandleInfo, SysHandleInfoData, sizeof(SYSTEM_HANDLE_INFORMATION));
193     HeapFree(GetProcessHeap(), 0, SysHandleInfoData);
194     
195     for (CurrentKernelTime=0, Idx=0; Idx<SystemBasicInfo.bKeNumberProcessors; Idx++) {
196         CurrentKernelTime += Li2Double(SystemProcessorTimeInfo[Idx].KernelTime);
197         CurrentKernelTime += Li2Double(SystemProcessorTimeInfo[Idx].DpcTime);
198         CurrentKernelTime += Li2Double(SystemProcessorTimeInfo[Idx].InterruptTime);
199     }
200
201     /* If it's a first call - skip idle time calcs */
202     if (liOldIdleTime.QuadPart != 0) {
203         /*  CurrentValue = NewValue - OldValue */
204         dbIdleTime = Li2Double(SysPerfInfo.liIdleTime) - Li2Double(liOldIdleTime);
205         dbKernelTime = CurrentKernelTime - OldKernelTime;
206         dbSystemTime = Li2Double(SysTimeInfo.liKeSystemTime) - Li2Double(liOldSystemTime);
207
208         /*  CurrentCpuIdle = IdleTime / SystemTime */
209         dbIdleTime = dbIdleTime / dbSystemTime;
210         dbKernelTime = dbKernelTime / dbSystemTime;
211         
212         /*  CurrentCpuUsage% = 100 - (CurrentCpuIdle * 100) / NumberOfProcessors */
213         dbIdleTime = 100.0 - dbIdleTime * 100.0 / (double)SystemBasicInfo.bKeNumberProcessors; /* + 0.5; */
214         dbKernelTime = 100.0 - dbKernelTime * 100.0 / (double)SystemBasicInfo.bKeNumberProcessors; /* + 0.5; */
215     }
216
217     /* Store new CPU's idle and system time */
218     liOldIdleTime = SysPerfInfo.liIdleTime;
219     liOldSystemTime = SysTimeInfo.liKeSystemTime;
220     OldKernelTime = CurrentKernelTime;
221
222     /* Determine the process count
223      * We loop through the data we got from NtQuerySystemInformation
224      * and count how many structures there are (until RelativeOffset is 0)
225      */
226     ProcessCountOld = ProcessCount;
227     ProcessCount = 0;
228     pSPI = (PSYSTEM_PROCESS_INFORMATION)pBuffer;
229     while (pSPI) {
230         ProcessCount++;
231         if (pSPI->RelativeOffset == 0)
232             break;
233         pSPI = (PSYSTEM_PROCESS_INFORMATION)((LPBYTE)pSPI + pSPI->RelativeOffset);
234     }
235
236     /* Now alloc a new PERFDATA array and fill in the data */
237     HeapFree(GetProcessHeap(), 0, pPerfDataOld);
238     pPerfDataOld = pPerfData;
239     pPerfData = HeapAlloc(GetProcessHeap(), 0, sizeof(PERFDATA) * ProcessCount);
240     pSPI = (PSYSTEM_PROCESS_INFORMATION)pBuffer;
241     for (Idx=0; Idx<ProcessCount; Idx++) {
242         /* Get the old perf data for this process (if any) */
243         /* so that we can establish delta values */
244         pPDOld = NULL;
245         for (Idx2=0; Idx2<ProcessCountOld; Idx2++) {
246             if (pPerfDataOld[Idx2].ProcessId == pSPI->ProcessId) {
247                 pPDOld = &pPerfDataOld[Idx2];
248                 break;
249             }
250         }
251
252         /* Clear out process perf data structure */
253         memset(&pPerfData[Idx], 0, sizeof(PERFDATA));
254
255         if (pSPI->Name.Buffer)
256             lstrcpyW(pPerfData[Idx].ImageName, pSPI->Name.Buffer);
257         else
258         {
259             WCHAR idleW[255];
260             LoadStringW(hInst, IDS_SYSTEM_IDLE_PROCESS, idleW, sizeof(idleW)/sizeof(WCHAR));
261             lstrcpyW(pPerfData[Idx].ImageName, idleW );
262         }
263
264         pPerfData[Idx].ProcessId = pSPI->ProcessId;
265
266         if (pPDOld)    {
267             double    CurTime = Li2Double(pSPI->KernelTime) + Li2Double(pSPI->UserTime);
268             double    OldTime = Li2Double(pPDOld->KernelTime) + Li2Double(pPDOld->UserTime);
269             double    CpuTime = (CurTime - OldTime) / dbSystemTime;
270             CpuTime = CpuTime * 100.0 / (double)SystemBasicInfo.bKeNumberProcessors; /* + 0.5; */
271             pPerfData[Idx].CPUUsage = (ULONG)CpuTime;
272         }
273         pPerfData[Idx].CPUTime.QuadPart = pSPI->UserTime.QuadPart + pSPI->KernelTime.QuadPart;
274         pPerfData[Idx].WorkingSetSizeBytes = pSPI->TotalWorkingSetSizeBytes;
275         pPerfData[Idx].PeakWorkingSetSizeBytes = pSPI->PeakWorkingSetSizeBytes;
276         if (pPDOld)
277             pPerfData[Idx].WorkingSetSizeDelta = labs((LONG)pSPI->TotalWorkingSetSizeBytes - (LONG)pPDOld->WorkingSetSizeBytes);
278         else
279             pPerfData[Idx].WorkingSetSizeDelta = 0;
280         pPerfData[Idx].PageFaultCount = pSPI->PageFaultCount;
281         if (pPDOld)
282             pPerfData[Idx].PageFaultCountDelta = labs((LONG)pSPI->PageFaultCount - (LONG)pPDOld->PageFaultCount);
283         else
284             pPerfData[Idx].PageFaultCountDelta = 0;
285         pPerfData[Idx].VirtualMemorySizeBytes = pSPI->TotalVirtualSizeBytes;
286         pPerfData[Idx].PagedPoolUsagePages = pSPI->TotalPagedPoolUsagePages;
287         pPerfData[Idx].NonPagedPoolUsagePages = pSPI->TotalNonPagedPoolUsagePages;
288         pPerfData[Idx].BasePriority = pSPI->BasePriority;
289         pPerfData[Idx].HandleCount = pSPI->HandleCount;
290         pPerfData[Idx].ThreadCount = pSPI->ThreadCount;
291         pPerfData[Idx].SessionId = pSPI->SessionId;
292         
293         hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pSPI->ProcessId);
294         if (hProcess) {
295             if (OpenProcessToken(hProcess, TOKEN_QUERY|TOKEN_DUPLICATE|TOKEN_IMPERSONATE, &hProcessToken)) {
296                 ImpersonateLoggedOnUser(hProcessToken);
297                 memset(wszTemp, 0, sizeof(wszTemp));
298                 dwSize = MAX_PATH;
299                 GetUserNameW(wszTemp, &dwSize);
300                 RevertToSelf();
301                 CloseHandle(hProcessToken);
302             }
303             if (pGetGuiResources) {
304                 pPerfData[Idx].USERObjectCount = pGetGuiResources(hProcess, GR_USEROBJECTS);
305                 pPerfData[Idx].GDIObjectCount = pGetGuiResources(hProcess, GR_GDIOBJECTS);
306             }
307             if (pGetProcessIoCounters)
308                 pGetProcessIoCounters(hProcess, &pPerfData[Idx].IOCounters);
309             CloseHandle(hProcess);
310         }
311         pPerfData[Idx].UserTime.QuadPart = pSPI->UserTime.QuadPart;
312         pPerfData[Idx].KernelTime.QuadPart = pSPI->KernelTime.QuadPart;
313         pSPI = (PSYSTEM_PROCESS_INFORMATION)((LPBYTE)pSPI + pSPI->RelativeOffset);
314     }
315     HeapFree(GetProcessHeap(), 0, pBuffer);
316     LeaveCriticalSection(&PerfDataCriticalSection);
317 }
318
319 ULONG PerfDataGetProcessCount(void)
320 {
321     return ProcessCount;
322 }
323
324 ULONG PerfDataGetProcessorUsage(void)
325 {
326     if( dbIdleTime < 0.0 )
327         return 0;
328     if( dbIdleTime > 100.0 )
329         return 100;
330     return (ULONG)dbIdleTime;
331 }
332
333 ULONG PerfDataGetProcessorSystemUsage(void)
334 {
335     if( dbKernelTime < 0.0 )
336         return 0;
337     if( dbKernelTime > 100.0 )
338         return 100;
339     return (ULONG)dbKernelTime;
340 }
341
342 BOOL PerfDataGetImageName(ULONG Index, LPWSTR lpImageName, int nMaxCount)
343 {
344     BOOL    bSuccessful;
345
346     EnterCriticalSection(&PerfDataCriticalSection);
347
348     if (Index < ProcessCount) {
349         wcsncpy(lpImageName, pPerfData[Index].ImageName, nMaxCount);
350         bSuccessful = TRUE;
351     } else {
352         bSuccessful = FALSE;
353     }
354     LeaveCriticalSection(&PerfDataCriticalSection);
355     return bSuccessful;
356 }
357
358 ULONG PerfDataGetProcessId(ULONG Index)
359 {
360     ULONG    ProcessId;
361
362     EnterCriticalSection(&PerfDataCriticalSection);
363
364     if (Index < ProcessCount)
365         ProcessId = pPerfData[Index].ProcessId;
366     else
367         ProcessId = 0;
368
369     LeaveCriticalSection(&PerfDataCriticalSection);
370
371     return ProcessId;
372 }
373
374 BOOL PerfDataGetUserName(ULONG Index, LPWSTR lpUserName, int nMaxCount)
375 {
376     BOOL    bSuccessful;
377
378     EnterCriticalSection(&PerfDataCriticalSection);
379
380     if (Index < ProcessCount) {
381         wcsncpy(lpUserName, pPerfData[Index].UserName, nMaxCount);
382         bSuccessful = TRUE;
383     } else {
384         bSuccessful = FALSE;
385     }
386
387     LeaveCriticalSection(&PerfDataCriticalSection);
388
389     return bSuccessful;
390 }
391
392 ULONG PerfDataGetSessionId(ULONG Index)
393 {
394     ULONG    SessionId;
395
396     EnterCriticalSection(&PerfDataCriticalSection);
397
398     if (Index < ProcessCount)
399         SessionId = pPerfData[Index].SessionId;
400     else
401         SessionId = 0;
402
403     LeaveCriticalSection(&PerfDataCriticalSection);
404
405     return SessionId;
406 }
407
408 ULONG PerfDataGetCPUUsage(ULONG Index)
409 {
410     ULONG    CpuUsage;
411
412     EnterCriticalSection(&PerfDataCriticalSection);
413
414     if (Index < ProcessCount)
415         CpuUsage = pPerfData[Index].CPUUsage;
416     else
417         CpuUsage = 0;
418
419     LeaveCriticalSection(&PerfDataCriticalSection);
420
421     return CpuUsage;
422 }
423
424 TIME PerfDataGetCPUTime(ULONG Index)
425 {
426     TIME    CpuTime = {{0,0}};
427
428     EnterCriticalSection(&PerfDataCriticalSection);
429
430     if (Index < ProcessCount)
431         CpuTime = pPerfData[Index].CPUTime;
432
433     LeaveCriticalSection(&PerfDataCriticalSection);
434
435     return CpuTime;
436 }
437
438 ULONG PerfDataGetWorkingSetSizeBytes(ULONG Index)
439 {
440     ULONG    WorkingSetSizeBytes;
441
442     EnterCriticalSection(&PerfDataCriticalSection);
443
444     if (Index < ProcessCount)
445         WorkingSetSizeBytes = pPerfData[Index].WorkingSetSizeBytes;
446     else
447         WorkingSetSizeBytes = 0;
448
449     LeaveCriticalSection(&PerfDataCriticalSection);
450
451     return WorkingSetSizeBytes;
452 }
453
454 ULONG PerfDataGetPeakWorkingSetSizeBytes(ULONG Index)
455 {
456     ULONG    PeakWorkingSetSizeBytes;
457
458     EnterCriticalSection(&PerfDataCriticalSection);
459
460     if (Index < ProcessCount)
461         PeakWorkingSetSizeBytes = pPerfData[Index].PeakWorkingSetSizeBytes;
462     else
463         PeakWorkingSetSizeBytes = 0;
464
465     LeaveCriticalSection(&PerfDataCriticalSection);
466
467     return PeakWorkingSetSizeBytes;
468 }
469
470 ULONG PerfDataGetWorkingSetSizeDelta(ULONG Index)
471 {
472     ULONG    WorkingSetSizeDelta;
473
474     EnterCriticalSection(&PerfDataCriticalSection);
475
476     if (Index < ProcessCount)
477         WorkingSetSizeDelta = pPerfData[Index].WorkingSetSizeDelta;
478     else
479         WorkingSetSizeDelta = 0;
480
481     LeaveCriticalSection(&PerfDataCriticalSection);
482
483     return WorkingSetSizeDelta;
484 }
485
486 ULONG PerfDataGetPageFaultCount(ULONG Index)
487 {
488     ULONG    PageFaultCount;
489
490     EnterCriticalSection(&PerfDataCriticalSection);
491
492     if (Index < ProcessCount)
493         PageFaultCount = pPerfData[Index].PageFaultCount;
494     else
495         PageFaultCount = 0;
496
497     LeaveCriticalSection(&PerfDataCriticalSection);
498
499     return PageFaultCount;
500 }
501
502 ULONG PerfDataGetPageFaultCountDelta(ULONG Index)
503 {
504     ULONG    PageFaultCountDelta;
505
506     EnterCriticalSection(&PerfDataCriticalSection);
507
508     if (Index < ProcessCount)
509         PageFaultCountDelta = pPerfData[Index].PageFaultCountDelta;
510     else
511         PageFaultCountDelta = 0;
512
513     LeaveCriticalSection(&PerfDataCriticalSection);
514
515     return PageFaultCountDelta;
516 }
517
518 ULONG PerfDataGetVirtualMemorySizeBytes(ULONG Index)
519 {
520     ULONG    VirtualMemorySizeBytes;
521
522     EnterCriticalSection(&PerfDataCriticalSection);
523
524     if (Index < ProcessCount)
525         VirtualMemorySizeBytes = pPerfData[Index].VirtualMemorySizeBytes;
526     else
527         VirtualMemorySizeBytes = 0;
528
529     LeaveCriticalSection(&PerfDataCriticalSection);
530
531     return VirtualMemorySizeBytes;
532 }
533
534 ULONG PerfDataGetPagedPoolUsagePages(ULONG Index)
535 {
536     ULONG    PagedPoolUsagePages;
537
538     EnterCriticalSection(&PerfDataCriticalSection);
539
540     if (Index < ProcessCount)
541         PagedPoolUsagePages = pPerfData[Index].PagedPoolUsagePages;
542     else
543         PagedPoolUsagePages = 0;
544
545     LeaveCriticalSection(&PerfDataCriticalSection);
546
547     return PagedPoolUsagePages;
548 }
549
550 ULONG PerfDataGetNonPagedPoolUsagePages(ULONG Index)
551 {
552     ULONG    NonPagedPoolUsagePages;
553
554     EnterCriticalSection(&PerfDataCriticalSection);
555
556     if (Index < ProcessCount)
557         NonPagedPoolUsagePages = pPerfData[Index].NonPagedPoolUsagePages;
558     else
559         NonPagedPoolUsagePages = 0;
560
561     LeaveCriticalSection(&PerfDataCriticalSection);
562
563     return NonPagedPoolUsagePages;
564 }
565
566 ULONG PerfDataGetBasePriority(ULONG Index)
567 {
568     ULONG    BasePriority;
569
570     EnterCriticalSection(&PerfDataCriticalSection);
571
572     if (Index < ProcessCount)
573         BasePriority = pPerfData[Index].BasePriority;
574     else
575         BasePriority = 0;
576
577     LeaveCriticalSection(&PerfDataCriticalSection);
578
579     return BasePriority;
580 }
581
582 ULONG PerfDataGetHandleCount(ULONG Index)
583 {
584     ULONG    HandleCount;
585
586     EnterCriticalSection(&PerfDataCriticalSection);
587
588     if (Index < ProcessCount)
589         HandleCount = pPerfData[Index].HandleCount;
590     else
591         HandleCount = 0;
592
593     LeaveCriticalSection(&PerfDataCriticalSection);
594
595     return HandleCount;
596 }
597
598 ULONG PerfDataGetThreadCount(ULONG Index)
599 {
600     ULONG    ThreadCount;
601
602     EnterCriticalSection(&PerfDataCriticalSection);
603
604     if (Index < ProcessCount)
605         ThreadCount = pPerfData[Index].ThreadCount;
606     else
607         ThreadCount = 0;
608
609     LeaveCriticalSection(&PerfDataCriticalSection);
610
611     return ThreadCount;
612 }
613
614 ULONG PerfDataGetUSERObjectCount(ULONG Index)
615 {
616     ULONG    USERObjectCount;
617
618     EnterCriticalSection(&PerfDataCriticalSection);
619
620     if (Index < ProcessCount)
621         USERObjectCount = pPerfData[Index].USERObjectCount;
622     else
623         USERObjectCount = 0;
624
625     LeaveCriticalSection(&PerfDataCriticalSection);
626
627     return USERObjectCount;
628 }
629
630 ULONG PerfDataGetGDIObjectCount(ULONG Index)
631 {
632     ULONG    GDIObjectCount;
633
634     EnterCriticalSection(&PerfDataCriticalSection);
635
636     if (Index < ProcessCount)
637         GDIObjectCount = pPerfData[Index].GDIObjectCount;
638     else
639         GDIObjectCount = 0;
640
641     LeaveCriticalSection(&PerfDataCriticalSection);
642
643     return GDIObjectCount;
644 }
645
646 BOOL PerfDataGetIOCounters(ULONG Index, PIO_COUNTERS pIoCounters)
647 {
648     BOOL    bSuccessful;
649
650     EnterCriticalSection(&PerfDataCriticalSection);
651
652     if (Index < ProcessCount)
653     {
654         memcpy(pIoCounters, &pPerfData[Index].IOCounters, sizeof(IO_COUNTERS));
655         bSuccessful = TRUE;
656     }
657     else
658         bSuccessful = FALSE;
659
660     LeaveCriticalSection(&PerfDataCriticalSection);
661
662     return bSuccessful;
663 }
664
665 ULONG PerfDataGetCommitChargeTotalK(void)
666 {
667     ULONG    Total;
668     ULONG    PageSize;
669
670     EnterCriticalSection(&PerfDataCriticalSection);
671
672     Total = SystemPerfInfo.MmTotalCommittedPages;
673     PageSize = SystemBasicInfo.uPageSize;
674
675     LeaveCriticalSection(&PerfDataCriticalSection);
676
677     Total = Total * (PageSize / 1024);
678
679     return Total;
680 }
681
682 ULONG PerfDataGetCommitChargeLimitK(void)
683 {
684     ULONG    Limit;
685     ULONG    PageSize;
686
687     EnterCriticalSection(&PerfDataCriticalSection);
688
689     Limit = SystemPerfInfo.MmTotalCommitLimit;
690     PageSize = SystemBasicInfo.uPageSize;
691
692     LeaveCriticalSection(&PerfDataCriticalSection);
693
694     Limit = Limit * (PageSize / 1024);
695
696     return Limit;
697 }
698
699 ULONG PerfDataGetCommitChargePeakK(void)
700 {
701     ULONG    Peak;
702     ULONG    PageSize;
703
704     EnterCriticalSection(&PerfDataCriticalSection);
705
706     Peak = SystemPerfInfo.MmPeakLimit;
707     PageSize = SystemBasicInfo.uPageSize;
708
709     LeaveCriticalSection(&PerfDataCriticalSection);
710
711     Peak = Peak * (PageSize / 1024);
712
713     return Peak;
714 }
715
716 ULONG PerfDataGetKernelMemoryTotalK(void)
717 {
718     ULONG    Total;
719     ULONG    Paged;
720     ULONG    NonPaged;
721     ULONG    PageSize;
722
723     EnterCriticalSection(&PerfDataCriticalSection);
724
725     Paged = SystemPerfInfo.PoolPagedBytes;
726     NonPaged = SystemPerfInfo.PoolNonPagedBytes;
727     PageSize = SystemBasicInfo.uPageSize;
728
729     LeaveCriticalSection(&PerfDataCriticalSection);
730
731     Paged = Paged * (PageSize / 1024);
732     NonPaged = NonPaged * (PageSize / 1024);
733
734     Total = Paged + NonPaged;
735
736     return Total;
737 }
738
739 ULONG PerfDataGetKernelMemoryPagedK(void)
740 {
741     ULONG    Paged;
742     ULONG    PageSize;
743
744     EnterCriticalSection(&PerfDataCriticalSection);
745
746     Paged = SystemPerfInfo.PoolPagedBytes;
747     PageSize = SystemBasicInfo.uPageSize;
748
749     LeaveCriticalSection(&PerfDataCriticalSection);
750
751     Paged = Paged * (PageSize / 1024);
752
753     return Paged;
754 }
755
756 ULONG PerfDataGetKernelMemoryNonPagedK(void)
757 {
758     ULONG    NonPaged;
759     ULONG    PageSize;
760
761     EnterCriticalSection(&PerfDataCriticalSection);
762
763     NonPaged = SystemPerfInfo.PoolNonPagedBytes;
764     PageSize = SystemBasicInfo.uPageSize;
765
766     LeaveCriticalSection(&PerfDataCriticalSection);
767
768     NonPaged = NonPaged * (PageSize / 1024);
769
770     return NonPaged;
771 }
772
773 ULONG PerfDataGetPhysicalMemoryTotalK(void)
774 {
775     ULONG    Total;
776     ULONG    PageSize;
777
778     EnterCriticalSection(&PerfDataCriticalSection);
779
780     Total = SystemBasicInfo.uMmNumberOfPhysicalPages;
781     PageSize = SystemBasicInfo.uPageSize;
782
783     LeaveCriticalSection(&PerfDataCriticalSection);
784
785     Total = Total * (PageSize / 1024);
786
787     return Total;
788 }
789
790 ULONG PerfDataGetPhysicalMemoryAvailableK(void)
791 {
792     ULONG    Available;
793     ULONG    PageSize;
794
795     EnterCriticalSection(&PerfDataCriticalSection);
796
797     Available = SystemPerfInfo.MmAvailablePages;
798     PageSize = SystemBasicInfo.uPageSize;
799
800     LeaveCriticalSection(&PerfDataCriticalSection);
801
802     Available = Available * (PageSize / 1024);
803
804     return Available;
805 }
806
807 ULONG PerfDataGetPhysicalMemorySystemCacheK(void)
808 {
809     ULONG    SystemCache;
810
811     EnterCriticalSection(&PerfDataCriticalSection);
812
813     SystemCache = SystemCacheInfo.CurrentSize;
814
815     LeaveCriticalSection(&PerfDataCriticalSection);
816
817     SystemCache = SystemCache / 1024;
818
819     return SystemCache;
820 }
821
822 ULONG PerfDataGetSystemHandleCount(void)
823 {
824     ULONG    HandleCount;
825
826     EnterCriticalSection(&PerfDataCriticalSection);
827
828     HandleCount = SystemHandleInfo.Count;
829
830     LeaveCriticalSection(&PerfDataCriticalSection);
831
832     return HandleCount;
833 }
834
835 ULONG PerfDataGetTotalThreadCount(void)
836 {
837     ULONG    ThreadCount = 0;
838     ULONG    i;
839
840     EnterCriticalSection(&PerfDataCriticalSection);
841
842     for (i=0; i<ProcessCount; i++)
843     {
844         ThreadCount += pPerfData[i].ThreadCount;
845     }
846
847     LeaveCriticalSection(&PerfDataCriticalSection);
848
849     return ThreadCount;
850 }