6 * Copyright (C) 1999 - 2001 Brian Palmer <brianp@reactos.org>
7 * Copyright (C) 2014 Ismael Ferreras Morezuelas <swyterzone+ros@gmail.com>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 #define WIN32_LEAN_AND_MEAN
29 #define NTOS_MODE_USER
30 #include <ndk/psfuncs.h>
31 #include <ndk/exfuncs.h>
33 CRITICAL_SECTION PerfDataCriticalSection
;
34 PPERFDATA pPerfDataOld
= NULL
; /* Older perf data (saved to establish delta values) */
35 PPERFDATA pPerfData
= NULL
; /* Most recent copy of perf data */
36 ULONG ProcessCountOld
= 0;
37 ULONG ProcessCount
= 0;
41 LARGE_INTEGER liOldIdleTime
= {{0,0}};
42 double OldKernelTime
= 0;
43 LARGE_INTEGER liOldSystemTime
= {{0,0}};
44 SYSTEM_PERFORMANCE_INFORMATION SystemPerfInfo
;
45 SYSTEM_BASIC_INFORMATION SystemBasicInfo
;
46 SYSTEM_FILECACHE_INFORMATION SystemCacheInfo
;
47 SYSTEM_HANDLE_INFORMATION SystemHandleInfo
;
48 PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION SystemProcessorTimeInfo
= NULL
;
49 PSID SystemUserSid
= NULL
;
51 PCMD_LINE_CACHE global_cache
= NULL
;
53 #define CMD_LINE_MIN(a, b) (a < b ? a - sizeof(WCHAR) : b)
55 typedef struct _SIDTOUSERNAME
60 } SIDTOUSERNAME
, *PSIDTOUSERNAME
;
62 static LIST_ENTRY SidToUserNameHead
= {&SidToUserNameHead
, &SidToUserNameHead
};
64 BOOL
PerfDataInitialize(void)
66 SID_IDENTIFIER_AUTHORITY NtSidAuthority
= {SECURITY_NT_AUTHORITY
};
69 InitializeCriticalSection(&PerfDataCriticalSection
);
72 * Get number of processors in the system
74 status
= NtQuerySystemInformation(SystemBasicInformation
, &SystemBasicInfo
, sizeof(SystemBasicInfo
), NULL
);
75 if (!NT_SUCCESS(status
))
79 * Create the SYSTEM Sid
81 AllocateAndInitializeSid(&NtSidAuthority
, 1, SECURITY_LOCAL_SYSTEM_RID
, 0, 0, 0, 0, 0, 0, 0, &SystemUserSid
);
85 void PerfDataUninitialize(void)
88 PSIDTOUSERNAME pEntry
;
90 if (pPerfData
!= NULL
)
91 HeapFree(GetProcessHeap(), 0, pPerfData
);
93 DeleteCriticalSection(&PerfDataCriticalSection
);
95 if (SystemUserSid
!= NULL
)
97 FreeSid(SystemUserSid
);
101 /* Free user names cache list */
102 pCur
= SidToUserNameHead
.Flink
;
103 while (pCur
!= &SidToUserNameHead
)
105 pEntry
= CONTAINING_RECORD(pCur
, SIDTOUSERNAME
, List
);
107 HeapFree(GetProcessHeap(), 0, pEntry
);
110 if (SystemProcessorTimeInfo
) {
111 HeapFree(GetProcessHeap(), 0, SystemProcessorTimeInfo
);
115 static void SidToUserName(PSID Sid
, LPWSTR szBuffer
, DWORD BufferSize
)
117 static WCHAR szDomainNameUnused
[255];
118 DWORD DomainNameLen
= sizeof(szDomainNameUnused
) / sizeof(szDomainNameUnused
[0]);
122 LookupAccountSidW(NULL
, Sid
, szBuffer
, &BufferSize
, szDomainNameUnused
, &DomainNameLen
, &Use
);
127 CachedGetUserFromSid(
133 PSIDTOUSERNAME pEntry
;
134 ULONG cbSid
, cwcUserName
;
136 cwcUserName
= *pcwcUserName
;
138 /* Walk through the list */
139 for(pCur
= SidToUserNameHead
.Flink
;
140 pCur
!= &SidToUserNameHead
;
143 pEntry
= CONTAINING_RECORD(pCur
, SIDTOUSERNAME
, List
);
144 if (EqualSid((PSID
)&pEntry
->Data
, pSid
))
146 wcsncpy(pUserName
, pEntry
->pszName
, cwcUserName
);
147 *pcwcUserName
= cwcUserName
;
152 /* We didn't find the SID in the list, get the name conventional */
153 SidToUserName(pSid
, pUserName
, cwcUserName
);
155 /* Allocate a new entry */
156 *pcwcUserName
= wcslen(pUserName
);
157 cwcUserName
= *pcwcUserName
+ 1;
158 cbSid
= GetLengthSid(pSid
);
159 pEntry
= HeapAlloc(GetProcessHeap(), 0, sizeof(SIDTOUSERNAME
) + cbSid
+ cwcUserName
* sizeof(WCHAR
));
161 /* Copy the Sid and name to our entry */
162 CopySid(cbSid
, (PSID
)&pEntry
->Data
, pSid
);
163 pEntry
->pszName
= (LPWSTR
)(pEntry
->Data
+ cbSid
);
164 wcsncpy(pEntry
->pszName
, pUserName
, cwcUserName
);
166 /* Insert the new entry */
167 pEntry
->List
.Flink
= &SidToUserNameHead
;
168 pEntry
->List
.Blink
= SidToUserNameHead
.Blink
;
169 SidToUserNameHead
.Blink
->Flink
= &pEntry
->List
;
170 SidToUserNameHead
.Blink
= &pEntry
->List
;
175 void PerfDataRefresh(void)
181 PSYSTEM_PROCESS_INFORMATION pSPI
;
185 HANDLE hProcessToken
;
186 SYSTEM_PERFORMANCE_INFORMATION SysPerfInfo
;
187 SYSTEM_TIMEOFDAY_INFORMATION SysTimeInfo
;
188 SYSTEM_FILECACHE_INFORMATION SysCacheInfo
;
189 LPBYTE SysHandleInfoData
;
190 PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION SysProcessorTimeInfo
;
191 double CurrentKernelTime
;
192 PSECURITY_DESCRIPTOR ProcessSD
;
194 ULONG Buffer
[64]; /* must be 4 bytes aligned! */
197 /* Get new system time */
198 status
= NtQuerySystemInformation(SystemTimeOfDayInformation
, &SysTimeInfo
, sizeof(SysTimeInfo
), NULL
);
199 if (!NT_SUCCESS(status
))
202 /* Get new CPU's idle time */
203 status
= NtQuerySystemInformation(SystemPerformanceInformation
, &SysPerfInfo
, sizeof(SysPerfInfo
), NULL
);
204 if (!NT_SUCCESS(status
))
207 /* Get system cache information */
208 status
= NtQuerySystemInformation(SystemFileCacheInformation
, &SysCacheInfo
, sizeof(SysCacheInfo
), NULL
);
209 if (!NT_SUCCESS(status
))
212 /* Get processor time information */
213 SysProcessorTimeInfo
= (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
)HeapAlloc(GetProcessHeap(), 0, sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
) * SystemBasicInfo
.NumberOfProcessors
);
214 status
= NtQuerySystemInformation(SystemProcessorPerformanceInformation
, SysProcessorTimeInfo
, sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
) * SystemBasicInfo
.NumberOfProcessors
, &ulSize
);
216 if (!NT_SUCCESS(status
))
218 if (SysProcessorTimeInfo
!= NULL
)
219 HeapFree(GetProcessHeap(), 0, SysProcessorTimeInfo
);
223 /* Get handle information
224 * We don't know how much data there is so just keep
225 * increasing the buffer size until the call succeeds
230 BufferSize
+= 0x10000;
231 SysHandleInfoData
= (LPBYTE
)HeapAlloc(GetProcessHeap(), 0, BufferSize
);
233 status
= NtQuerySystemInformation(SystemHandleInformation
, SysHandleInfoData
, BufferSize
, &ulSize
);
235 if (status
== STATUS_INFO_LENGTH_MISMATCH
) {
236 HeapFree(GetProcessHeap(), 0, SysHandleInfoData
);
239 } while (status
== STATUS_INFO_LENGTH_MISMATCH
);
241 /* Get process information
242 * We don't know how much data there is so just keep
243 * increasing the buffer size until the call succeeds
248 BufferSize
+= 0x10000;
249 pBuffer
= (LPBYTE
)HeapAlloc(GetProcessHeap(), 0, BufferSize
);
251 status
= NtQuerySystemInformation(SystemProcessInformation
, pBuffer
, BufferSize
, &ulSize
);
253 if (status
== STATUS_INFO_LENGTH_MISMATCH
) {
254 HeapFree(GetProcessHeap(), 0, pBuffer
);
257 } while (status
== STATUS_INFO_LENGTH_MISMATCH
);
259 EnterCriticalSection(&PerfDataCriticalSection
);
262 * Save system performance info
264 memcpy(&SystemPerfInfo
, &SysPerfInfo
, sizeof(SYSTEM_PERFORMANCE_INFORMATION
));
267 * Save system cache info
269 memcpy(&SystemCacheInfo
, &SysCacheInfo
, sizeof(SYSTEM_FILECACHE_INFORMATION
));
272 * Save system processor time info
274 if (SystemProcessorTimeInfo
) {
275 HeapFree(GetProcessHeap(), 0, SystemProcessorTimeInfo
);
277 SystemProcessorTimeInfo
= SysProcessorTimeInfo
;
280 * Save system handle info
282 memcpy(&SystemHandleInfo
, SysHandleInfoData
, sizeof(SYSTEM_HANDLE_INFORMATION
));
283 HeapFree(GetProcessHeap(), 0, SysHandleInfoData
);
285 for (CurrentKernelTime
=0, Idx
=0; Idx
<(ULONG
)SystemBasicInfo
.NumberOfProcessors
; Idx
++) {
286 CurrentKernelTime
+= Li2Double(SystemProcessorTimeInfo
[Idx
].KernelTime
);
287 CurrentKernelTime
+= Li2Double(SystemProcessorTimeInfo
[Idx
].DpcTime
);
288 CurrentKernelTime
+= Li2Double(SystemProcessorTimeInfo
[Idx
].InterruptTime
);
291 /* If it's a first call - skip idle time calcs */
292 if (liOldIdleTime
.QuadPart
!= 0) {
293 /* CurrentValue = NewValue - OldValue */
294 dbIdleTime
= Li2Double(SysPerfInfo
.IdleProcessTime
) - Li2Double(liOldIdleTime
);
295 dbKernelTime
= CurrentKernelTime
- OldKernelTime
;
296 dbSystemTime
= Li2Double(SysTimeInfo
.CurrentTime
) - Li2Double(liOldSystemTime
);
298 /* CurrentCpuIdle = IdleTime / SystemTime */
299 dbIdleTime
= dbIdleTime
/ dbSystemTime
;
300 dbKernelTime
= dbKernelTime
/ dbSystemTime
;
302 /* CurrentCpuUsage% = 100 - (CurrentCpuIdle * 100) / NumberOfProcessors */
303 dbIdleTime
= 100.0 - dbIdleTime
* 100.0 / (double)SystemBasicInfo
.NumberOfProcessors
; /* + 0.5; */
304 dbKernelTime
= 100.0 - dbKernelTime
* 100.0 / (double)SystemBasicInfo
.NumberOfProcessors
; /* + 0.5; */
307 /* Store new CPU's idle and system time */
308 liOldIdleTime
= SysPerfInfo
.IdleProcessTime
;
309 liOldSystemTime
= SysTimeInfo
.CurrentTime
;
310 OldKernelTime
= CurrentKernelTime
;
312 /* Determine the process count
313 * We loop through the data we got from NtQuerySystemInformation
314 * and count how many structures there are (until RelativeOffset is 0)
316 ProcessCountOld
= ProcessCount
;
318 pSPI
= (PSYSTEM_PROCESS_INFORMATION
)pBuffer
;
321 if (pSPI
->NextEntryOffset
== 0)
323 pSPI
= (PSYSTEM_PROCESS_INFORMATION
)((LPBYTE
)pSPI
+ pSPI
->NextEntryOffset
);
326 /* Now alloc a new PERFDATA array and fill in the data */
327 pPerfData
= (PPERFDATA
)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(PERFDATA
) * ProcessCount
);
329 pSPI
= (PSYSTEM_PROCESS_INFORMATION
)pBuffer
;
330 for (Idx
=0; Idx
<ProcessCount
; Idx
++) {
331 /* Get the old perf data for this process (if any) */
332 /* so that we can establish delta values */
335 for (Idx2
=0; Idx2
<ProcessCountOld
; Idx2
++) {
336 if (pPerfDataOld
[Idx2
].ProcessId
== pSPI
->UniqueProcessId
) {
337 pPDOld
= &pPerfDataOld
[Idx2
];
343 if (pSPI
->ImageName
.Buffer
) {
344 /* Don't assume a UNICODE_STRING Buffer is zero terminated: */
345 int len
= pSPI
->ImageName
.Length
/ 2;
346 /* Check against max size and allow for terminating zero (already zeroed): */
347 if(len
>= MAX_PATH
)len
=MAX_PATH
- 1;
348 wcsncpy(pPerfData
[Idx
].ImageName
, pSPI
->ImageName
.Buffer
, len
);
350 LoadStringW(hInst
, IDS_IDLE_PROCESS
, pPerfData
[Idx
].ImageName
,
351 sizeof(pPerfData
[Idx
].ImageName
) / sizeof(pPerfData
[Idx
].ImageName
[0]));
354 pPerfData
[Idx
].ProcessId
= pSPI
->UniqueProcessId
;
357 double CurTime
= Li2Double(pSPI
->KernelTime
) + Li2Double(pSPI
->UserTime
);
358 double OldTime
= Li2Double(pPDOld
->KernelTime
) + Li2Double(pPDOld
->UserTime
);
359 double CpuTime
= (CurTime
- OldTime
) / dbSystemTime
;
360 CpuTime
= CpuTime
* 100.0 / (double)SystemBasicInfo
.NumberOfProcessors
; /* + 0.5; */
361 pPerfData
[Idx
].CPUUsage
= (ULONG
)CpuTime
;
363 pPerfData
[Idx
].CPUTime
.QuadPart
= pSPI
->UserTime
.QuadPart
+ pSPI
->KernelTime
.QuadPart
;
364 pPerfData
[Idx
].WorkingSetSizeBytes
= pSPI
->WorkingSetSize
;
365 pPerfData
[Idx
].PeakWorkingSetSizeBytes
= pSPI
->PeakWorkingSetSize
;
367 pPerfData
[Idx
].WorkingSetSizeDelta
= labs((LONG
)pSPI
->WorkingSetSize
- (LONG
)pPDOld
->WorkingSetSizeBytes
);
369 pPerfData
[Idx
].WorkingSetSizeDelta
= 0;
370 pPerfData
[Idx
].PageFaultCount
= pSPI
->PageFaultCount
;
372 pPerfData
[Idx
].PageFaultCountDelta
= labs((LONG
)pSPI
->PageFaultCount
- (LONG
)pPDOld
->PageFaultCount
);
374 pPerfData
[Idx
].PageFaultCountDelta
= 0;
375 pPerfData
[Idx
].VirtualMemorySizeBytes
= pSPI
->VirtualSize
;
376 pPerfData
[Idx
].PagedPoolUsagePages
= pSPI
->QuotaPeakPagedPoolUsage
;
377 pPerfData
[Idx
].NonPagedPoolUsagePages
= pSPI
->QuotaPeakNonPagedPoolUsage
;
378 pPerfData
[Idx
].BasePriority
= pSPI
->BasePriority
;
379 pPerfData
[Idx
].HandleCount
= pSPI
->HandleCount
;
380 pPerfData
[Idx
].ThreadCount
= pSPI
->NumberOfThreads
;
381 pPerfData
[Idx
].SessionId
= pSPI
->SessionId
;
382 pPerfData
[Idx
].UserName
[0] = UNICODE_NULL
;
383 pPerfData
[Idx
].USERObjectCount
= 0;
384 pPerfData
[Idx
].GDIObjectCount
= 0;
385 ProcessUser
= SystemUserSid
;
388 if (pSPI
->UniqueProcessId
!= NULL
) {
389 hProcess
= OpenProcess(PROCESS_QUERY_INFORMATION
| READ_CONTROL
, FALSE
, PtrToUlong(pSPI
->UniqueProcessId
));
391 /* don't query the information of the system process. It's possible but
392 returns Administrators as the owner of the process instead of SYSTEM */
393 if (pSPI
->UniqueProcessId
!= (HANDLE
)0x4)
395 if (OpenProcessToken(hProcess
, TOKEN_QUERY
, &hProcessToken
))
400 Ret
= GetTokenInformation(hProcessToken
, TokenUser
, (LPVOID
)Buffer
, sizeof(Buffer
), &RetLen
);
401 CloseHandle(hProcessToken
);
404 ProcessUser
= ((PTOKEN_USER
)Buffer
)->User
.Sid
;
411 GetSecurityInfo(hProcess
, SE_KERNEL_OBJECT
, OWNER_SECURITY_INFORMATION
, &ProcessUser
, NULL
, NULL
, NULL
, &ProcessSD
);
414 pPerfData
[Idx
].USERObjectCount
= GetGuiResources(hProcess
, GR_USEROBJECTS
);
415 pPerfData
[Idx
].GDIObjectCount
= GetGuiResources(hProcess
, GR_GDIOBJECTS
);
418 GetProcessIoCounters(hProcess
, &pPerfData
[Idx
].IOCounters
);
419 CloseHandle(hProcess
);
425 /* clear information we were unable to fetch */
426 ZeroMemory(&pPerfData
[Idx
].IOCounters
, sizeof(IO_COUNTERS
));
429 cwcUserName
= sizeof(pPerfData
[0].UserName
) / sizeof(pPerfData
[0].UserName
[0]);
430 CachedGetUserFromSid(ProcessUser
, pPerfData
[Idx
].UserName
, &cwcUserName
);
432 if (ProcessSD
!= NULL
)
434 LocalFree((HLOCAL
)ProcessSD
);
437 pPerfData
[Idx
].UserTime
.QuadPart
= pSPI
->UserTime
.QuadPart
;
438 pPerfData
[Idx
].KernelTime
.QuadPart
= pSPI
->KernelTime
.QuadPart
;
439 pSPI
= (PSYSTEM_PROCESS_INFORMATION
)((LPBYTE
)pSPI
+ pSPI
->NextEntryOffset
);
441 HeapFree(GetProcessHeap(), 0, pBuffer
);
443 HeapFree(GetProcessHeap(), 0, pPerfDataOld
);
445 pPerfDataOld
= pPerfData
;
446 LeaveCriticalSection(&PerfDataCriticalSection
);
449 ULONG
PerfDataGetProcessIndex(ULONG pid
)
453 EnterCriticalSection(&PerfDataCriticalSection
);
455 for (idx
= 0; idx
< ProcessCount
; idx
++)
457 if (PtrToUlong(pPerfData
[idx
].ProcessId
) == pid
)
463 LeaveCriticalSection(&PerfDataCriticalSection
);
465 if (idx
== ProcessCount
)
472 ULONG
PerfDataGetProcessCount(void)
475 EnterCriticalSection(&PerfDataCriticalSection
);
476 Result
= ProcessCount
;
477 LeaveCriticalSection(&PerfDataCriticalSection
);
481 ULONG
PerfDataGetProcessorUsage(void)
484 EnterCriticalSection(&PerfDataCriticalSection
);
485 Result
= (ULONG
)dbIdleTime
;
486 LeaveCriticalSection(&PerfDataCriticalSection
);
490 ULONG
PerfDataGetProcessorSystemUsage(void)
493 EnterCriticalSection(&PerfDataCriticalSection
);
494 Result
= (ULONG
)dbKernelTime
;
495 LeaveCriticalSection(&PerfDataCriticalSection
);
499 BOOL
PerfDataGetImageName(ULONG Index
, LPWSTR lpImageName
, ULONG nMaxCount
)
503 EnterCriticalSection(&PerfDataCriticalSection
);
505 if (Index
< ProcessCount
) {
506 wcsncpy(lpImageName
, pPerfData
[Index
].ImageName
, nMaxCount
);
511 LeaveCriticalSection(&PerfDataCriticalSection
);
515 ULONG
PerfDataGetProcessId(ULONG Index
)
519 EnterCriticalSection(&PerfDataCriticalSection
);
521 if (Index
< ProcessCount
)
522 ProcessId
= PtrToUlong(pPerfData
[Index
].ProcessId
);
526 LeaveCriticalSection(&PerfDataCriticalSection
);
531 BOOL
PerfDataGetUserName(ULONG Index
, LPWSTR lpUserName
, ULONG nMaxCount
)
535 EnterCriticalSection(&PerfDataCriticalSection
);
537 if (Index
< ProcessCount
) {
538 wcsncpy(lpUserName
, pPerfData
[Index
].UserName
, nMaxCount
);
544 LeaveCriticalSection(&PerfDataCriticalSection
);
549 BOOL
PerfDataGetCommandLine(ULONG Index
, LPWSTR lpCommandLine
, ULONG nMaxCount
)
551 static const LPWSTR ellipsis
= L
"...";
553 PROCESS_BASIC_INFORMATION pbi
= {0};
554 UNICODE_STRING CommandLineStr
= {0};
556 PVOID ProcessParams
= NULL
;
563 PCMD_LINE_CACHE new_entry
;
566 PCMD_LINE_CACHE cache
= global_cache
;
568 /* [A] Search for a string already in cache? If so, use it */
569 while (cache
&& cache
->pnext
!= NULL
)
571 if (cache
->idx
== Index
&& cache
->str
!= NULL
)
573 /* Found it. Use it, and add some ellipsis at the very end to make it cute */
574 wcsncpy(lpCommandLine
, cache
->str
, CMD_LINE_MIN(nMaxCount
, cache
->len
));
575 wcscpy(lpCommandLine
+ CMD_LINE_MIN(nMaxCount
, cache
->len
) - wcslen(ellipsis
), ellipsis
);
579 cache
= cache
->pnext
;
582 /* [B] We don't; let's allocate and load a value from the process mem... and cache it */
583 ProcessId
= PerfDataGetProcessId(Index
);
585 /* Default blank command line in case things don't work out */
586 wcsncpy(lpCommandLine
, L
"", nMaxCount
);
588 /* Ask for a handle to the target process so that we can read its memory and query stuff */
589 hProcess
= OpenProcess(PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
, FALSE
, ProcessId
);
593 /* First off, get the ProcessEnvironmentBlock location in that process' address space */
594 Status
= NtQueryInformationProcess(hProcess
, 0, &pbi
, sizeof(pbi
), NULL
);
595 if (!NT_SUCCESS(Status
))
598 /* Then get the PEB.ProcessParameters member pointer */
599 result
= ReadProcessMemory(hProcess
,
600 (PVOID
)((ULONG_PTR
)pbi
.PebBaseAddress
+ FIELD_OFFSET(PEB
, ProcessParameters
)),
602 sizeof(ProcessParams
),
607 /* Then copy the PEB->ProcessParameters.CommandLine member
608 to get the pointer to the string buffer and its size */
609 result
= ReadProcessMemory(hProcess
,
610 (PVOID
)((ULONG_PTR
)ProcessParams
+ FIELD_OFFSET(RTL_USER_PROCESS_PARAMETERS
, CommandLine
)),
612 sizeof(CommandLineStr
),
617 /* Allocate the next cache entry and its accompanying string in one go */
618 new_entry
= HeapAlloc(GetProcessHeap(),
620 sizeof(CMD_LINE_CACHE
) + CommandLineStr
.Length
+ sizeof(UNICODE_NULL
));
624 new_string
= (LPWSTR
)((ULONG_PTR
)new_entry
+ sizeof(CMD_LINE_CACHE
));
626 /* Bingo, the command line should be stored there,
627 copy the string from the other process */
628 result
= ReadProcessMemory(hProcess
,
629 CommandLineStr
.Buffer
,
631 CommandLineStr
.Length
,
635 /* Weird, after successfully reading the mem of that process
636 various times it fails now, forget it and bail out */
637 HeapFree(GetProcessHeap(), 0, new_entry
);
641 /* Add our pointer to the cache... */
642 new_entry
->idx
= Index
;
643 new_entry
->str
= new_string
;
644 new_entry
->len
= CommandLineStr
.Length
;
647 global_cache
= new_entry
;
649 cache
->pnext
= new_entry
;
651 /* ... and print the buffer for the first time */
652 wcsncpy(lpCommandLine
, new_string
, CMD_LINE_MIN(nMaxCount
, CommandLineStr
.Length
));
655 if (hProcess
) CloseHandle(hProcess
);
659 void PerfDataDeallocCommandLineCache()
661 PCMD_LINE_CACHE cache
= global_cache
;
662 PCMD_LINE_CACHE cache_old
;
664 while (cache
&& cache
->pnext
!= NULL
)
667 cache
= cache
->pnext
;
669 HeapFree(GetProcessHeap(), 0, cache_old
);
673 ULONG
PerfDataGetSessionId(ULONG Index
)
677 EnterCriticalSection(&PerfDataCriticalSection
);
679 if (Index
< ProcessCount
)
680 SessionId
= pPerfData
[Index
].SessionId
;
684 LeaveCriticalSection(&PerfDataCriticalSection
);
689 ULONG
PerfDataGetCPUUsage(ULONG Index
)
693 EnterCriticalSection(&PerfDataCriticalSection
);
695 if (Index
< ProcessCount
)
696 CpuUsage
= pPerfData
[Index
].CPUUsage
;
700 LeaveCriticalSection(&PerfDataCriticalSection
);
705 LARGE_INTEGER
PerfDataGetCPUTime(ULONG Index
)
707 LARGE_INTEGER CpuTime
= {{0,0}};
709 EnterCriticalSection(&PerfDataCriticalSection
);
711 if (Index
< ProcessCount
)
712 CpuTime
= pPerfData
[Index
].CPUTime
;
714 LeaveCriticalSection(&PerfDataCriticalSection
);
719 ULONG
PerfDataGetWorkingSetSizeBytes(ULONG Index
)
721 ULONG WorkingSetSizeBytes
;
723 EnterCriticalSection(&PerfDataCriticalSection
);
725 if (Index
< ProcessCount
)
726 WorkingSetSizeBytes
= pPerfData
[Index
].WorkingSetSizeBytes
;
728 WorkingSetSizeBytes
= 0;
730 LeaveCriticalSection(&PerfDataCriticalSection
);
732 return WorkingSetSizeBytes
;
735 ULONG
PerfDataGetPeakWorkingSetSizeBytes(ULONG Index
)
737 ULONG PeakWorkingSetSizeBytes
;
739 EnterCriticalSection(&PerfDataCriticalSection
);
741 if (Index
< ProcessCount
)
742 PeakWorkingSetSizeBytes
= pPerfData
[Index
].PeakWorkingSetSizeBytes
;
744 PeakWorkingSetSizeBytes
= 0;
746 LeaveCriticalSection(&PerfDataCriticalSection
);
748 return PeakWorkingSetSizeBytes
;
751 ULONG
PerfDataGetWorkingSetSizeDelta(ULONG Index
)
753 ULONG WorkingSetSizeDelta
;
755 EnterCriticalSection(&PerfDataCriticalSection
);
757 if (Index
< ProcessCount
)
758 WorkingSetSizeDelta
= pPerfData
[Index
].WorkingSetSizeDelta
;
760 WorkingSetSizeDelta
= 0;
762 LeaveCriticalSection(&PerfDataCriticalSection
);
764 return WorkingSetSizeDelta
;
767 ULONG
PerfDataGetPageFaultCount(ULONG Index
)
769 ULONG PageFaultCount
;
771 EnterCriticalSection(&PerfDataCriticalSection
);
773 if (Index
< ProcessCount
)
774 PageFaultCount
= pPerfData
[Index
].PageFaultCount
;
778 LeaveCriticalSection(&PerfDataCriticalSection
);
780 return PageFaultCount
;
783 ULONG
PerfDataGetPageFaultCountDelta(ULONG Index
)
785 ULONG PageFaultCountDelta
;
787 EnterCriticalSection(&PerfDataCriticalSection
);
789 if (Index
< ProcessCount
)
790 PageFaultCountDelta
= pPerfData
[Index
].PageFaultCountDelta
;
792 PageFaultCountDelta
= 0;
794 LeaveCriticalSection(&PerfDataCriticalSection
);
796 return PageFaultCountDelta
;
799 ULONG
PerfDataGetVirtualMemorySizeBytes(ULONG Index
)
801 ULONG VirtualMemorySizeBytes
;
803 EnterCriticalSection(&PerfDataCriticalSection
);
805 if (Index
< ProcessCount
)
806 VirtualMemorySizeBytes
= pPerfData
[Index
].VirtualMemorySizeBytes
;
808 VirtualMemorySizeBytes
= 0;
810 LeaveCriticalSection(&PerfDataCriticalSection
);
812 return VirtualMemorySizeBytes
;
815 ULONG
PerfDataGetPagedPoolUsagePages(ULONG Index
)
817 ULONG PagedPoolUsage
;
819 EnterCriticalSection(&PerfDataCriticalSection
);
821 if (Index
< ProcessCount
)
822 PagedPoolUsage
= pPerfData
[Index
].PagedPoolUsagePages
;
826 LeaveCriticalSection(&PerfDataCriticalSection
);
828 return PagedPoolUsage
;
831 ULONG
PerfDataGetNonPagedPoolUsagePages(ULONG Index
)
833 ULONG NonPagedPoolUsage
;
835 EnterCriticalSection(&PerfDataCriticalSection
);
837 if (Index
< ProcessCount
)
838 NonPagedPoolUsage
= pPerfData
[Index
].NonPagedPoolUsagePages
;
840 NonPagedPoolUsage
= 0;
842 LeaveCriticalSection(&PerfDataCriticalSection
);
844 return NonPagedPoolUsage
;
847 ULONG
PerfDataGetBasePriority(ULONG Index
)
851 EnterCriticalSection(&PerfDataCriticalSection
);
853 if (Index
< ProcessCount
)
854 BasePriority
= pPerfData
[Index
].BasePriority
;
858 LeaveCriticalSection(&PerfDataCriticalSection
);
863 ULONG
PerfDataGetHandleCount(ULONG Index
)
867 EnterCriticalSection(&PerfDataCriticalSection
);
869 if (Index
< ProcessCount
)
870 HandleCount
= pPerfData
[Index
].HandleCount
;
874 LeaveCriticalSection(&PerfDataCriticalSection
);
879 ULONG
PerfDataGetThreadCount(ULONG Index
)
883 EnterCriticalSection(&PerfDataCriticalSection
);
885 if (Index
< ProcessCount
)
886 ThreadCount
= pPerfData
[Index
].ThreadCount
;
890 LeaveCriticalSection(&PerfDataCriticalSection
);
895 ULONG
PerfDataGetUSERObjectCount(ULONG Index
)
897 ULONG USERObjectCount
;
899 EnterCriticalSection(&PerfDataCriticalSection
);
901 if (Index
< ProcessCount
)
902 USERObjectCount
= pPerfData
[Index
].USERObjectCount
;
906 LeaveCriticalSection(&PerfDataCriticalSection
);
908 return USERObjectCount
;
911 ULONG
PerfDataGetGDIObjectCount(ULONG Index
)
913 ULONG GDIObjectCount
;
915 EnterCriticalSection(&PerfDataCriticalSection
);
917 if (Index
< ProcessCount
)
918 GDIObjectCount
= pPerfData
[Index
].GDIObjectCount
;
922 LeaveCriticalSection(&PerfDataCriticalSection
);
924 return GDIObjectCount
;
927 BOOL
PerfDataGetIOCounters(ULONG Index
, PIO_COUNTERS pIoCounters
)
931 EnterCriticalSection(&PerfDataCriticalSection
);
933 if (Index
< ProcessCount
)
935 memcpy(pIoCounters
, &pPerfData
[Index
].IOCounters
, sizeof(IO_COUNTERS
));
941 LeaveCriticalSection(&PerfDataCriticalSection
);
946 ULONG
PerfDataGetCommitChargeTotalK(void)
951 EnterCriticalSection(&PerfDataCriticalSection
);
953 Total
= SystemPerfInfo
.CommittedPages
;
954 PageSize
= SystemBasicInfo
.PageSize
;
956 LeaveCriticalSection(&PerfDataCriticalSection
);
958 Total
= Total
* (PageSize
/ 1024);
963 ULONG
PerfDataGetCommitChargeLimitK(void)
968 EnterCriticalSection(&PerfDataCriticalSection
);
970 Limit
= SystemPerfInfo
.CommitLimit
;
971 PageSize
= SystemBasicInfo
.PageSize
;
973 LeaveCriticalSection(&PerfDataCriticalSection
);
975 Limit
= Limit
* (PageSize
/ 1024);
980 ULONG
PerfDataGetCommitChargePeakK(void)
985 EnterCriticalSection(&PerfDataCriticalSection
);
987 Peak
= SystemPerfInfo
.PeakCommitment
;
988 PageSize
= SystemBasicInfo
.PageSize
;
990 LeaveCriticalSection(&PerfDataCriticalSection
);
992 Peak
= Peak
* (PageSize
/ 1024);
997 ULONG
PerfDataGetKernelMemoryTotalK(void)
1004 EnterCriticalSection(&PerfDataCriticalSection
);
1006 Paged
= SystemPerfInfo
.PagedPoolPages
;
1007 NonPaged
= SystemPerfInfo
.NonPagedPoolPages
;
1008 PageSize
= SystemBasicInfo
.PageSize
;
1010 LeaveCriticalSection(&PerfDataCriticalSection
);
1012 Paged
= Paged
* (PageSize
/ 1024);
1013 NonPaged
= NonPaged
* (PageSize
/ 1024);
1015 Total
= Paged
+ NonPaged
;
1020 ULONG
PerfDataGetKernelMemoryPagedK(void)
1025 EnterCriticalSection(&PerfDataCriticalSection
);
1027 Paged
= SystemPerfInfo
.PagedPoolPages
;
1028 PageSize
= SystemBasicInfo
.PageSize
;
1030 LeaveCriticalSection(&PerfDataCriticalSection
);
1032 Paged
= Paged
* (PageSize
/ 1024);
1037 ULONG
PerfDataGetKernelMemoryNonPagedK(void)
1042 EnterCriticalSection(&PerfDataCriticalSection
);
1044 NonPaged
= SystemPerfInfo
.NonPagedPoolPages
;
1045 PageSize
= SystemBasicInfo
.PageSize
;
1047 LeaveCriticalSection(&PerfDataCriticalSection
);
1049 NonPaged
= NonPaged
* (PageSize
/ 1024);
1054 ULONG
PerfDataGetPhysicalMemoryTotalK(void)
1059 EnterCriticalSection(&PerfDataCriticalSection
);
1061 Total
= SystemBasicInfo
.NumberOfPhysicalPages
;
1062 PageSize
= SystemBasicInfo
.PageSize
;
1064 LeaveCriticalSection(&PerfDataCriticalSection
);
1066 Total
= Total
* (PageSize
/ 1024);
1071 ULONG
PerfDataGetPhysicalMemoryAvailableK(void)
1076 EnterCriticalSection(&PerfDataCriticalSection
);
1078 Available
= SystemPerfInfo
.AvailablePages
;
1079 PageSize
= SystemBasicInfo
.PageSize
;
1081 LeaveCriticalSection(&PerfDataCriticalSection
);
1083 Available
= Available
* (PageSize
/ 1024);
1088 ULONG
PerfDataGetPhysicalMemorySystemCacheK(void)
1093 EnterCriticalSection(&PerfDataCriticalSection
);
1095 PageSize
= SystemBasicInfo
.PageSize
;
1096 SystemCache
= SystemCacheInfo
.CurrentSizeIncludingTransitionInPages
* PageSize
;
1098 LeaveCriticalSection(&PerfDataCriticalSection
);
1100 return SystemCache
/ 1024;
1103 ULONG
PerfDataGetSystemHandleCount(void)
1107 EnterCriticalSection(&PerfDataCriticalSection
);
1109 HandleCount
= SystemHandleInfo
.NumberOfHandles
;
1111 LeaveCriticalSection(&PerfDataCriticalSection
);
1116 ULONG
PerfDataGetTotalThreadCount(void)
1118 ULONG ThreadCount
= 0;
1121 EnterCriticalSection(&PerfDataCriticalSection
);
1123 for (i
=0; i
<ProcessCount
; i
++)
1125 ThreadCount
+= pPerfData
[i
].ThreadCount
;
1128 LeaveCriticalSection(&PerfDataCriticalSection
);
1133 BOOL
PerfDataGet(ULONG Index
, PPERFDATA
*lppData
)
1135 BOOL bSuccessful
= FALSE
;
1137 EnterCriticalSection(&PerfDataCriticalSection
);
1138 if (Index
< ProcessCount
)
1140 *lppData
= pPerfData
+ Index
;
1143 LeaveCriticalSection(&PerfDataCriticalSection
);