Something went wrong. Try again.
Reactos
Something went wrong. Try again.
33 kB · 1134 lines
C
at listview
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135/* * PROJECT: ReactOS Task Manager * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) * PURPOSE: Performance Counters * COPYRIGHT: Copyright 1999-2001 Brian Palmer <brianp@reactos.org> * Copyright 2014 Ismael Ferreras Morezuelas <swyterzone+ros@gmail.com> */
#include "precomp.h"
#define WIN32_LEAN_AND_MEAN#include <aclapi.h>
#define NTOS_MODE_USER#include <ndk/psfuncs.h>#include <ndk/exfuncs.h>
CRITICAL_SECTION PerfDataCriticalSection;PPERFDATA pPerfDataOld = NULL; /* Older perf data (saved to establish delta values) */PPERFDATA pPerfData = NULL; /* Most recent copy of perf data */ULONG ProcessCountOld = 0;ULONG ProcessCount = 0;double dbIdleTime;double dbKernelTime;double dbSystemTime;LARGE_INTEGER liOldIdleTime = {{0,0}};double OldKernelTime = 0;LARGE_INTEGER liOldSystemTime = {{0,0}};SYSTEM_PERFORMANCE_INFORMATION SystemPerfInfo;SYSTEM_BASIC_INFORMATION SystemBasicInfo;SYSTEM_FILECACHE_INFORMATION SystemCacheInfo;ULONG SystemNumberOfHandles;PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION SystemProcessorTimeInfo = NULL;PSID SystemUserSid = NULL;
PCMD_LINE_CACHE global_cache = NULL;
#define CMD_LINE_MIN(a, b) (a < b ? a - sizeof(WCHAR) : b)
typedef struct _SIDTOUSERNAME{ LIST_ENTRY List; LPWSTR pszName; BYTE Data[0];} SIDTOUSERNAME, *PSIDTOUSERNAME;
static LIST_ENTRY SidToUserNameHead = {&SidToUserNameHead, &SidToUserNameHead};
BOOL PerfDataInitialize(void){ SID_IDENTIFIER_AUTHORITY NtSidAuthority = {SECURITY_NT_AUTHORITY}; NTSTATUS status;
InitializeCriticalSection(&PerfDataCriticalSection);
/* * Get number of processors in the system */ status = NtQuerySystemInformation(SystemBasicInformation, &SystemBasicInfo, sizeof(SystemBasicInfo), NULL); if (!NT_SUCCESS(status)) return FALSE;
/* * Create the SYSTEM Sid */ AllocateAndInitializeSid(&NtSidAuthority, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &SystemUserSid);
/* * Set up global info storage */ SystemProcessorTimeInfo = (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)HeapAlloc(GetProcessHeap(), 0, sizeof(*SystemProcessorTimeInfo) * SystemBasicInfo.NumberOfProcessors);
return SystemProcessorTimeInfo != NULL;}
void PerfDataUninitialize(void){ PLIST_ENTRY pCur; PSIDTOUSERNAME pEntry;
if (pPerfData != NULL) HeapFree(GetProcessHeap(), 0, pPerfData);
DeleteCriticalSection(&PerfDataCriticalSection);
if (SystemUserSid != NULL) { FreeSid(SystemUserSid); SystemUserSid = NULL; }
/* Free user names cache list */ pCur = SidToUserNameHead.Flink; while (pCur != &SidToUserNameHead) { pEntry = CONTAINING_RECORD(pCur, SIDTOUSERNAME, List); pCur = pCur->Flink; HeapFree(GetProcessHeap(), 0, pEntry); }
if (SystemProcessorTimeInfo) { HeapFree(GetProcessHeap(), 0, SystemProcessorTimeInfo); }}
static void SidToUserName(PSID Sid, LPWSTR szBuffer, DWORD BufferSize){ static WCHAR szDomainNameUnused[255]; DWORD DomainNameLen = _countof(szDomainNameUnused); SID_NAME_USE Use;
if (Sid != NULL) LookupAccountSidW(NULL, Sid, szBuffer, &BufferSize, szDomainNameUnused, &DomainNameLen, &Use);}
VOIDWINAPICachedGetUserFromSid( PSID pSid, LPWSTR pUserName, PULONG pcwcUserName){ PLIST_ENTRY pCur; PSIDTOUSERNAME pEntry; ULONG cbSid, cwcUserName;
cwcUserName = *pcwcUserName;
/* Walk through the list */ for(pCur = SidToUserNameHead.Flink; pCur != &SidToUserNameHead; pCur = pCur->Flink) { pEntry = CONTAINING_RECORD(pCur, SIDTOUSERNAME, List); if (EqualSid((PSID)&pEntry->Data, pSid)) { wcsncpy(pUserName, pEntry->pszName, cwcUserName); *pcwcUserName = wcslen(pUserName); return; } }
/* We didn't find the SID in the list, get the name conventional */ SidToUserName(pSid, pUserName, cwcUserName); *pcwcUserName = wcslen(pUserName);
/* Allocate a new entry */ cwcUserName = *pcwcUserName + 1; cbSid = GetLengthSid(pSid); pEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(SIDTOUSERNAME) + cbSid + cwcUserName * sizeof(WCHAR));
/* Copy the Sid and name to our entry */ CopySid(cbSid, (PSID)&pEntry->Data, pSid); pEntry->pszName = (LPWSTR)(pEntry->Data + cbSid); wcsncpy(pEntry->pszName, pUserName, cwcUserName);
/* Insert the new entry */ pEntry->List.Flink = &SidToUserNameHead; pEntry->List.Blink = SidToUserNameHead.Blink; SidToUserNameHead.Blink->Flink = &pEntry->List; SidToUserNameHead.Blink = &pEntry->List;}
void PerfDataRefresh(void){ ULONG ulSize; NTSTATUS status; LPBYTE pBuffer; ULONG BufferSize; PSYSTEM_PROCESS_INFORMATION pSPI; PPERFDATA pPDOld; ULONG Idx, Idx2; HANDLE hProcess; HANDLE hProcessToken; SYSTEM_PERFORMANCE_INFORMATION SysPerfInfo; SYSTEM_TIMEOFDAY_INFORMATION SysTimeInfo; SYSTEM_FILECACHE_INFORMATION SysCacheInfo; SYSTEM_HANDLE_INFORMATION SysHandleInfoData; PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION SysProcessorTimeInfo; double CurrentKernelTime; PSECURITY_DESCRIPTOR ProcessSD; PSID ProcessUser; ULONG Buffer[64]; /* must be 4 bytes aligned! */ ULONG cwcUserName; BOOL bIsWow64;
/* Get new system time */ status = NtQuerySystemInformation(SystemTimeOfDayInformation, &SysTimeInfo, sizeof(SysTimeInfo), NULL); if (!NT_SUCCESS(status)) return;
/* Get new CPU's idle time */ status = NtQuerySystemInformation(SystemPerformanceInformation, &SysPerfInfo, sizeof(SysPerfInfo), NULL); if (!NT_SUCCESS(status)) return;
/* Get system cache information */ status = NtQuerySystemInformation(SystemFileCacheInformation, &SysCacheInfo, sizeof(SysCacheInfo), NULL); if (!NT_SUCCESS(status)) return;
/* Get processor time information */ SysProcessorTimeInfo = (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)HeapAlloc(GetProcessHeap(), 0, sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * SystemBasicInfo.NumberOfProcessors); status = NtQuerySystemInformation(SystemProcessorPerformanceInformation, SysProcessorTimeInfo, sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * SystemBasicInfo.NumberOfProcessors, &ulSize);
if (!NT_SUCCESS(status)) { if (SysProcessorTimeInfo != NULL) HeapFree(GetProcessHeap(), 0, SysProcessorTimeInfo); return; }
/* Get handle information * Number of handles is enough, no need for data array. */ status = NtQuerySystemInformation(SystemHandleInformation, &SysHandleInfoData, sizeof(SysHandleInfoData), NULL); /* On unexpected error, reuse previous value. * STATUS_SUCCESS (0-1 handle) should never happen. */ if (status != STATUS_INFO_LENGTH_MISMATCH) SysHandleInfoData.NumberOfHandles = SystemNumberOfHandles;
/* Get process information * We don't know how much data there is so just keep * increasing the buffer size until the call succeeds */ BufferSize = 0; do { BufferSize += 0x10000; pBuffer = (LPBYTE)HeapAlloc(GetProcessHeap(), 0, BufferSize);
status = NtQuerySystemInformation(SystemProcessInformation, pBuffer, BufferSize, &ulSize);
if (status == STATUS_INFO_LENGTH_MISMATCH) { HeapFree(GetProcessHeap(), 0, pBuffer); }
} while (status == STATUS_INFO_LENGTH_MISMATCH);
EnterCriticalSection(&PerfDataCriticalSection);
/* * Save system performance info */ memcpy(&SystemPerfInfo, &SysPerfInfo, sizeof(SYSTEM_PERFORMANCE_INFORMATION));
/* * Save system cache info */ memcpy(&SystemCacheInfo, &SysCacheInfo, sizeof(SYSTEM_FILECACHE_INFORMATION));
/* * Save system processor time info */ memcpy(SystemProcessorTimeInfo, SysProcessorTimeInfo, sizeof(*SystemProcessorTimeInfo) * SystemBasicInfo.NumberOfProcessors);
if (SysProcessorTimeInfo) { HeapFree(GetProcessHeap(), 0, SysProcessorTimeInfo); }
/* * Save system handle info */ SystemNumberOfHandles = SysHandleInfoData.NumberOfHandles;
for (CurrentKernelTime=0, Idx=0; Idx<(ULONG)SystemBasicInfo.NumberOfProcessors; Idx++) { CurrentKernelTime += Li2Double(SystemProcessorTimeInfo[Idx].KernelTime); CurrentKernelTime += Li2Double(SystemProcessorTimeInfo[Idx].DpcTime); CurrentKernelTime += Li2Double(SystemProcessorTimeInfo[Idx].InterruptTime); }
/* If it's a first call - skip idle time calcs */ if (liOldIdleTime.QuadPart != 0) { /* CurrentValue = NewValue - OldValue */ dbIdleTime = Li2Double(SysPerfInfo.IdleProcessTime) - Li2Double(liOldIdleTime); dbKernelTime = CurrentKernelTime - OldKernelTime; dbSystemTime = Li2Double(SysTimeInfo.CurrentTime) - Li2Double(liOldSystemTime);
/* CurrentCpuIdle = IdleTime / SystemTime */ dbIdleTime = dbIdleTime / dbSystemTime; dbKernelTime = dbKernelTime / dbSystemTime;
/* CurrentCpuUsage% = 100 - (CurrentCpuIdle * 100) / NumberOfProcessors */ dbIdleTime = 100.0 - dbIdleTime * 100.0 / (double)SystemBasicInfo.NumberOfProcessors; /* + 0.5; */ dbKernelTime = 100.0 - dbKernelTime * 100.0 / (double)SystemBasicInfo.NumberOfProcessors; /* + 0.5; */ }
/* Store new CPU's idle and system time */ liOldIdleTime = SysPerfInfo.IdleProcessTime; liOldSystemTime = SysTimeInfo.CurrentTime; OldKernelTime = CurrentKernelTime;
/* Determine the process count * We loop through the data we got from NtQuerySystemInformation * and count how many structures there are (until RelativeOffset is 0) */ ProcessCountOld = ProcessCount; ProcessCount = 0; pSPI = (PSYSTEM_PROCESS_INFORMATION)pBuffer; while (pSPI) { ProcessCount++; if (pSPI->NextEntryOffset == 0) break; pSPI = (PSYSTEM_PROCESS_INFORMATION)((LPBYTE)pSPI + pSPI->NextEntryOffset); }
/* Now alloc a new PERFDATA array and fill in the data */ pPerfData = (PPERFDATA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PERFDATA) * ProcessCount);
pSPI = (PSYSTEM_PROCESS_INFORMATION)pBuffer; for (Idx=0; Idx<ProcessCount; Idx++) { /* Get the old perf data for this process (if any) */ /* so that we can establish delta values */ pPDOld = NULL; if (pPerfDataOld) { for (Idx2=0; Idx2<ProcessCountOld; Idx2++) { if (pPerfDataOld[Idx2].ProcessId == pSPI->UniqueProcessId) { pPDOld = &pPerfDataOld[Idx2]; break; } } }
if (pSPI->ImageName.Buffer) { /* Don't assume a UNICODE_STRING Buffer is zero terminated: */ int len = pSPI->ImageName.Length / 2; /* Check against max size and allow for terminating zero (already zeroed): */ if(len >= MAX_PATH)len=MAX_PATH - 1; wcsncpy(pPerfData[Idx].ImageName, pSPI->ImageName.Buffer, len); } else { LoadStringW(hInst, IDS_IDLE_PROCESS, pPerfData[Idx].ImageName, _countof(pPerfData[Idx].ImageName)); }
pPerfData[Idx].ProcessId = pSPI->UniqueProcessId;
if (pPDOld) { double CurTime = Li2Double(pSPI->KernelTime) + Li2Double(pSPI->UserTime); double OldTime = Li2Double(pPDOld->KernelTime) + Li2Double(pPDOld->UserTime); double CpuTime = (CurTime - OldTime) / dbSystemTime; CpuTime = CpuTime * 100.0 / (double)SystemBasicInfo.NumberOfProcessors; /* + 0.5; */ pPerfData[Idx].CPUUsage = (ULONG)CpuTime; } pPerfData[Idx].CPUTime.QuadPart = pSPI->UserTime.QuadPart + pSPI->KernelTime.QuadPart; pPerfData[Idx].WorkingSetSizeBytes = pSPI->WorkingSetSize; pPerfData[Idx].PeakWorkingSetSizeBytes = pSPI->PeakWorkingSetSize; if (pPDOld) pPerfData[Idx].WorkingSetSizeDelta = labs((LONG)pSPI->WorkingSetSize - (LONG)pPDOld->WorkingSetSizeBytes); else pPerfData[Idx].WorkingSetSizeDelta = 0; pPerfData[Idx].PageFaultCount = pSPI->PageFaultCount; if (pPDOld) pPerfData[Idx].PageFaultCountDelta = labs((LONG)pSPI->PageFaultCount - (LONG)pPDOld->PageFaultCount); else pPerfData[Idx].PageFaultCountDelta = 0; pPerfData[Idx].VirtualMemorySizeBytes = pSPI->VirtualSize; pPerfData[Idx].PagedPoolUsagePages = pSPI->QuotaPeakPagedPoolUsage; pPerfData[Idx].NonPagedPoolUsagePages = pSPI->QuotaPeakNonPagedPoolUsage; pPerfData[Idx].BasePriority = pSPI->BasePriority; pPerfData[Idx].HandleCount = pSPI->HandleCount; pPerfData[Idx].ThreadCount = pSPI->NumberOfThreads; pPerfData[Idx].SessionId = pSPI->SessionId; pPerfData[Idx].UserName[0] = UNICODE_NULL; pPerfData[Idx].USERObjectCount = 0; pPerfData[Idx].GDIObjectCount = 0; ProcessUser = SystemUserSid; ProcessSD = NULL;
if (pSPI->UniqueProcessId != NULL) { hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | READ_CONTROL, FALSE, PtrToUlong(pSPI->UniqueProcessId)); if (hProcess) { /* don't query the information of the system process. It's possible but returns Administrators as the owner of the process instead of SYSTEM */ if (pSPI->UniqueProcessId != (HANDLE)0x4) { if (OpenProcessToken(hProcess, TOKEN_QUERY, &hProcessToken)) { DWORD RetLen = 0; BOOL Ret;
Ret = GetTokenInformation(hProcessToken, TokenUser, (LPVOID)Buffer, sizeof(Buffer), &RetLen); CloseHandle(hProcessToken);
if (Ret) ProcessUser = ((PTOKEN_USER)Buffer)->User.Sid; else goto ReadProcOwner; } else {ReadProcOwner: GetSecurityInfo(hProcess, SE_KERNEL_OBJECT, OWNER_SECURITY_INFORMATION, &ProcessUser, NULL, NULL, NULL, &ProcessSD); }
pPerfData[Idx].USERObjectCount = GetGuiResources(hProcess, GR_USEROBJECTS); pPerfData[Idx].GDIObjectCount = GetGuiResources(hProcess, GR_GDIOBJECTS); }
if (IsWow64Process(hProcess, &bIsWow64) && bIsWow64) { wcscat(pPerfData[Idx].ImageName, L" *32"); }
GetProcessIoCounters(hProcess, &pPerfData[Idx].IOCounters); CloseHandle(hProcess); } else { goto ClearInfo; } } else {ClearInfo: /* clear information we were unable to fetch */ ZeroMemory(&pPerfData[Idx].IOCounters, sizeof(IO_COUNTERS)); }
cwcUserName = _countof(pPerfData[0].UserName); CachedGetUserFromSid(ProcessUser, pPerfData[Idx].UserName, &cwcUserName);
if (ProcessSD != NULL) { LocalFree((HLOCAL)ProcessSD); }
pPerfData[Idx].UserTime.QuadPart = pSPI->UserTime.QuadPart; pPerfData[Idx].KernelTime.QuadPart = pSPI->KernelTime.QuadPart; pSPI = (PSYSTEM_PROCESS_INFORMATION)((LPBYTE)pSPI + pSPI->NextEntryOffset); } HeapFree(GetProcessHeap(), 0, pBuffer); if (pPerfDataOld) { HeapFree(GetProcessHeap(), 0, pPerfDataOld); } pPerfDataOld = pPerfData; LeaveCriticalSection(&PerfDataCriticalSection);}
ULONG PerfDataGetProcessIndex(ULONG pid){ ULONG idx;
EnterCriticalSection(&PerfDataCriticalSection);
for (idx = 0; idx < ProcessCount; idx++) { if (PtrToUlong(pPerfData[idx].ProcessId) == pid) { break; } }
LeaveCriticalSection(&PerfDataCriticalSection);
if (idx == ProcessCount) { return -1; } return idx;}
ULONG PerfDataGetProcessCount(void){ ULONG Result; EnterCriticalSection(&PerfDataCriticalSection); Result = ProcessCount; LeaveCriticalSection(&PerfDataCriticalSection); return Result;}
ULONG PerfDataGetProcessorUsage(void){ ULONG Result; EnterCriticalSection(&PerfDataCriticalSection); Result = (ULONG)min(max(dbIdleTime, 0.), 100.); LeaveCriticalSection(&PerfDataCriticalSection); return Result;}
ULONG PerfDataGetProcessorSystemUsage(void){ ULONG Result; EnterCriticalSection(&PerfDataCriticalSection); Result = (ULONG)min(max(dbKernelTime, 0.), 100.); LeaveCriticalSection(&PerfDataCriticalSection); return Result;}
BOOL PerfDataGetImageName(ULONG Index, LPWSTR lpImageName, ULONG nMaxCount){ BOOL bSuccessful;
EnterCriticalSection(&PerfDataCriticalSection);
if (Index < ProcessCount) { wcsncpy(lpImageName, pPerfData[Index].ImageName, nMaxCount); bSuccessful = TRUE; } else { bSuccessful = FALSE; } LeaveCriticalSection(&PerfDataCriticalSection); return bSuccessful;}
ULONG PerfDataGetProcessId(ULONG Index){ ULONG ProcessId;
EnterCriticalSection(&PerfDataCriticalSection);
if (Index < ProcessCount) ProcessId = PtrToUlong(pPerfData[Index].ProcessId); else ProcessId = 0;
LeaveCriticalSection(&PerfDataCriticalSection);
return ProcessId;}
BOOL PerfDataGetUserName(ULONG Index, LPWSTR lpUserName, ULONG nMaxCount){ BOOL bSuccessful;
EnterCriticalSection(&PerfDataCriticalSection);
if (Index < ProcessCount) { wcsncpy(lpUserName, pPerfData[Index].UserName, nMaxCount); bSuccessful = TRUE; } else { bSuccessful = FALSE; }
LeaveCriticalSection(&PerfDataCriticalSection);
return bSuccessful;}
BOOL PerfDataGetCommandLine(ULONG Index, LPWSTR lpCommandLine, ULONG nMaxCount){ static const LPWSTR ellipsis = L"...";
PROCESS_BASIC_INFORMATION pbi = {0}; UNICODE_STRING CommandLineStr = {0};
PVOID ProcessParams = NULL; HANDLE hProcess; ULONG ProcessId;
NTSTATUS Status; BOOL result;
PCMD_LINE_CACHE new_entry; LPWSTR new_string;
PCMD_LINE_CACHE cache = global_cache;
/* [A] Search for a string already in cache? If so, use it */ while (cache && cache->pnext != NULL) { if (cache->idx == Index && cache->str != NULL) { /* Found it. Use it, and add some ellipsis at the very end to make it cute */ wcsncpy(lpCommandLine, cache->str, CMD_LINE_MIN(nMaxCount, cache->len)); wcscpy(lpCommandLine + CMD_LINE_MIN(nMaxCount, cache->len) - wcslen(ellipsis), ellipsis); return TRUE; }
cache = cache->pnext; }
/* [B] We don't; let's allocate and load a value from the process mem... and cache it */ ProcessId = PerfDataGetProcessId(Index);
/* Default blank command line in case things don't work out */ wcsncpy(lpCommandLine, L"", nMaxCount);
/* Ask for a handle to the target process so that we can read its memory and query stuff */ hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, ProcessId); if (!hProcess) goto cleanup;
/* First off, get the ProcessEnvironmentBlock location in that process' address space */ Status = NtQueryInformationProcess(hProcess, 0, &pbi, sizeof(pbi), NULL); if (!NT_SUCCESS(Status)) goto cleanup;
/* Then get the PEB.ProcessParameters member pointer */ result = ReadProcessMemory(hProcess, (PVOID)((ULONG_PTR)pbi.PebBaseAddress + FIELD_OFFSET(PEB, ProcessParameters)), &ProcessParams, sizeof(ProcessParams), NULL); if (!result) goto cleanup;
/* Then copy the PEB->ProcessParameters.CommandLine member to get the pointer to the string buffer and its size */ result = ReadProcessMemory(hProcess, (PVOID)((ULONG_PTR)ProcessParams + FIELD_OFFSET(RTL_USER_PROCESS_PARAMETERS, CommandLine)), &CommandLineStr, sizeof(CommandLineStr), NULL); if (!result) goto cleanup;
/* Allocate the next cache entry and its accompanying string in one go */ new_entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CMD_LINE_CACHE) + CommandLineStr.Length + sizeof(UNICODE_NULL)); if (!new_entry) goto cleanup;
new_string = (LPWSTR)((ULONG_PTR)new_entry + sizeof(CMD_LINE_CACHE));
/* Bingo, the command line should be stored there, copy the string from the other process */ result = ReadProcessMemory(hProcess, CommandLineStr.Buffer, new_string, CommandLineStr.Length, NULL); if (!result) { /* Weird, after successfully reading the mem of that process various times it fails now, forget it and bail out */ HeapFree(GetProcessHeap(), 0, new_entry); goto cleanup; }
/* Add our pointer to the cache... */ new_entry->idx = Index; new_entry->str = new_string; new_entry->len = CommandLineStr.Length;
if (!global_cache) global_cache = new_entry; else cache->pnext = new_entry;
/* ... and print the buffer for the first time */ wcsncpy(lpCommandLine, new_string, CMD_LINE_MIN(nMaxCount, CommandLineStr.Length));
cleanup: if (hProcess) CloseHandle(hProcess); return TRUE;}
void PerfDataDeallocCommandLineCache(){ PCMD_LINE_CACHE cache, pnext;
for (cache = global_cache; cache; cache = pnext) { pnext = cache->pnext; HeapFree(GetProcessHeap(), 0, cache); }
global_cache = NULL;}
ULONG PerfDataGetSessionId(ULONG Index){ ULONG SessionId;
EnterCriticalSection(&PerfDataCriticalSection);
if (Index < ProcessCount) SessionId = pPerfData[Index].SessionId; else SessionId = 0;
LeaveCriticalSection(&PerfDataCriticalSection);
return SessionId;}
ULONG PerfDataGetCPUUsage(ULONG Index){ ULONG CpuUsage;
EnterCriticalSection(&PerfDataCriticalSection);
if (Index < ProcessCount) CpuUsage = pPerfData[Index].CPUUsage; else CpuUsage = 0;
LeaveCriticalSection(&PerfDataCriticalSection);
return CpuUsage;}
LARGE_INTEGER PerfDataGetCPUTime(ULONG Index){ LARGE_INTEGER CpuTime = {{0,0}};
EnterCriticalSection(&PerfDataCriticalSection);
if (Index < ProcessCount) CpuTime = pPerfData[Index].CPUTime;
LeaveCriticalSection(&PerfDataCriticalSection);
return CpuTime;}
ULONG PerfDataGetWorkingSetSizeBytes(ULONG Index){ ULONG WorkingSetSizeBytes;
EnterCriticalSection(&PerfDataCriticalSection);
if (Index < ProcessCount) WorkingSetSizeBytes = pPerfData[Index].WorkingSetSizeBytes; else WorkingSetSizeBytes = 0;
LeaveCriticalSection(&PerfDataCriticalSection);
return WorkingSetSizeBytes;}
ULONG PerfDataGetPeakWorkingSetSizeBytes(ULONG Index){ ULONG PeakWorkingSetSizeBytes;
EnterCriticalSection(&PerfDataCriticalSection);
if (Index < ProcessCount) PeakWorkingSetSizeBytes = pPerfData[Index].PeakWorkingSetSizeBytes; else PeakWorkingSetSizeBytes = 0;
LeaveCriticalSection(&PerfDataCriticalSection);
return PeakWorkingSetSizeBytes;}
ULONG PerfDataGetWorkingSetSizeDelta(ULONG Index){ ULONG WorkingSetSizeDelta;
EnterCriticalSection(&PerfDataCriticalSection);
if (Index < ProcessCount) WorkingSetSizeDelta = pPerfData[Index].WorkingSetSizeDelta; else WorkingSetSizeDelta = 0;
LeaveCriticalSection(&PerfDataCriticalSection);
return WorkingSetSizeDelta;}
ULONG PerfDataGetPageFaultCount(ULONG Index){ ULONG PageFaultCount;
EnterCriticalSection(&PerfDataCriticalSection);
if (Index < ProcessCount) PageFaultCount = pPerfData[Index].PageFaultCount; else PageFaultCount = 0;
LeaveCriticalSection(&PerfDataCriticalSection);
return PageFaultCount;}
ULONG PerfDataGetPageFaultCountDelta(ULONG Index){ ULONG PageFaultCountDelta;
EnterCriticalSection(&PerfDataCriticalSection);
if (Index < ProcessCount) PageFaultCountDelta = pPerfData[Index].PageFaultCountDelta; else PageFaultCountDelta = 0;
LeaveCriticalSection(&PerfDataCriticalSection);
return PageFaultCountDelta;}
ULONG PerfDataGetVirtualMemorySizeBytes(ULONG Index){ ULONG VirtualMemorySizeBytes;
EnterCriticalSection(&PerfDataCriticalSection);
if (Index < ProcessCount) VirtualMemorySizeBytes = pPerfData[Index].VirtualMemorySizeBytes; else VirtualMemorySizeBytes = 0;
LeaveCriticalSection(&PerfDataCriticalSection);
return VirtualMemorySizeBytes;}
ULONG PerfDataGetPagedPoolUsagePages(ULONG Index){ ULONG PagedPoolUsage;
EnterCriticalSection(&PerfDataCriticalSection);
if (Index < ProcessCount) PagedPoolUsage = pPerfData[Index].PagedPoolUsagePages; else PagedPoolUsage = 0;
LeaveCriticalSection(&PerfDataCriticalSection);
return PagedPoolUsage;}
ULONG PerfDataGetNonPagedPoolUsagePages(ULONG Index){ ULONG NonPagedPoolUsage;
EnterCriticalSection(&PerfDataCriticalSection);
if (Index < ProcessCount) NonPagedPoolUsage = pPerfData[Index].NonPagedPoolUsagePages; else NonPagedPoolUsage = 0;
LeaveCriticalSection(&PerfDataCriticalSection);
return NonPagedPoolUsage;}
ULONG PerfDataGetBasePriority(ULONG Index){ ULONG BasePriority;
EnterCriticalSection(&PerfDataCriticalSection);
if (Index < ProcessCount) BasePriority = pPerfData[Index].BasePriority; else BasePriority = 0;
LeaveCriticalSection(&PerfDataCriticalSection);
return BasePriority;}
ULONG PerfDataGetHandleCount(ULONG Index){ ULONG HandleCount;
EnterCriticalSection(&PerfDataCriticalSection);
if (Index < ProcessCount) HandleCount = pPerfData[Index].HandleCount; else HandleCount = 0;
LeaveCriticalSection(&PerfDataCriticalSection);
return HandleCount;}
ULONG PerfDataGetThreadCount(ULONG Index){ ULONG ThreadCount;
EnterCriticalSection(&PerfDataCriticalSection);
if (Index < ProcessCount) ThreadCount = pPerfData[Index].ThreadCount; else ThreadCount = 0;
LeaveCriticalSection(&PerfDataCriticalSection);
return ThreadCount;}
ULONG PerfDataGetUSERObjectCount(ULONG Index){ ULONG USERObjectCount;
EnterCriticalSection(&PerfDataCriticalSection);
if (Index < ProcessCount) USERObjectCount = pPerfData[Index].USERObjectCount; else USERObjectCount = 0;
LeaveCriticalSection(&PerfDataCriticalSection);
return USERObjectCount;}
ULONG PerfDataGetGDIObjectCount(ULONG Index){ ULONG GDIObjectCount;
EnterCriticalSection(&PerfDataCriticalSection);
if (Index < ProcessCount) GDIObjectCount = pPerfData[Index].GDIObjectCount; else GDIObjectCount = 0;
LeaveCriticalSection(&PerfDataCriticalSection);
return GDIObjectCount;}
BOOL PerfDataGetIOCounters(ULONG Index, PIO_COUNTERS pIoCounters){ BOOL bSuccessful;
EnterCriticalSection(&PerfDataCriticalSection);
if (Index < ProcessCount) { memcpy(pIoCounters, &pPerfData[Index].IOCounters, sizeof(IO_COUNTERS)); bSuccessful = TRUE; } else bSuccessful = FALSE;
LeaveCriticalSection(&PerfDataCriticalSection);
return bSuccessful;}
ULONG PerfDataGetCommitChargeTotalK(void){ ULONG Total; ULONG PageSize;
EnterCriticalSection(&PerfDataCriticalSection);
Total = SystemPerfInfo.CommittedPages; PageSize = SystemBasicInfo.PageSize;
LeaveCriticalSection(&PerfDataCriticalSection);
Total = Total * (PageSize / 1024);
return Total;}
ULONG PerfDataGetCommitChargeLimitK(void){ ULONG Limit; ULONG PageSize;
EnterCriticalSection(&PerfDataCriticalSection);
Limit = SystemPerfInfo.CommitLimit; PageSize = SystemBasicInfo.PageSize;
LeaveCriticalSection(&PerfDataCriticalSection);
Limit = Limit * (PageSize / 1024);
return Limit;}
ULONG PerfDataGetCommitChargePeakK(void){ ULONG Peak; ULONG PageSize;
EnterCriticalSection(&PerfDataCriticalSection);
Peak = SystemPerfInfo.PeakCommitment; PageSize = SystemBasicInfo.PageSize;
LeaveCriticalSection(&PerfDataCriticalSection);
Peak = Peak * (PageSize / 1024);
return Peak;}
ULONG PerfDataGetKernelMemoryTotalK(void){ ULONG Total; ULONG Paged; ULONG NonPaged; ULONG PageSize;
EnterCriticalSection(&PerfDataCriticalSection);
Paged = SystemPerfInfo.PagedPoolPages; NonPaged = SystemPerfInfo.NonPagedPoolPages; PageSize = SystemBasicInfo.PageSize;
LeaveCriticalSection(&PerfDataCriticalSection);
Paged = Paged * (PageSize / 1024); NonPaged = NonPaged * (PageSize / 1024);
Total = Paged + NonPaged;
return Total;}
ULONG PerfDataGetKernelMemoryPagedK(void){ ULONG Paged; ULONG PageSize;
EnterCriticalSection(&PerfDataCriticalSection);
Paged = SystemPerfInfo.PagedPoolPages; PageSize = SystemBasicInfo.PageSize;
LeaveCriticalSection(&PerfDataCriticalSection);
Paged = Paged * (PageSize / 1024);
return Paged;}
ULONG PerfDataGetKernelMemoryNonPagedK(void){ ULONG NonPaged; ULONG PageSize;
EnterCriticalSection(&PerfDataCriticalSection);
NonPaged = SystemPerfInfo.NonPagedPoolPages; PageSize = SystemBasicInfo.PageSize;
LeaveCriticalSection(&PerfDataCriticalSection);
NonPaged = NonPaged * (PageSize / 1024);
return NonPaged;}
ULONG PerfDataGetPhysicalMemoryTotalK(void){ ULONG Total; ULONG PageSize;
EnterCriticalSection(&PerfDataCriticalSection);
Total = SystemBasicInfo.NumberOfPhysicalPages; PageSize = SystemBasicInfo.PageSize;
LeaveCriticalSection(&PerfDataCriticalSection);
Total = Total * (PageSize / 1024);
return Total;}
ULONG PerfDataGetPhysicalMemoryAvailableK(void){ ULONG Available; ULONG PageSize;
EnterCriticalSection(&PerfDataCriticalSection);
Available = SystemPerfInfo.AvailablePages; PageSize = SystemBasicInfo.PageSize;
LeaveCriticalSection(&PerfDataCriticalSection);
Available = Available * (PageSize / 1024);
return Available;}
ULONG PerfDataGetPhysicalMemorySystemCacheK(void){ ULONG SystemCache; ULONG PageSize;
EnterCriticalSection(&PerfDataCriticalSection);
PageSize = SystemBasicInfo.PageSize; SystemCache = SystemCacheInfo.CurrentSizeIncludingTransitionInPages * PageSize;
LeaveCriticalSection(&PerfDataCriticalSection);
return SystemCache / 1024;}
ULONG PerfDataGetSystemHandleCount(void){ ULONG HandleCount;
EnterCriticalSection(&PerfDataCriticalSection);
HandleCount = SystemNumberOfHandles;
LeaveCriticalSection(&PerfDataCriticalSection);
return HandleCount;}
ULONG PerfDataGetTotalThreadCount(void){ ULONG ThreadCount = 0; ULONG i;
EnterCriticalSection(&PerfDataCriticalSection);
for (i=0; i<ProcessCount; i++) { ThreadCount += pPerfData[i].ThreadCount; }
LeaveCriticalSection(&PerfDataCriticalSection);
return ThreadCount;}
BOOL PerfDataGet(ULONG Index, PPERFDATA *lppData){ BOOL bSuccessful = FALSE;
EnterCriticalSection(&PerfDataCriticalSection); if (Index < ProcessCount) { *lppData = pPerfData + Index; bSuccessful = TRUE; } LeaveCriticalSection(&PerfDataCriticalSection); return bSuccessful;}