/*++ Copyright (c) 2000 Microsoft Corporation Module Name: psenum.c Abstract: This module returns various performance values Author: Neill clift (NeillC) 23-Jul-2000 Revision History: --*/ #include #include #include #include #include "psapi.h" BOOL WINAPI GetPerformanceInfo ( PPERFORMANCE_INFORMATION pPerformanceInformation, DWORD cb ) /*++ Routine Description: The routine gets some performance values. Arguments: pPerformanceInformation - A block out performance values that are returned. Return Value: BOOL - Returns TRUE is the function was successfull FALSE otherwise --*/ { NTSTATUS Status; SYSTEM_BASIC_INFORMATION BasicInfo; SYSTEM_PERFORMANCE_INFORMATION PerfInfo; SYSTEM_FILECACHE_INFORMATION FileCache; PSYSTEM_PROCESS_INFORMATION ProcInfo, tProcInfo; ULONG BufferLength, RetLen; ULONG Processes; ULONG Threads; ULONG Handles; if (cb < sizeof (PERFORMANCE_INFORMATION)) { SetLastError (RtlNtStatusToDosError (STATUS_INFO_LENGTH_MISMATCH)); return FALSE; } Status = NtQuerySystemInformation (SystemBasicInformation, &BasicInfo, sizeof(BasicInfo), NULL); if (!NT_SUCCESS (Status)) { SetLastError (RtlNtStatusToDosError (Status)); return FALSE; } Status = NtQuerySystemInformation (SystemPerformanceInformation, &PerfInfo, sizeof(PerfInfo), NULL); if (!NT_SUCCESS (Status)) { SetLastError (RtlNtStatusToDosError (Status)); return FALSE; } Status = NtQuerySystemInformation (SystemFileCacheInformation, &FileCache, sizeof(FileCache), NULL); if (!NT_SUCCESS (Status)) { SetLastError (RtlNtStatusToDosError (Status)); return FALSE; } BufferLength = 4096; while (1) { ProcInfo = LocalAlloc (LMEM_FIXED, BufferLength); if (ProcInfo == NULL) { SetLastError (RtlNtStatusToDosError (STATUS_INSUFFICIENT_RESOURCES)); return FALSE; } Status = NtQuerySystemInformation (SystemProcessInformation, ProcInfo, BufferLength, &RetLen); if (NT_SUCCESS (Status)) { break; } LocalFree (ProcInfo); if (Status == STATUS_INFO_LENGTH_MISMATCH) { if (RetLen > BufferLength) { BufferLength = RetLen; } else { BufferLength += 4096; } } else { SetLastError (RtlNtStatusToDosError (Status)); return FALSE; } } Processes = 0; Threads = 0; Handles = 0; tProcInfo = ProcInfo; while (RetLen > sizeof (SYSTEM_PROCESS_INFORMATION)) { Processes += 1; Threads += tProcInfo->NumberOfThreads; Handles += tProcInfo->HandleCount; if (tProcInfo->NextEntryOffset == 0 || tProcInfo->NextEntryOffset > RetLen) { break; } RetLen -= tProcInfo->NextEntryOffset; tProcInfo = (PSYSTEM_PROCESS_INFORMATION) ((PUCHAR) tProcInfo + tProcInfo->NextEntryOffset); } LocalFree (ProcInfo); pPerformanceInformation->cb = sizeof (PERFORMANCE_INFORMATION); pPerformanceInformation->CommitTotal = PerfInfo.CommittedPages; pPerformanceInformation->CommitLimit = PerfInfo.CommitLimit; pPerformanceInformation->CommitPeak = PerfInfo.PeakCommitment; pPerformanceInformation->PhysicalTotal = BasicInfo.NumberOfPhysicalPages; pPerformanceInformation->PhysicalAvailable = PerfInfo.AvailablePages; pPerformanceInformation->SystemCache = FileCache.CurrentSizeIncludingTransitionInPages; pPerformanceInformation->KernelTotal = PerfInfo.PagedPoolPages + PerfInfo.NonPagedPoolPages; pPerformanceInformation->KernelPaged = PerfInfo.PagedPoolPages; pPerformanceInformation->KernelNonpaged = PerfInfo.NonPagedPoolPages; pPerformanceInformation->PageSize = BasicInfo.PageSize; pPerformanceInformation->HandleCount = Handles; pPerformanceInformation->ProcessCount = Processes; pPerformanceInformation->ThreadCount = Threads; return TRUE; } BOOL WINAPI EnumPageFilesW ( PENUM_PAGE_FILE_CALLBACKW pCallBackRoutine, LPVOID pContext ) /*++ Routine Description: The routine calls the callback routine for each installed page file in the system Arguments: pCallBackRoutine - Routine called for each pagefile pContext - Context value provided by the user and passed to the call back routine. Return Value: BOOL - Returns TRUE is the function was successfull FALSE otherwise --*/ { NTSTATUS Status; ULONG BufferLength, RetLen; PSYSTEM_PAGEFILE_INFORMATION PageFileInfo, tPageFileInfo; BufferLength = 4096; while (1) { PageFileInfo = LocalAlloc (LMEM_FIXED, BufferLength); if (PageFileInfo == NULL) { SetLastError (RtlNtStatusToDosError (STATUS_INSUFFICIENT_RESOURCES)); return FALSE; } Status = NtQuerySystemInformation (SystemPageFileInformation, PageFileInfo, BufferLength, &RetLen); if (NT_SUCCESS (Status)) { break; } LocalFree (PageFileInfo); if (Status == STATUS_INFO_LENGTH_MISMATCH) { if (RetLen > BufferLength) { BufferLength = RetLen; } else { BufferLength += 4096; } } else { SetLastError (RtlNtStatusToDosError (Status)); return FALSE; } } tPageFileInfo = PageFileInfo; while (RetLen > sizeof (SYSTEM_PAGEFILE_INFORMATION)) { ENUM_PAGE_FILE_INFORMATION pfi; PWCHAR pWc; pfi.cb = sizeof (ENUM_PAGE_FILE_INFORMATION); pfi.Reserved = 0; pfi.TotalSize = tPageFileInfo->TotalSize; pfi.TotalInUse = tPageFileInfo->TotalInUse; pfi.PeakUsage = tPageFileInfo->PeakUsage; pWc = wcschr (tPageFileInfo->PageFileName.Buffer, L':'); if (pWc != NULL && pWc > tPageFileInfo->PageFileName.Buffer) { pWc--; pCallBackRoutine (pContext, &pfi, pWc); } if (tPageFileInfo->NextEntryOffset == 0 || tPageFileInfo->NextEntryOffset > RetLen) { break; } RetLen -= tPageFileInfo->NextEntryOffset; tPageFileInfo = (PSYSTEM_PAGEFILE_INFORMATION) ((PUCHAR) tPageFileInfo + tPageFileInfo->NextEntryOffset); } LocalFree (PageFileInfo); return TRUE; } typedef struct _ENUM_PAGE_FILE_CONV_CTX { LPVOID Ctx; PENUM_PAGE_FILE_CALLBACKA CallBack; DWORD LastError; } ENUM_PAGE_FILE_CONV_CTX, *PENUM_PAGE_FILE_CONV_CTX; BOOL CallBackConvertToAscii ( LPVOID pContext, PENUM_PAGE_FILE_INFORMATION pPageFileInfo, LPCWSTR lpFilename ) { DWORD Len; LPSTR AsciiStr; PENUM_PAGE_FILE_CONV_CTX Ctx = pContext; BOOL RetVal; Len = wcslen (lpFilename) + 1; AsciiStr = LocalAlloc (LMEM_FIXED, Len); if (AsciiStr == NULL) { Ctx->LastError = RtlNtStatusToDosError (STATUS_INSUFFICIENT_RESOURCES); return FALSE; } if (WideCharToMultiByte (CP_ACP, 0, lpFilename, -1, AsciiStr, Len, NULL, NULL)) { RetVal = Ctx->CallBack (Ctx->Ctx, pPageFileInfo, AsciiStr); } else { Ctx->LastError = GetLastError (); RetVal = FALSE; } LocalFree (AsciiStr); return RetVal; } BOOL WINAPI EnumPageFilesA ( PENUM_PAGE_FILE_CALLBACKA pCallBackRoutine, LPVOID pContext ) /*++ Routine Description: The routine calls the callback routine for each installed page file in the system Arguments: pCallBackRoutine - Routine called for each pagefile pContext - Context value provided by the user and passed to the call back routine. Return Value: BOOL - Returns TRUE is the function was successfull FALSE otherwise --*/ { ENUM_PAGE_FILE_CONV_CTX Ctx; BOOL RetVal; Ctx.Ctx = pContext; Ctx.CallBack = pCallBackRoutine; Ctx.LastError = 0; RetVal = EnumPageFilesW (CallBackConvertToAscii, &Ctx); if (RetVal) { // // See if our conversion routine encountered an error. If it doid then return this to the caller // if (Ctx.LastError != 0) { RetVal = FALSE; SetLastError (Ctx.LastError); } } return RetVal; }