windows-nt/Source/XPSP1/NT/sdktools/psapi/perf.c
2020-09-26 16:20:57 +08:00

317 lines
8.9 KiB
C

/*++
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 <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include "psapi.h"
BOOL
WINAPI
GetPerformanceInfo (
PPERFORMACE_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 (PERFORMACE_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 (PERFORMACE_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;
}