|  | /* | 
|  | *  ReactOS Task Manager | 
|  | * | 
|  | *  perfdata.c | 
|  | * | 
|  | *  Copyright (C) 1999 - 2001  Brian Palmer  <brianp@reactos.org> | 
|  | * | 
|  | * This library is free software; you can redistribute it and/or | 
|  | * modify it under the terms of the GNU Lesser General Public | 
|  | * License as published by the Free Software Foundation; either | 
|  | * version 2.1 of the License, or (at your option) any later version. | 
|  | * | 
|  | * This library is distributed in the hope that it will be useful, | 
|  | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|  | * Lesser General Public License for more details. | 
|  | * | 
|  | * You should have received a copy of the GNU Lesser General Public | 
|  | * License along with this library; if not, write to the Free Software | 
|  | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA | 
|  | */ | 
|  |  | 
|  | #define WIN32_LEAN_AND_MEAN    /* Exclude rarely-used stuff from Windows headers */ | 
|  | #include <windows.h> | 
|  | #include <commctrl.h> | 
|  | #include <stdlib.h> | 
|  | #include <malloc.h> | 
|  | #include <memory.h> | 
|  | #include <tchar.h> | 
|  | #include <stdio.h> | 
|  | #include <winnt.h> | 
|  | #include "taskmgr.h" | 
|  | #include "perfdata.h" | 
|  |  | 
|  | PROCNTQSI                        NtQuerySystemInformation = NULL; | 
|  | PROCGGR                            pGetGuiResources = NULL; | 
|  | PROCGPIC                        pGetProcessIoCounters = NULL; | 
|  | 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_CACHE_INFORMATION        SystemCacheInfo; | 
|  | SYSTEM_HANDLE_INFORMATION        SystemHandleInfo; | 
|  | PSYSTEM_PROCESSORTIME_INFO        SystemProcessorTimeInfo = NULL; | 
|  |  | 
|  | BOOL PerfDataInitialize(void) | 
|  | { | 
|  | LONG    status; | 
|  |  | 
|  | NtQuerySystemInformation = (PROCNTQSI)GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "NtQuerySystemInformation"); | 
|  | pGetGuiResources = (PROCGGR)GetProcAddress(GetModuleHandle(_T("user32.dll")), "GetGuiResources"); | 
|  | pGetProcessIoCounters = (PROCGPIC)GetProcAddress(GetModuleHandle(_T("kernel32.dll")), "GetProcessIoCounters"); | 
|  |  | 
|  | InitializeCriticalSection(&PerfDataCriticalSection); | 
|  |  | 
|  | if (!NtQuerySystemInformation) | 
|  | return FALSE; | 
|  |  | 
|  | /* | 
|  | * Get number of processors in the system | 
|  | */ | 
|  | status = NtQuerySystemInformation(SystemBasicInformation, &SystemBasicInfo, sizeof(SystemBasicInfo), NULL); | 
|  | if (status != NO_ERROR) | 
|  | return FALSE; | 
|  |  | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  | void PerfDataUninitialize(void) | 
|  | { | 
|  | NtQuerySystemInformation = NULL; | 
|  |  | 
|  | DeleteCriticalSection(&PerfDataCriticalSection); | 
|  | } | 
|  |  | 
|  | void PerfDataRefresh(void) | 
|  | { | 
|  | ULONG                            ulSize; | 
|  | LONG                            status; | 
|  | LPBYTE                            pBuffer; | 
|  | ULONG                            BufferSize; | 
|  | PSYSTEM_PROCESS_INFORMATION        pSPI; | 
|  | PPERFDATA                        pPDOld; | 
|  | ULONG                            Idx, Idx2; | 
|  | HANDLE                            hProcess; | 
|  | HANDLE                            hProcessToken; | 
|  | TCHAR                            szTemp[MAX_PATH]; | 
|  | DWORD                            dwSize; | 
|  | SYSTEM_PERFORMANCE_INFORMATION    SysPerfInfo; | 
|  | SYSTEM_TIME_INFORMATION            SysTimeInfo; | 
|  | SYSTEM_CACHE_INFORMATION        SysCacheInfo; | 
|  | LPBYTE                            SysHandleInfoData; | 
|  | PSYSTEM_PROCESSORTIME_INFO        SysProcessorTimeInfo; | 
|  | double                            CurrentKernelTime; | 
|  |  | 
|  |  | 
|  | if (!NtQuerySystemInformation) | 
|  | return; | 
|  |  | 
|  | /* Get new system time */ | 
|  | status = NtQuerySystemInformation(SystemTimeInformation, &SysTimeInfo, sizeof(SysTimeInfo), 0); | 
|  | if (status != NO_ERROR) | 
|  | return; | 
|  |  | 
|  | /* Get new CPU's idle time */ | 
|  | status = NtQuerySystemInformation(SystemPerformanceInformation, &SysPerfInfo, sizeof(SysPerfInfo), NULL); | 
|  | if (status != NO_ERROR) | 
|  | return; | 
|  |  | 
|  | /* Get system cache information */ | 
|  | status = NtQuerySystemInformation(SystemCacheInformation, &SysCacheInfo, sizeof(SysCacheInfo), NULL); | 
|  | if (status != NO_ERROR) | 
|  | return; | 
|  |  | 
|  | /* Get processor time information */ | 
|  | SysProcessorTimeInfo = (PSYSTEM_PROCESSORTIME_INFO)malloc(sizeof(SYSTEM_PROCESSORTIME_INFO) * SystemBasicInfo.bKeNumberProcessors); | 
|  | status = NtQuerySystemInformation(SystemProcessorTimeInformation, SysProcessorTimeInfo, sizeof(SYSTEM_PROCESSORTIME_INFO) * SystemBasicInfo.bKeNumberProcessors, &ulSize); | 
|  | if (status != NO_ERROR) | 
|  | return; | 
|  |  | 
|  | /* Get handle 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; | 
|  | SysHandleInfoData = (LPBYTE)malloc(BufferSize); | 
|  |  | 
|  | status = NtQuerySystemInformation(SystemHandleInformation, SysHandleInfoData, BufferSize, &ulSize); | 
|  |  | 
|  | if (status == 0xC0000004 /*STATUS_INFO_LENGTH_MISMATCH*/) { | 
|  | free(SysHandleInfoData); | 
|  | } | 
|  |  | 
|  | } while (status == 0xC0000004 /*STATUS_INFO_LENGTH_MISMATCH*/); | 
|  |  | 
|  | /* 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)malloc(BufferSize); | 
|  |  | 
|  | status = NtQuerySystemInformation(SystemProcessInformation, pBuffer, BufferSize, &ulSize); | 
|  |  | 
|  | if (status == 0xC0000004 /*STATUS_INFO_LENGTH_MISMATCH*/) { | 
|  | free(pBuffer); | 
|  | } | 
|  |  | 
|  | } while (status == 0xC0000004 /*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_CACHE_INFORMATION)); | 
|  |  | 
|  | /* | 
|  | * Save system processor time info | 
|  | */ | 
|  | free(SystemProcessorTimeInfo); | 
|  | SystemProcessorTimeInfo = SysProcessorTimeInfo; | 
|  |  | 
|  | /* | 
|  | * Save system handle info | 
|  | */ | 
|  | memcpy(&SystemHandleInfo, SysHandleInfoData, sizeof(SYSTEM_HANDLE_INFORMATION)); | 
|  | free(SysHandleInfoData); | 
|  |  | 
|  | for (CurrentKernelTime=0, Idx=0; Idx<SystemBasicInfo.bKeNumberProcessors; 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.liIdleTime) - Li2Double(liOldIdleTime); | 
|  | dbKernelTime = CurrentKernelTime - OldKernelTime; | 
|  | dbSystemTime = Li2Double(SysTimeInfo.liKeSystemTime) - Li2Double(liOldSystemTime); | 
|  |  | 
|  | /*  CurrentCpuIdle = IdleTime / SystemTime */ | 
|  | dbIdleTime = dbIdleTime / dbSystemTime; | 
|  | dbKernelTime = dbKernelTime / dbSystemTime; | 
|  |  | 
|  | /*  CurrentCpuUsage% = 100 - (CurrentCpuIdle * 100) / NumberOfProcessors */ | 
|  | dbIdleTime = 100.0 - dbIdleTime * 100.0 / (double)SystemBasicInfo.bKeNumberProcessors; /* + 0.5; */ | 
|  | dbKernelTime = 100.0 - dbKernelTime * 100.0 / (double)SystemBasicInfo.bKeNumberProcessors; /* + 0.5; */ | 
|  | } | 
|  |  | 
|  | /* Store new CPU's idle and system time */ | 
|  | liOldIdleTime = SysPerfInfo.liIdleTime; | 
|  | liOldSystemTime = SysTimeInfo.liKeSystemTime; | 
|  | 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->RelativeOffset == 0) | 
|  | break; | 
|  | pSPI = (PSYSTEM_PROCESS_INFORMATION)((LPBYTE)pSPI + pSPI->RelativeOffset); | 
|  | } | 
|  |  | 
|  | /* Now alloc a new PERFDATA array and fill in the data */ | 
|  | free(pPerfDataOld); | 
|  | pPerfDataOld = pPerfData; | 
|  | pPerfData = (PPERFDATA)malloc(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; | 
|  | for (Idx2=0; Idx2<ProcessCountOld; Idx2++) { | 
|  | if (pPerfDataOld[Idx2].ProcessId == pSPI->ProcessId) { | 
|  | pPDOld = &pPerfDataOld[Idx2]; | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Clear out process perf data structure */ | 
|  | memset(&pPerfData[Idx], 0, sizeof(PERFDATA)); | 
|  |  | 
|  | if (pSPI->Name.Buffer) | 
|  | lstrcpyW(pPerfData[Idx].ImageName, pSPI->Name.Buffer); | 
|  | else | 
|  | { | 
|  | static const WCHAR idleW[] = {'S','y','s','t','e','m',' ','I','d','l','e',' ','P','r','o','c','e','s','s',0}; | 
|  | lstrcpyW(pPerfData[Idx].ImageName, idleW ); | 
|  | } | 
|  |  | 
|  | pPerfData[Idx].ProcessId = pSPI->ProcessId; | 
|  |  | 
|  | 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.bKeNumberProcessors; /* + 0.5; */ | 
|  | pPerfData[Idx].CPUUsage = (ULONG)CpuTime; | 
|  | } | 
|  | pPerfData[Idx].CPUTime.QuadPart = pSPI->UserTime.QuadPart + pSPI->KernelTime.QuadPart; | 
|  | pPerfData[Idx].WorkingSetSizeBytes = pSPI->TotalWorkingSetSizeBytes; | 
|  | pPerfData[Idx].PeakWorkingSetSizeBytes = pSPI->PeakWorkingSetSizeBytes; | 
|  | if (pPDOld) | 
|  | pPerfData[Idx].WorkingSetSizeDelta = labs((LONG)pSPI->TotalWorkingSetSizeBytes - (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->TotalVirtualSizeBytes; | 
|  | pPerfData[Idx].PagedPoolUsagePages = pSPI->TotalPagedPoolUsagePages; | 
|  | pPerfData[Idx].NonPagedPoolUsagePages = pSPI->TotalNonPagedPoolUsagePages; | 
|  | pPerfData[Idx].BasePriority = pSPI->BasePriority; | 
|  | pPerfData[Idx].HandleCount = pSPI->HandleCount; | 
|  | pPerfData[Idx].ThreadCount = pSPI->ThreadCount; | 
|  | pPerfData[Idx].SessionId = pSPI->SessionId; | 
|  |  | 
|  | hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pSPI->ProcessId); | 
|  | if (hProcess) { | 
|  | if (OpenProcessToken(hProcess, TOKEN_QUERY|TOKEN_DUPLICATE|TOKEN_IMPERSONATE, &hProcessToken)) { | 
|  | ImpersonateLoggedOnUser(hProcessToken); | 
|  | memset(szTemp, 0, sizeof(TCHAR[MAX_PATH])); | 
|  | dwSize = MAX_PATH; | 
|  | GetUserName(szTemp, &dwSize); | 
|  | #ifndef UNICODE | 
|  | MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szTemp, -1, pPerfData[Idx].UserName, MAX_PATH); | 
|  | /* | 
|  | int MultiByteToWideChar( | 
|  | UINT CodePage,         // code page | 
|  | DWORD dwFlags,         //  character-type options | 
|  | LPCSTR lpMultiByteStr, //  string to map | 
|  | int cbMultiByte,       //  number of bytes in string | 
|  | LPWSTR lpWideCharStr,  //  wide-character buffer | 
|  | int cchWideChar        //  size of buffer | 
|  | ); | 
|  | */ | 
|  | #endif | 
|  | RevertToSelf(); | 
|  | CloseHandle(hProcessToken); | 
|  | } | 
|  | if (pGetGuiResources) { | 
|  | pPerfData[Idx].USERObjectCount = pGetGuiResources(hProcess, GR_USEROBJECTS); | 
|  | pPerfData[Idx].GDIObjectCount = pGetGuiResources(hProcess, GR_GDIOBJECTS); | 
|  | } | 
|  | if (pGetProcessIoCounters) | 
|  | pGetProcessIoCounters(hProcess, &pPerfData[Idx].IOCounters); | 
|  | CloseHandle(hProcess); | 
|  | } | 
|  | pPerfData[Idx].UserTime.QuadPart = pSPI->UserTime.QuadPart; | 
|  | pPerfData[Idx].KernelTime.QuadPart = pSPI->KernelTime.QuadPart; | 
|  | pSPI = (PSYSTEM_PROCESS_INFORMATION)((LPBYTE)pSPI + pSPI->RelativeOffset); | 
|  | } | 
|  | free(pBuffer); | 
|  | LeaveCriticalSection(&PerfDataCriticalSection); | 
|  | } | 
|  |  | 
|  | ULONG PerfDataGetProcessCount(void) | 
|  | { | 
|  | return ProcessCount; | 
|  | } | 
|  |  | 
|  | ULONG PerfDataGetProcessorUsage(void) | 
|  | { | 
|  | return (ULONG)dbIdleTime; | 
|  | } | 
|  |  | 
|  | ULONG PerfDataGetProcessorSystemUsage(void) | 
|  | { | 
|  | return (ULONG)dbKernelTime; | 
|  | } | 
|  |  | 
|  | BOOL PerfDataGetImageName(ULONG Index, LPTSTR lpImageName, int nMaxCount) | 
|  | { | 
|  | BOOL    bSuccessful; | 
|  |  | 
|  | EnterCriticalSection(&PerfDataCriticalSection); | 
|  |  | 
|  | if (Index < ProcessCount) { | 
|  | #ifdef _UNICODE | 
|  | wcsncpy(lpImageName, pPerfData[Index].ImageName, nMaxCount); | 
|  | #else | 
|  | WideCharToMultiByte(CP_ACP, 0, pPerfData[Index].ImageName, -1, lpImageName, nMaxCount, NULL, NULL); | 
|  | #endif | 
|  |  | 
|  | bSuccessful = TRUE; | 
|  | } else { | 
|  | bSuccessful = FALSE; | 
|  | } | 
|  | LeaveCriticalSection(&PerfDataCriticalSection); | 
|  | return bSuccessful; | 
|  | } | 
|  |  | 
|  | ULONG PerfDataGetProcessId(ULONG Index) | 
|  | { | 
|  | ULONG    ProcessId; | 
|  |  | 
|  | EnterCriticalSection(&PerfDataCriticalSection); | 
|  |  | 
|  | if (Index < ProcessCount) | 
|  | ProcessId = pPerfData[Index].ProcessId; | 
|  | else | 
|  | ProcessId = 0; | 
|  |  | 
|  | LeaveCriticalSection(&PerfDataCriticalSection); | 
|  |  | 
|  | return ProcessId; | 
|  | } | 
|  |  | 
|  | BOOL PerfDataGetUserName(ULONG Index, LPTSTR lpUserName, int nMaxCount) | 
|  | { | 
|  | BOOL    bSuccessful; | 
|  |  | 
|  | EnterCriticalSection(&PerfDataCriticalSection); | 
|  |  | 
|  | if (Index < ProcessCount) { | 
|  | #ifdef _UNICODE | 
|  | wcsncpy(lpUserName, pPerfData[Index].UserName, nMaxCount); | 
|  | #else | 
|  | WideCharToMultiByte(CP_ACP, 0, pPerfData[Index].UserName, -1, lpUserName, nMaxCount, NULL, NULL); | 
|  | #endif | 
|  |  | 
|  | bSuccessful = TRUE; | 
|  | } else { | 
|  | bSuccessful = FALSE; | 
|  | } | 
|  |  | 
|  | LeaveCriticalSection(&PerfDataCriticalSection); | 
|  |  | 
|  | return bSuccessful; | 
|  | } | 
|  |  | 
|  | 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; | 
|  | } | 
|  |  | 
|  | TIME PerfDataGetCPUTime(ULONG Index) | 
|  | { | 
|  | TIME    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    PagedPoolUsagePages; | 
|  |  | 
|  | EnterCriticalSection(&PerfDataCriticalSection); | 
|  |  | 
|  | if (Index < ProcessCount) | 
|  | PagedPoolUsagePages = pPerfData[Index].PagedPoolUsagePages; | 
|  | else | 
|  | PagedPoolUsagePages = 0; | 
|  |  | 
|  | LeaveCriticalSection(&PerfDataCriticalSection); | 
|  |  | 
|  | return PagedPoolUsagePages; | 
|  | } | 
|  |  | 
|  | ULONG PerfDataGetNonPagedPoolUsagePages(ULONG Index) | 
|  | { | 
|  | ULONG    NonPagedPoolUsagePages; | 
|  |  | 
|  | EnterCriticalSection(&PerfDataCriticalSection); | 
|  |  | 
|  | if (Index < ProcessCount) | 
|  | NonPagedPoolUsagePages = pPerfData[Index].NonPagedPoolUsagePages; | 
|  | else | 
|  | NonPagedPoolUsagePages = 0; | 
|  |  | 
|  | LeaveCriticalSection(&PerfDataCriticalSection); | 
|  |  | 
|  | return NonPagedPoolUsagePages; | 
|  | } | 
|  |  | 
|  | 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.MmTotalCommittedPages; | 
|  | PageSize = SystemBasicInfo.uPageSize; | 
|  |  | 
|  | LeaveCriticalSection(&PerfDataCriticalSection); | 
|  |  | 
|  | Total = Total * (PageSize / 1024); | 
|  |  | 
|  | return Total; | 
|  | } | 
|  |  | 
|  | ULONG PerfDataGetCommitChargeLimitK(void) | 
|  | { | 
|  | ULONG    Limit; | 
|  | ULONG    PageSize; | 
|  |  | 
|  | EnterCriticalSection(&PerfDataCriticalSection); | 
|  |  | 
|  | Limit = SystemPerfInfo.MmTotalCommitLimit; | 
|  | PageSize = SystemBasicInfo.uPageSize; | 
|  |  | 
|  | LeaveCriticalSection(&PerfDataCriticalSection); | 
|  |  | 
|  | Limit = Limit * (PageSize / 1024); | 
|  |  | 
|  | return Limit; | 
|  | } | 
|  |  | 
|  | ULONG PerfDataGetCommitChargePeakK(void) | 
|  | { | 
|  | ULONG    Peak; | 
|  | ULONG    PageSize; | 
|  |  | 
|  | EnterCriticalSection(&PerfDataCriticalSection); | 
|  |  | 
|  | Peak = SystemPerfInfo.MmPeakLimit; | 
|  | PageSize = SystemBasicInfo.uPageSize; | 
|  |  | 
|  | LeaveCriticalSection(&PerfDataCriticalSection); | 
|  |  | 
|  | Peak = Peak * (PageSize / 1024); | 
|  |  | 
|  | return Peak; | 
|  | } | 
|  |  | 
|  | ULONG PerfDataGetKernelMemoryTotalK(void) | 
|  | { | 
|  | ULONG    Total; | 
|  | ULONG    Paged; | 
|  | ULONG    NonPaged; | 
|  | ULONG    PageSize; | 
|  |  | 
|  | EnterCriticalSection(&PerfDataCriticalSection); | 
|  |  | 
|  | Paged = SystemPerfInfo.PoolPagedBytes; | 
|  | NonPaged = SystemPerfInfo.PoolNonPagedBytes; | 
|  | PageSize = SystemBasicInfo.uPageSize; | 
|  |  | 
|  | 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.PoolPagedBytes; | 
|  | PageSize = SystemBasicInfo.uPageSize; | 
|  |  | 
|  | LeaveCriticalSection(&PerfDataCriticalSection); | 
|  |  | 
|  | Paged = Paged * (PageSize / 1024); | 
|  |  | 
|  | return Paged; | 
|  | } | 
|  |  | 
|  | ULONG PerfDataGetKernelMemoryNonPagedK(void) | 
|  | { | 
|  | ULONG    NonPaged; | 
|  | ULONG    PageSize; | 
|  |  | 
|  | EnterCriticalSection(&PerfDataCriticalSection); | 
|  |  | 
|  | NonPaged = SystemPerfInfo.PoolNonPagedBytes; | 
|  | PageSize = SystemBasicInfo.uPageSize; | 
|  |  | 
|  | LeaveCriticalSection(&PerfDataCriticalSection); | 
|  |  | 
|  | NonPaged = NonPaged * (PageSize / 1024); | 
|  |  | 
|  | return NonPaged; | 
|  | } | 
|  |  | 
|  | ULONG PerfDataGetPhysicalMemoryTotalK(void) | 
|  | { | 
|  | ULONG    Total; | 
|  | ULONG    PageSize; | 
|  |  | 
|  | EnterCriticalSection(&PerfDataCriticalSection); | 
|  |  | 
|  | Total = SystemBasicInfo.uMmNumberOfPhysicalPages; | 
|  | PageSize = SystemBasicInfo.uPageSize; | 
|  |  | 
|  | LeaveCriticalSection(&PerfDataCriticalSection); | 
|  |  | 
|  | Total = Total * (PageSize / 1024); | 
|  |  | 
|  | return Total; | 
|  | } | 
|  |  | 
|  | ULONG PerfDataGetPhysicalMemoryAvailableK(void) | 
|  | { | 
|  | ULONG    Available; | 
|  | ULONG    PageSize; | 
|  |  | 
|  | EnterCriticalSection(&PerfDataCriticalSection); | 
|  |  | 
|  | Available = SystemPerfInfo.MmAvailablePages; | 
|  | PageSize = SystemBasicInfo.uPageSize; | 
|  |  | 
|  | LeaveCriticalSection(&PerfDataCriticalSection); | 
|  |  | 
|  | Available = Available * (PageSize / 1024); | 
|  |  | 
|  | return Available; | 
|  | } | 
|  |  | 
|  | ULONG PerfDataGetPhysicalMemorySystemCacheK(void) | 
|  | { | 
|  | ULONG    SystemCache; | 
|  | ULONG    PageSize; | 
|  |  | 
|  | EnterCriticalSection(&PerfDataCriticalSection); | 
|  |  | 
|  | SystemCache = SystemCacheInfo.CurrentSize; | 
|  | PageSize = SystemBasicInfo.uPageSize; | 
|  |  | 
|  | LeaveCriticalSection(&PerfDataCriticalSection); | 
|  |  | 
|  | /* SystemCache = SystemCache * (PageSize / 1024); */ | 
|  | SystemCache = SystemCache / 1024; | 
|  |  | 
|  | return SystemCache; | 
|  | } | 
|  |  | 
|  | ULONG PerfDataGetSystemHandleCount(void) | 
|  | { | 
|  | ULONG    HandleCount; | 
|  |  | 
|  | EnterCriticalSection(&PerfDataCriticalSection); | 
|  |  | 
|  | HandleCount = SystemHandleInfo.Count; | 
|  |  | 
|  | 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; | 
|  | } |