- Sync with trunk up to r46941.
[reactos.git] / base / applications / taskmgr / perfdata.c
1 /*
2 * ReactOS Task Manager
3 *
4 * perfdata.cpp
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 Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 #include <precomp.h>
24
25 CRITICAL_SECTION PerfDataCriticalSection;
26 PPERFDATA pPerfDataOld = NULL; /* Older perf data (saved to establish delta values) */
27 PPERFDATA pPerfData = NULL; /* Most recent copy of perf data */
28 ULONG ProcessCountOld = 0;
29 ULONG ProcessCount = 0;
30 double dbIdleTime;
31 double dbKernelTime;
32 double dbSystemTime;
33 LARGE_INTEGER liOldIdleTime = {{0,0}};
34 double OldKernelTime = 0;
35 LARGE_INTEGER liOldSystemTime = {{0,0}};
36 SYSTEM_PERFORMANCE_INFORMATION SystemPerfInfo;
37 SYSTEM_BASIC_INFORMATION SystemBasicInfo;
38 SYSTEM_FILECACHE_INFORMATION SystemCacheInfo;
39 SYSTEM_HANDLE_INFORMATION SystemHandleInfo;
40 PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION SystemProcessorTimeInfo = NULL;
41 PSID SystemUserSid = NULL;
42
43 typedef struct _SIDTOUSERNAME
44 {
45 LIST_ENTRY List;
46 LPWSTR pszName;
47 BYTE Data[0];
48 } SIDTOUSERNAME, *PSIDTOUSERNAME;
49
50 static LIST_ENTRY SidToUserNameHead = {&SidToUserNameHead, &SidToUserNameHead};
51
52 BOOL PerfDataInitialize(void)
53 {
54 SID_IDENTIFIER_AUTHORITY NtSidAuthority = {SECURITY_NT_AUTHORITY};
55 NTSTATUS status;
56
57 InitializeCriticalSection(&PerfDataCriticalSection);
58
59 /*
60 * Get number of processors in the system
61 */
62 status = NtQuerySystemInformation(SystemBasicInformation, &SystemBasicInfo, sizeof(SystemBasicInfo), NULL);
63 if (status != NO_ERROR)
64 return FALSE;
65
66 /*
67 * Create the SYSTEM Sid
68 */
69 AllocateAndInitializeSid(&NtSidAuthority, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &SystemUserSid);
70 return TRUE;
71 }
72
73 void PerfDataUninitialize(void)
74 {
75 PLIST_ENTRY pCur;
76 PSIDTOUSERNAME pEntry;
77
78 if (pPerfData != NULL)
79 HeapFree(GetProcessHeap(), 0, pPerfData);
80
81 DeleteCriticalSection(&PerfDataCriticalSection);
82
83 if (SystemUserSid != NULL)
84 {
85 FreeSid(SystemUserSid);
86 SystemUserSid = NULL;
87 }
88
89 /* Free user names cache list */
90 pCur = SidToUserNameHead.Flink;
91 while (pCur != &SidToUserNameHead)
92 {
93 pEntry = CONTAINING_RECORD(pCur, SIDTOUSERNAME, List);
94 pCur = pCur->Flink;
95 HeapFree(GetProcessHeap(), 0, pEntry);
96 }
97 }
98
99 static void SidToUserName(PSID Sid, LPWSTR szBuffer, DWORD BufferSize)
100 {
101 static WCHAR szDomainNameUnused[255];
102 DWORD DomainNameLen = sizeof(szDomainNameUnused) / sizeof(szDomainNameUnused[0]);
103 SID_NAME_USE Use;
104
105 if (Sid != NULL)
106 LookupAccountSidW(NULL, Sid, szBuffer, &BufferSize, szDomainNameUnused, &DomainNameLen, &Use);
107 }
108
109 VOID
110 WINAPI
111 CachedGetUserFromSid(
112 PSID pSid,
113 LPWSTR pUserName,
114 PULONG pcwcUserName)
115 {
116 PLIST_ENTRY pCur;
117 PSIDTOUSERNAME pEntry;
118 ULONG cbSid, cwcUserName;
119
120 cwcUserName = *pcwcUserName;
121
122 /* Walk through the list */
123 for(pCur = SidToUserNameHead.Flink;
124 pCur != &SidToUserNameHead;
125 pCur = pCur->Flink)
126 {
127 pEntry = CONTAINING_RECORD(pCur, SIDTOUSERNAME, List);
128 if (EqualSid((PSID)&pEntry->Data, pSid))
129 {
130 wcsncpy(pUserName, pEntry->pszName, cwcUserName);
131 *pcwcUserName = cwcUserName;
132 return;
133 }
134 }
135
136 /* We didn't find the SID in the list, get the name conventional */
137 SidToUserName(pSid, pUserName, cwcUserName);
138
139 /* Allocate a new entry */
140 *pcwcUserName = wcslen(pUserName);
141 cwcUserName = *pcwcUserName + 1;
142 cbSid = GetLengthSid(pSid);
143 pEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(SIDTOUSERNAME) + cbSid + cwcUserName * sizeof(WCHAR));
144
145 /* Copy the Sid and name to our entry */
146 CopySid(cbSid, (PSID)&pEntry->Data, pSid);
147 pEntry->pszName = (LPWSTR)(pEntry->Data + cbSid);
148 wcsncpy(pEntry->pszName, pUserName, cwcUserName);
149
150 /* Insert the new entry */
151 pEntry->List.Flink = &SidToUserNameHead;
152 pEntry->List.Blink = SidToUserNameHead.Blink;
153 SidToUserNameHead.Blink->Flink = &pEntry->List;
154 SidToUserNameHead.Blink = &pEntry->List;
155
156 return;
157 }
158
159 void PerfDataRefresh(void)
160 {
161 ULONG ulSize;
162 NTSTATUS status;
163 LPBYTE pBuffer;
164 ULONG BufferSize;
165 PSYSTEM_PROCESS_INFORMATION pSPI;
166 PPERFDATA pPDOld;
167 ULONG Idx, Idx2;
168 HANDLE hProcess;
169 HANDLE hProcessToken;
170 SYSTEM_PERFORMANCE_INFORMATION SysPerfInfo;
171 SYSTEM_TIMEOFDAY_INFORMATION SysTimeInfo;
172 SYSTEM_FILECACHE_INFORMATION SysCacheInfo;
173 LPBYTE SysHandleInfoData;
174 PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION SysProcessorTimeInfo;
175 double CurrentKernelTime;
176 PSECURITY_DESCRIPTOR ProcessSD;
177 PSID ProcessUser;
178 ULONG Buffer[64]; /* must be 4 bytes aligned! */
179 ULONG cwcUserName;
180
181 /* Get new system time */
182 status = NtQuerySystemInformation(SystemTimeOfDayInformation, &SysTimeInfo, sizeof(SysTimeInfo), 0);
183 if (status != NO_ERROR)
184 return;
185
186 /* Get new CPU's idle time */
187 status = NtQuerySystemInformation(SystemPerformanceInformation, &SysPerfInfo, sizeof(SysPerfInfo), NULL);
188 if (status != NO_ERROR)
189 return;
190
191 /* Get system cache information */
192 status = NtQuerySystemInformation(SystemFileCacheInformation, &SysCacheInfo, sizeof(SysCacheInfo), NULL);
193 if (status != NO_ERROR)
194 return;
195
196 /* Get processor time information */
197 SysProcessorTimeInfo = (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)HeapAlloc(GetProcessHeap(), 0, sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * SystemBasicInfo.NumberOfProcessors);
198 status = NtQuerySystemInformation(SystemProcessorPerformanceInformation, SysProcessorTimeInfo, sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * SystemBasicInfo.NumberOfProcessors, &ulSize);
199
200 if (status != NO_ERROR)
201 {
202 if (SysProcessorTimeInfo != NULL)
203 HeapFree(GetProcessHeap(), 0, SysProcessorTimeInfo);
204 return;
205 }
206
207 /* Get handle information
208 * We don't know how much data there is so just keep
209 * increasing the buffer size until the call succeeds
210 */
211 BufferSize = 0;
212 do
213 {
214 BufferSize += 0x10000;
215 SysHandleInfoData = (LPBYTE)HeapAlloc(GetProcessHeap(), 0, BufferSize);
216
217 status = NtQuerySystemInformation(SystemHandleInformation, SysHandleInfoData, BufferSize, &ulSize);
218
219 if (status == STATUS_INFO_LENGTH_MISMATCH) {
220 HeapFree(GetProcessHeap(), 0, SysHandleInfoData);
221 }
222
223 } while (status == STATUS_INFO_LENGTH_MISMATCH);
224
225 /* Get process information
226 * We don't know how much data there is so just keep
227 * increasing the buffer size until the call succeeds
228 */
229 BufferSize = 0;
230 do
231 {
232 BufferSize += 0x10000;
233 pBuffer = (LPBYTE)HeapAlloc(GetProcessHeap(), 0, BufferSize);
234
235 status = NtQuerySystemInformation(SystemProcessInformation, pBuffer, BufferSize, &ulSize);
236
237 if (status == STATUS_INFO_LENGTH_MISMATCH) {
238 HeapFree(GetProcessHeap(), 0, pBuffer);
239 }
240
241 } while (status == STATUS_INFO_LENGTH_MISMATCH);
242
243 EnterCriticalSection(&PerfDataCriticalSection);
244
245 /*
246 * Save system performance info
247 */
248 memcpy(&SystemPerfInfo, &SysPerfInfo, sizeof(SYSTEM_PERFORMANCE_INFORMATION));
249
250 /*
251 * Save system cache info
252 */
253 memcpy(&SystemCacheInfo, &SysCacheInfo, sizeof(SYSTEM_FILECACHE_INFORMATION));
254
255 /*
256 * Save system processor time info
257 */
258 if (SystemProcessorTimeInfo) {
259 HeapFree(GetProcessHeap(), 0, SystemProcessorTimeInfo);
260 }
261 SystemProcessorTimeInfo = SysProcessorTimeInfo;
262
263 /*
264 * Save system handle info
265 */
266 memcpy(&SystemHandleInfo, SysHandleInfoData, sizeof(SYSTEM_HANDLE_INFORMATION));
267 HeapFree(GetProcessHeap(), 0, SysHandleInfoData);
268
269 for (CurrentKernelTime=0, Idx=0; Idx<(ULONG)SystemBasicInfo.NumberOfProcessors; Idx++) {
270 CurrentKernelTime += Li2Double(SystemProcessorTimeInfo[Idx].KernelTime);
271 CurrentKernelTime += Li2Double(SystemProcessorTimeInfo[Idx].DpcTime);
272 CurrentKernelTime += Li2Double(SystemProcessorTimeInfo[Idx].InterruptTime);
273 }
274
275 /* If it's a first call - skip idle time calcs */
276 if (liOldIdleTime.QuadPart != 0) {
277 /* CurrentValue = NewValue - OldValue */
278 dbIdleTime = Li2Double(SysPerfInfo.IdleProcessTime) - Li2Double(liOldIdleTime);
279 dbKernelTime = CurrentKernelTime - OldKernelTime;
280 dbSystemTime = Li2Double(SysTimeInfo.CurrentTime) - Li2Double(liOldSystemTime);
281
282 /* CurrentCpuIdle = IdleTime / SystemTime */
283 dbIdleTime = dbIdleTime / dbSystemTime;
284 dbKernelTime = dbKernelTime / dbSystemTime;
285
286 /* CurrentCpuUsage% = 100 - (CurrentCpuIdle * 100) / NumberOfProcessors */
287 dbIdleTime = 100.0 - dbIdleTime * 100.0 / (double)SystemBasicInfo.NumberOfProcessors; /* + 0.5; */
288 dbKernelTime = 100.0 - dbKernelTime * 100.0 / (double)SystemBasicInfo.NumberOfProcessors; /* + 0.5; */
289 }
290
291 /* Store new CPU's idle and system time */
292 liOldIdleTime = SysPerfInfo.IdleProcessTime;
293 liOldSystemTime = SysTimeInfo.CurrentTime;
294 OldKernelTime = CurrentKernelTime;
295
296 /* Determine the process count
297 * We loop through the data we got from NtQuerySystemInformation
298 * and count how many structures there are (until RelativeOffset is 0)
299 */
300 ProcessCountOld = ProcessCount;
301 ProcessCount = 0;
302 pSPI = (PSYSTEM_PROCESS_INFORMATION)pBuffer;
303 while (pSPI) {
304 ProcessCount++;
305 if (pSPI->NextEntryOffset == 0)
306 break;
307 pSPI = (PSYSTEM_PROCESS_INFORMATION)((LPBYTE)pSPI + pSPI->NextEntryOffset);
308 }
309
310 /* Now alloc a new PERFDATA array and fill in the data */
311 if (pPerfDataOld) {
312 HeapFree(GetProcessHeap(), 0, pPerfDataOld);
313 }
314 pPerfDataOld = pPerfData;
315 /* Clear out process perf data structures with HEAP_ZERO_MEMORY flag: */
316 pPerfData = (PPERFDATA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PERFDATA) * ProcessCount);
317 pSPI = (PSYSTEM_PROCESS_INFORMATION)pBuffer;
318 for (Idx=0; Idx<ProcessCount; Idx++) {
319 /* Get the old perf data for this process (if any) */
320 /* so that we can establish delta values */
321 pPDOld = NULL;
322 for (Idx2=0; Idx2<ProcessCountOld; Idx2++) {
323 if (pPerfDataOld[Idx2].ProcessId == pSPI->UniqueProcessId) {
324 pPDOld = &pPerfDataOld[Idx2];
325 break;
326 }
327 }
328
329 if (pSPI->ImageName.Buffer) {
330 /* Don't assume a UNICODE_STRING Buffer is zero terminated: */
331 int len = pSPI->ImageName.Length / 2;
332 /* Check against max size and allow for terminating zero (already zeroed): */
333 if(len >= MAX_PATH)len=MAX_PATH - 1;
334 wcsncpy(pPerfData[Idx].ImageName, pSPI->ImageName.Buffer, len);
335 } else {
336 LoadStringW(hInst, IDS_IDLE_PROCESS, pPerfData[Idx].ImageName,
337 sizeof(pPerfData[Idx].ImageName) / sizeof(pPerfData[Idx].ImageName[0]));
338 }
339
340 pPerfData[Idx].ProcessId = pSPI->UniqueProcessId;
341
342 if (pPDOld) {
343 double CurTime = Li2Double(pSPI->KernelTime) + Li2Double(pSPI->UserTime);
344 double OldTime = Li2Double(pPDOld->KernelTime) + Li2Double(pPDOld->UserTime);
345 double CpuTime = (CurTime - OldTime) / dbSystemTime;
346 CpuTime = CpuTime * 100.0 / (double)SystemBasicInfo.NumberOfProcessors; /* + 0.5; */
347 pPerfData[Idx].CPUUsage = (ULONG)CpuTime;
348 }
349 pPerfData[Idx].CPUTime.QuadPart = pSPI->UserTime.QuadPart + pSPI->KernelTime.QuadPart;
350 pPerfData[Idx].WorkingSetSizeBytes = pSPI->WorkingSetSize;
351 pPerfData[Idx].PeakWorkingSetSizeBytes = pSPI->PeakWorkingSetSize;
352 if (pPDOld)
353 pPerfData[Idx].WorkingSetSizeDelta = labs((LONG)pSPI->WorkingSetSize - (LONG)pPDOld->WorkingSetSizeBytes);
354 else
355 pPerfData[Idx].WorkingSetSizeDelta = 0;
356 pPerfData[Idx].PageFaultCount = pSPI->PageFaultCount;
357 if (pPDOld)
358 pPerfData[Idx].PageFaultCountDelta = labs((LONG)pSPI->PageFaultCount - (LONG)pPDOld->PageFaultCount);
359 else
360 pPerfData[Idx].PageFaultCountDelta = 0;
361 pPerfData[Idx].VirtualMemorySizeBytes = pSPI->VirtualSize;
362 pPerfData[Idx].PagedPoolUsagePages = pSPI->QuotaPeakPagedPoolUsage;
363 pPerfData[Idx].NonPagedPoolUsagePages = pSPI->QuotaPeakNonPagedPoolUsage;
364 pPerfData[Idx].BasePriority = pSPI->BasePriority;
365 pPerfData[Idx].HandleCount = pSPI->HandleCount;
366 pPerfData[Idx].ThreadCount = pSPI->NumberOfThreads;
367 pPerfData[Idx].SessionId = pSPI->SessionId;
368 pPerfData[Idx].UserName[0] = L'\0';
369 pPerfData[Idx].USERObjectCount = 0;
370 pPerfData[Idx].GDIObjectCount = 0;
371 ProcessUser = SystemUserSid;
372 ProcessSD = NULL;
373
374 if (pSPI->UniqueProcessId != NULL) {
375 hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | READ_CONTROL, FALSE, PtrToUlong(pSPI->UniqueProcessId));
376 if (hProcess) {
377 /* don't query the information of the system process. It's possible but
378 returns Administrators as the owner of the process instead of SYSTEM */
379 if (pSPI->UniqueProcessId != (HANDLE)0x4)
380 {
381 if (OpenProcessToken(hProcess, TOKEN_QUERY, &hProcessToken))
382 {
383 DWORD RetLen = 0;
384 BOOL Ret;
385
386 Ret = GetTokenInformation(hProcessToken, TokenUser, (LPVOID)Buffer, sizeof(Buffer), &RetLen);
387 CloseHandle(hProcessToken);
388
389 if (Ret)
390 ProcessUser = ((PTOKEN_USER)Buffer)->User.Sid;
391 else
392 goto ReadProcOwner;
393 }
394 else
395 {
396 ReadProcOwner:
397 GetSecurityInfo(hProcess, SE_KERNEL_OBJECT, OWNER_SECURITY_INFORMATION, &ProcessUser, NULL, NULL, NULL, &ProcessSD);
398 }
399
400 pPerfData[Idx].USERObjectCount = GetGuiResources(hProcess, GR_USEROBJECTS);
401 pPerfData[Idx].GDIObjectCount = GetGuiResources(hProcess, GR_GDIOBJECTS);
402 }
403
404 GetProcessIoCounters(hProcess, &pPerfData[Idx].IOCounters);
405 CloseHandle(hProcess);
406 } else {
407 goto ClearInfo;
408 }
409 } else {
410 ClearInfo:
411 /* clear information we were unable to fetch */
412 ZeroMemory(&pPerfData[Idx].IOCounters, sizeof(IO_COUNTERS));
413 }
414
415 cwcUserName = sizeof(pPerfData[0].UserName) / sizeof(pPerfData[0].UserName[0]);
416 CachedGetUserFromSid(ProcessUser, pPerfData[Idx].UserName, &cwcUserName);
417
418 if (ProcessSD != NULL)
419 {
420 LocalFree((HLOCAL)ProcessSD);
421 }
422
423 pPerfData[Idx].UserTime.QuadPart = pSPI->UserTime.QuadPart;
424 pPerfData[Idx].KernelTime.QuadPart = pSPI->KernelTime.QuadPart;
425 pSPI = (PSYSTEM_PROCESS_INFORMATION)((LPBYTE)pSPI + pSPI->NextEntryOffset);
426 }
427 HeapFree(GetProcessHeap(), 0, pBuffer);
428 LeaveCriticalSection(&PerfDataCriticalSection);
429 }
430
431 ULONG PerfDataGetProcessIndex(ULONG pid)
432 {
433 ULONG idx;
434
435 EnterCriticalSection(&PerfDataCriticalSection);
436
437 for (idx = 0; idx < ProcessCount; idx++)
438 {
439 if (PtrToUlong(pPerfData[idx].ProcessId) == pid)
440 {
441 break;
442 }
443 }
444
445 LeaveCriticalSection(&PerfDataCriticalSection);
446
447 if (idx == ProcessCount)
448 {
449 return -1;
450 }
451 return idx;
452 }
453
454 ULONG PerfDataGetProcessCount(void)
455 {
456 return ProcessCount;
457 }
458
459 ULONG PerfDataGetProcessorUsage(void)
460 {
461 return (ULONG)dbIdleTime;
462 }
463
464 ULONG PerfDataGetProcessorSystemUsage(void)
465 {
466 return (ULONG)dbKernelTime;
467 }
468
469 BOOL PerfDataGetImageName(ULONG Index, LPWSTR lpImageName, int nMaxCount)
470 {
471 BOOL bSuccessful;
472
473 EnterCriticalSection(&PerfDataCriticalSection);
474
475 if (Index < ProcessCount) {
476 wcsncpy(lpImageName, pPerfData[Index].ImageName, nMaxCount);
477 bSuccessful = TRUE;
478 } else {
479 bSuccessful = FALSE;
480 }
481 LeaveCriticalSection(&PerfDataCriticalSection);
482 return bSuccessful;
483 }
484
485 ULONG PerfDataGetProcessId(ULONG Index)
486 {
487 ULONG ProcessId;
488
489 EnterCriticalSection(&PerfDataCriticalSection);
490
491 if (Index < ProcessCount)
492 ProcessId = PtrToUlong(pPerfData[Index].ProcessId);
493 else
494 ProcessId = 0;
495
496 LeaveCriticalSection(&PerfDataCriticalSection);
497
498 return ProcessId;
499 }
500
501 BOOL PerfDataGetUserName(ULONG Index, LPWSTR lpUserName, int nMaxCount)
502 {
503 BOOL bSuccessful;
504
505 EnterCriticalSection(&PerfDataCriticalSection);
506
507 if (Index < ProcessCount) {
508 wcsncpy(lpUserName, pPerfData[Index].UserName, nMaxCount);
509 bSuccessful = TRUE;
510 } else {
511 bSuccessful = FALSE;
512 }
513
514 LeaveCriticalSection(&PerfDataCriticalSection);
515
516 return bSuccessful;
517 }
518
519 ULONG PerfDataGetSessionId(ULONG Index)
520 {
521 ULONG SessionId;
522
523 EnterCriticalSection(&PerfDataCriticalSection);
524
525 if (Index < ProcessCount)
526 SessionId = pPerfData[Index].SessionId;
527 else
528 SessionId = 0;
529
530 LeaveCriticalSection(&PerfDataCriticalSection);
531
532 return SessionId;
533 }
534
535 ULONG PerfDataGetCPUUsage(ULONG Index)
536 {
537 ULONG CpuUsage;
538
539 EnterCriticalSection(&PerfDataCriticalSection);
540
541 if (Index < ProcessCount)
542 CpuUsage = pPerfData[Index].CPUUsage;
543 else
544 CpuUsage = 0;
545
546 LeaveCriticalSection(&PerfDataCriticalSection);
547
548 return CpuUsage;
549 }
550
551 LARGE_INTEGER PerfDataGetCPUTime(ULONG Index)
552 {
553 LARGE_INTEGER CpuTime = {{0,0}};
554
555 EnterCriticalSection(&PerfDataCriticalSection);
556
557 if (Index < ProcessCount)
558 CpuTime = pPerfData[Index].CPUTime;
559
560 LeaveCriticalSection(&PerfDataCriticalSection);
561
562 return CpuTime;
563 }
564
565 ULONG PerfDataGetWorkingSetSizeBytes(ULONG Index)
566 {
567 ULONG WorkingSetSizeBytes;
568
569 EnterCriticalSection(&PerfDataCriticalSection);
570
571 if (Index < ProcessCount)
572 WorkingSetSizeBytes = pPerfData[Index].WorkingSetSizeBytes;
573 else
574 WorkingSetSizeBytes = 0;
575
576 LeaveCriticalSection(&PerfDataCriticalSection);
577
578 return WorkingSetSizeBytes;
579 }
580
581 ULONG PerfDataGetPeakWorkingSetSizeBytes(ULONG Index)
582 {
583 ULONG PeakWorkingSetSizeBytes;
584
585 EnterCriticalSection(&PerfDataCriticalSection);
586
587 if (Index < ProcessCount)
588 PeakWorkingSetSizeBytes = pPerfData[Index].PeakWorkingSetSizeBytes;
589 else
590 PeakWorkingSetSizeBytes = 0;
591
592 LeaveCriticalSection(&PerfDataCriticalSection);
593
594 return PeakWorkingSetSizeBytes;
595 }
596
597 ULONG PerfDataGetWorkingSetSizeDelta(ULONG Index)
598 {
599 ULONG WorkingSetSizeDelta;
600
601 EnterCriticalSection(&PerfDataCriticalSection);
602
603 if (Index < ProcessCount)
604 WorkingSetSizeDelta = pPerfData[Index].WorkingSetSizeDelta;
605 else
606 WorkingSetSizeDelta = 0;
607
608 LeaveCriticalSection(&PerfDataCriticalSection);
609
610 return WorkingSetSizeDelta;
611 }
612
613 ULONG PerfDataGetPageFaultCount(ULONG Index)
614 {
615 ULONG PageFaultCount;
616
617 EnterCriticalSection(&PerfDataCriticalSection);
618
619 if (Index < ProcessCount)
620 PageFaultCount = pPerfData[Index].PageFaultCount;
621 else
622 PageFaultCount = 0;
623
624 LeaveCriticalSection(&PerfDataCriticalSection);
625
626 return PageFaultCount;
627 }
628
629 ULONG PerfDataGetPageFaultCountDelta(ULONG Index)
630 {
631 ULONG PageFaultCountDelta;
632
633 EnterCriticalSection(&PerfDataCriticalSection);
634
635 if (Index < ProcessCount)
636 PageFaultCountDelta = pPerfData[Index].PageFaultCountDelta;
637 else
638 PageFaultCountDelta = 0;
639
640 LeaveCriticalSection(&PerfDataCriticalSection);
641
642 return PageFaultCountDelta;
643 }
644
645 ULONG PerfDataGetVirtualMemorySizeBytes(ULONG Index)
646 {
647 ULONG VirtualMemorySizeBytes;
648
649 EnterCriticalSection(&PerfDataCriticalSection);
650
651 if (Index < ProcessCount)
652 VirtualMemorySizeBytes = pPerfData[Index].VirtualMemorySizeBytes;
653 else
654 VirtualMemorySizeBytes = 0;
655
656 LeaveCriticalSection(&PerfDataCriticalSection);
657
658 return VirtualMemorySizeBytes;
659 }
660
661 ULONG PerfDataGetPagedPoolUsagePages(ULONG Index)
662 {
663 ULONG PagedPoolUsage;
664
665 EnterCriticalSection(&PerfDataCriticalSection);
666
667 if (Index < ProcessCount)
668 PagedPoolUsage = pPerfData[Index].PagedPoolUsagePages;
669 else
670 PagedPoolUsage = 0;
671
672 LeaveCriticalSection(&PerfDataCriticalSection);
673
674 return PagedPoolUsage;
675 }
676
677 ULONG PerfDataGetNonPagedPoolUsagePages(ULONG Index)
678 {
679 ULONG NonPagedPoolUsage;
680
681 EnterCriticalSection(&PerfDataCriticalSection);
682
683 if (Index < ProcessCount)
684 NonPagedPoolUsage = pPerfData[Index].NonPagedPoolUsagePages;
685 else
686 NonPagedPoolUsage = 0;
687
688 LeaveCriticalSection(&PerfDataCriticalSection);
689
690 return NonPagedPoolUsage;
691 }
692
693 ULONG PerfDataGetBasePriority(ULONG Index)
694 {
695 ULONG BasePriority;
696
697 EnterCriticalSection(&PerfDataCriticalSection);
698
699 if (Index < ProcessCount)
700 BasePriority = pPerfData[Index].BasePriority;
701 else
702 BasePriority = 0;
703
704 LeaveCriticalSection(&PerfDataCriticalSection);
705
706 return BasePriority;
707 }
708
709 ULONG PerfDataGetHandleCount(ULONG Index)
710 {
711 ULONG HandleCount;
712
713 EnterCriticalSection(&PerfDataCriticalSection);
714
715 if (Index < ProcessCount)
716 HandleCount = pPerfData[Index].HandleCount;
717 else
718 HandleCount = 0;
719
720 LeaveCriticalSection(&PerfDataCriticalSection);
721
722 return HandleCount;
723 }
724
725 ULONG PerfDataGetThreadCount(ULONG Index)
726 {
727 ULONG ThreadCount;
728
729 EnterCriticalSection(&PerfDataCriticalSection);
730
731 if (Index < ProcessCount)
732 ThreadCount = pPerfData[Index].ThreadCount;
733 else
734 ThreadCount = 0;
735
736 LeaveCriticalSection(&PerfDataCriticalSection);
737
738 return ThreadCount;
739 }
740
741 ULONG PerfDataGetUSERObjectCount(ULONG Index)
742 {
743 ULONG USERObjectCount;
744
745 EnterCriticalSection(&PerfDataCriticalSection);
746
747 if (Index < ProcessCount)
748 USERObjectCount = pPerfData[Index].USERObjectCount;
749 else
750 USERObjectCount = 0;
751
752 LeaveCriticalSection(&PerfDataCriticalSection);
753
754 return USERObjectCount;
755 }
756
757 ULONG PerfDataGetGDIObjectCount(ULONG Index)
758 {
759 ULONG GDIObjectCount;
760
761 EnterCriticalSection(&PerfDataCriticalSection);
762
763 if (Index < ProcessCount)
764 GDIObjectCount = pPerfData[Index].GDIObjectCount;
765 else
766 GDIObjectCount = 0;
767
768 LeaveCriticalSection(&PerfDataCriticalSection);
769
770 return GDIObjectCount;
771 }
772
773 BOOL PerfDataGetIOCounters(ULONG Index, PIO_COUNTERS pIoCounters)
774 {
775 BOOL bSuccessful;
776
777 EnterCriticalSection(&PerfDataCriticalSection);
778
779 if (Index < ProcessCount)
780 {
781 memcpy(pIoCounters, &pPerfData[Index].IOCounters, sizeof(IO_COUNTERS));
782 bSuccessful = TRUE;
783 }
784 else
785 bSuccessful = FALSE;
786
787 LeaveCriticalSection(&PerfDataCriticalSection);
788
789 return bSuccessful;
790 }
791
792 ULONG PerfDataGetCommitChargeTotalK(void)
793 {
794 ULONG Total;
795 ULONG PageSize;
796
797 EnterCriticalSection(&PerfDataCriticalSection);
798
799 Total = SystemPerfInfo.CommittedPages;
800 PageSize = SystemBasicInfo.PageSize;
801
802 LeaveCriticalSection(&PerfDataCriticalSection);
803
804 Total = Total * (PageSize / 1024);
805
806 return Total;
807 }
808
809 ULONG PerfDataGetCommitChargeLimitK(void)
810 {
811 ULONG Limit;
812 ULONG PageSize;
813
814 EnterCriticalSection(&PerfDataCriticalSection);
815
816 Limit = SystemPerfInfo.CommitLimit;
817 PageSize = SystemBasicInfo.PageSize;
818
819 LeaveCriticalSection(&PerfDataCriticalSection);
820
821 Limit = Limit * (PageSize / 1024);
822
823 return Limit;
824 }
825
826 ULONG PerfDataGetCommitChargePeakK(void)
827 {
828 ULONG Peak;
829 ULONG PageSize;
830
831 EnterCriticalSection(&PerfDataCriticalSection);
832
833 Peak = SystemPerfInfo.PeakCommitment;
834 PageSize = SystemBasicInfo.PageSize;
835
836 LeaveCriticalSection(&PerfDataCriticalSection);
837
838 Peak = Peak * (PageSize / 1024);
839
840 return Peak;
841 }
842
843 ULONG PerfDataGetKernelMemoryTotalK(void)
844 {
845 ULONG Total;
846 ULONG Paged;
847 ULONG NonPaged;
848 ULONG PageSize;
849
850 EnterCriticalSection(&PerfDataCriticalSection);
851
852 Paged = SystemPerfInfo.PagedPoolPages;
853 NonPaged = SystemPerfInfo.NonPagedPoolPages;
854 PageSize = SystemBasicInfo.PageSize;
855
856 LeaveCriticalSection(&PerfDataCriticalSection);
857
858 Paged = Paged * (PageSize / 1024);
859 NonPaged = NonPaged * (PageSize / 1024);
860
861 Total = Paged + NonPaged;
862
863 return Total;
864 }
865
866 ULONG PerfDataGetKernelMemoryPagedK(void)
867 {
868 ULONG Paged;
869 ULONG PageSize;
870
871 EnterCriticalSection(&PerfDataCriticalSection);
872
873 Paged = SystemPerfInfo.PagedPoolPages;
874 PageSize = SystemBasicInfo.PageSize;
875
876 LeaveCriticalSection(&PerfDataCriticalSection);
877
878 Paged = Paged * (PageSize / 1024);
879
880 return Paged;
881 }
882
883 ULONG PerfDataGetKernelMemoryNonPagedK(void)
884 {
885 ULONG NonPaged;
886 ULONG PageSize;
887
888 EnterCriticalSection(&PerfDataCriticalSection);
889
890 NonPaged = SystemPerfInfo.NonPagedPoolPages;
891 PageSize = SystemBasicInfo.PageSize;
892
893 LeaveCriticalSection(&PerfDataCriticalSection);
894
895 NonPaged = NonPaged * (PageSize / 1024);
896
897 return NonPaged;
898 }
899
900 ULONG PerfDataGetPhysicalMemoryTotalK(void)
901 {
902 ULONG Total;
903 ULONG PageSize;
904
905 EnterCriticalSection(&PerfDataCriticalSection);
906
907 Total = SystemBasicInfo.NumberOfPhysicalPages;
908 PageSize = SystemBasicInfo.PageSize;
909
910 LeaveCriticalSection(&PerfDataCriticalSection);
911
912 Total = Total * (PageSize / 1024);
913
914 return Total;
915 }
916
917 ULONG PerfDataGetPhysicalMemoryAvailableK(void)
918 {
919 ULONG Available;
920 ULONG PageSize;
921
922 EnterCriticalSection(&PerfDataCriticalSection);
923
924 Available = SystemPerfInfo.AvailablePages;
925 PageSize = SystemBasicInfo.PageSize;
926
927 LeaveCriticalSection(&PerfDataCriticalSection);
928
929 Available = Available * (PageSize / 1024);
930
931 return Available;
932 }
933
934 ULONG PerfDataGetPhysicalMemorySystemCacheK(void)
935 {
936 ULONG SystemCache;
937 ULONG PageSize;
938
939 EnterCriticalSection(&PerfDataCriticalSection);
940
941 PageSize = SystemBasicInfo.PageSize;
942 SystemCache = SystemCacheInfo.CurrentSizeIncludingTransitionInPages * PageSize;
943
944 LeaveCriticalSection(&PerfDataCriticalSection);
945
946 return SystemCache / 1024;
947 }
948
949 ULONG PerfDataGetSystemHandleCount(void)
950 {
951 ULONG HandleCount;
952
953 EnterCriticalSection(&PerfDataCriticalSection);
954
955 HandleCount = SystemHandleInfo.NumberOfHandles;
956
957 LeaveCriticalSection(&PerfDataCriticalSection);
958
959 return HandleCount;
960 }
961
962 ULONG PerfDataGetTotalThreadCount(void)
963 {
964 ULONG ThreadCount = 0;
965 ULONG i;
966
967 EnterCriticalSection(&PerfDataCriticalSection);
968
969 for (i=0; i<ProcessCount; i++)
970 {
971 ThreadCount += pPerfData[i].ThreadCount;
972 }
973
974 LeaveCriticalSection(&PerfDataCriticalSection);
975
976 return ThreadCount;
977 }
978
979 BOOL PerfDataGet(ULONG Index, PPERFDATA *lppData)
980 {
981 BOOL bSuccessful = FALSE;
982
983 EnterCriticalSection(&PerfDataCriticalSection);
984 if (Index < ProcessCount)
985 {
986 *lppData = pPerfData + Index;
987 bSuccessful = TRUE;
988 }
989 LeaveCriticalSection(&PerfDataCriticalSection);
990 return bSuccessful;
991 }
992