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