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