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