📄 psapi.c
字号:
STDCALL
InitializeProcessForWsWatch(HANDLE hProcess)
{
NTSTATUS Status;
Status = NtSetInformationProcess(hProcess,
ProcessWorkingSetWatch,
NULL,
0);
if(!NT_SUCCESS(Status))
{
SetLastErrorByStatus(Status);
return FALSE;
}
return TRUE;
}
/*
* @implemented
*/
BOOL
STDCALL
GetWsChanges(HANDLE hProcess,
PPSAPI_WS_WATCH_INFORMATION lpWatchInfo,
DWORD cb)
{
NTSTATUS Status;
Status = NtQueryInformationProcess(hProcess,
ProcessWorkingSetWatch,
(PVOID)lpWatchInfo,
cb,
NULL);
if(!NT_SUCCESS(Status))
{
SetLastErrorByStatus(Status);
return FALSE;
}
return TRUE;
}
/*
* @implemented
*/
DWORD
STDCALL
GetProcessImageFileNameW(HANDLE hProcess,
LPWSTR lpImageFileName,
DWORD nSize)
{
PUNICODE_STRING ImageFileName;
SIZE_T BufferSize;
NTSTATUS Status;
DWORD Ret = 0;
BufferSize = sizeof(UNICODE_STRING) + (nSize * sizeof(WCHAR));
ImageFileName = (PUNICODE_STRING)LocalAlloc(LMEM_FIXED, BufferSize);
if(ImageFileName != NULL)
{
Status = NtQueryInformationProcess(hProcess,
ProcessImageFileName,
ImageFileName,
BufferSize,
NULL);
if(NT_SUCCESS(Status))
{
memcpy(lpImageFileName, ImageFileName->Buffer, ImageFileName->Length);
/* make sure the string is null-terminated! */
lpImageFileName[ImageFileName->Length / sizeof(WCHAR)] = L'\0';
Ret = ImageFileName->Length / sizeof(WCHAR);
}
else if(Status == STATUS_INFO_LENGTH_MISMATCH)
{
/* XP sets this error code for some reason if the buffer is too small */
SetLastError(ERROR_INSUFFICIENT_BUFFER);
}
else
{
SetLastErrorByStatus(Status);
}
LocalFree((HLOCAL)ImageFileName);
}
return Ret;
}
/*
* @implemented
*/
DWORD
STDCALL
GetProcessImageFileNameA(HANDLE hProcess,
LPSTR lpImageFileName,
DWORD nSize)
{
PUNICODE_STRING ImageFileName;
SIZE_T BufferSize;
NTSTATUS Status;
DWORD Ret = 0;
BufferSize = sizeof(UNICODE_STRING) + (nSize * sizeof(WCHAR));
ImageFileName = (PUNICODE_STRING)LocalAlloc(LMEM_FIXED, BufferSize);
if(ImageFileName != NULL)
{
Status = NtQueryInformationProcess(hProcess,
ProcessImageFileName,
ImageFileName,
BufferSize,
NULL);
if(NT_SUCCESS(Status))
{
WideCharToMultiByte(CP_ACP,
0,
ImageFileName->Buffer,
ImageFileName->Length / sizeof(WCHAR),
lpImageFileName,
nSize,
NULL,
NULL);
/* make sure the string is null-terminated! */
lpImageFileName[ImageFileName->Length / sizeof(WCHAR)] = '\0';
Ret = ImageFileName->Length / sizeof(WCHAR);
}
else if(Status == STATUS_INFO_LENGTH_MISMATCH)
{
/* XP sets this error code for some reason if the buffer is too small */
SetLastError(ERROR_INSUFFICIENT_BUFFER);
}
else
{
SetLastErrorByStatus(Status);
}
LocalFree((HLOCAL)ImageFileName);
}
return Ret;
}
/*
* @implemented
*/
BOOL
STDCALL
EnumPageFilesA(PENUM_PAGE_FILE_CALLBACKA pCallbackRoutine,
LPVOID lpContext)
{
INTERNAL_ENUM_PAGE_FILES_CONTEXT Context;
Context.pCallbackRoutine = pCallbackRoutine;
Context.lpContext = lpContext;
return EnumPageFilesW(InternalAnsiPageFileCallback, &Context);
}
/*
* @implemented
*/
BOOL
STDCALL
EnumPageFilesW(PENUM_PAGE_FILE_CALLBACKW pCallbackRoutine,
LPVOID lpContext)
{
NTSTATUS Status;
PVOID Buffer;
ULONG BufferSize = 0;
BOOL Ret = FALSE;
for(;;)
{
BufferSize += 0x1000;
Buffer = LocalAlloc(LMEM_FIXED, BufferSize);
if(Buffer == NULL)
{
return FALSE;
}
Status = NtQuerySystemInformation(SystemPageFileInformation,
Buffer,
BufferSize,
NULL);
if(Status == STATUS_INFO_LENGTH_MISMATCH)
{
LocalFree((HLOCAL)Buffer);
}
else
{
break;
}
}
if(NT_SUCCESS(Status))
{
ENUM_PAGE_FILE_INFORMATION Information;
PSYSTEM_PAGEFILE_INFORMATION pfi = (PSYSTEM_PAGEFILE_INFORMATION)Buffer;
ULONG Offset = 0;
do
{
PWCHAR Colon;
pfi = (PSYSTEM_PAGEFILE_INFORMATION)((ULONG_PTR)pfi + Offset);
Information.cb = sizeof(Information);
Information.Reserved = 0;
Information.TotalSize = pfi->TotalSize;
Information.TotalInUse = pfi->TotalInUse;
Information.PeakUsage = pfi->PeakUsage;
/* strip the \??\ prefix from the file name. We do this by searching for the first
: character and then just change Buffer to point to the previous character. */
Colon = wcschr(pfi->PageFileName.Buffer, L':');
if(Colon != NULL)
{
pfi->PageFileName.Buffer = --Colon;
}
/* FIXME - looks like the PageFileName string is always NULL-terminated on win.
At least I haven't encountered a different case so far, we should
propably manually NULL-terminate the string here... */
if(!pCallbackRoutine(lpContext, &Information, pfi->PageFileName.Buffer))
{
break;
}
Offset = pfi->NextEntryOffset;
} while(Offset != 0);
Ret = TRUE;
}
else
{
SetLastErrorByStatus(Status);
}
LocalFree((HLOCAL)Buffer);
return Ret;
}
/*
* @implemented
*/
BOOL
STDCALL
GetPerformanceInfo(PPERFORMANCE_INFORMATION pPerformanceInformation,
DWORD cb)
{
SYSTEM_PERFORMANCE_INFORMATION spi;
SYSTEM_BASIC_INFORMATION sbi;
SYSTEM_HANDLE_INFORMATION shi;
PSYSTEM_PROCESS_INFORMATION ProcessInfo;
ULONG BufferSize, ProcOffset, ProcessCount, ThreadCount;
PVOID Buffer;
NTSTATUS Status;
Status = NtQuerySystemInformation(SystemPerformanceInformation,
&spi,
sizeof(spi),
NULL);
if(!NT_SUCCESS(Status))
{
SetLastErrorByStatus(Status);
return FALSE;
}
Status = NtQuerySystemInformation(SystemBasicInformation,
&sbi,
sizeof(sbi),
NULL);
if(!NT_SUCCESS(Status))
{
SetLastErrorByStatus(Status);
return FALSE;
}
/*
* allocate enough memory to get a dump of all processes and threads
*/
BufferSize = 0;
for(;;)
{
BufferSize += 0x10000;
Buffer = (PVOID)LocalAlloc(LMEM_FIXED, BufferSize);
if(Buffer == NULL)
{
return FALSE;
}
Status = NtQuerySystemInformation(SystemProcessInformation,
Buffer,
BufferSize,
NULL);
if(Status == STATUS_INFO_LENGTH_MISMATCH)
{
LocalFree((HLOCAL)Buffer);
}
else
{
break;
}
}
if(!NT_SUCCESS(Status))
{
LocalFree((HLOCAL)Buffer);
SetLastErrorByStatus(Status);
return FALSE;
}
/*
* determine the process and thread count
*/
ProcessCount = ThreadCount = ProcOffset = 0;
ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)Buffer;
do
{
ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)((ULONG_PTR)ProcessInfo + ProcOffset);
ProcessCount++;
ThreadCount += ProcessInfo->NumberOfThreads;
ProcOffset = ProcessInfo->NextEntryOffset;
} while(ProcOffset != 0);
LocalFree((HLOCAL)Buffer);
/*
* it's enough to supply a SYSTEM_HANDLE_INFORMATION structure as buffer. Even
* though it returns STATUS_INFO_LENGTH_MISMATCH, it already sets the NumberOfHandles
* field which is all we're looking for anyway.
*/
Status = NtQuerySystemInformation(SystemHandleInformation,
&shi,
sizeof(shi),
NULL);
if(!NT_SUCCESS(Status) && (Status != STATUS_INFO_LENGTH_MISMATCH))
{
SetLastErrorByStatus(Status);
return FALSE;
}
/*
* all required information collected, fill the structure
*/
pPerformanceInformation->cb = sizeof(PERFORMANCE_INFORMATION);
pPerformanceInformation->CommitTotal = spi.CommittedPages;
pPerformanceInformation->CommitLimit = spi.CommitLimit;
pPerformanceInformation->CommitPeak = spi.PeakCommitment;
pPerformanceInformation->PhysicalTotal = sbi.NumberOfPhysicalPages;
pPerformanceInformation->PhysicalAvailable = spi.AvailablePages;
pPerformanceInformation->SystemCache = 0; /* FIXME - where to get this information from? */
pPerformanceInformation->KernelTotal = spi.PagedPoolPages + spi.NonPagedPoolPages;
pPerformanceInformation->KernelPaged = spi.PagedPoolPages;
pPerformanceInformation->KernelNonpaged = spi.NonPagedPoolPages;
pPerformanceInformation->PageSize = sbi.PageSize;
pPerformanceInformation->HandleCount = shi.NumberOfHandles;
pPerformanceInformation->ProcessCount = ProcessCount;
pPerformanceInformation->ThreadCount = ThreadCount;
return TRUE;
}
/*
* @implemented
*/
BOOL
STDCALL
GetProcessMemoryInfo(HANDLE Process,
PPROCESS_MEMORY_COUNTERS ppsmemCounters,
DWORD cb)
{
NTSTATUS Status;
VM_COUNTERS vmc;
BOOL Ret = FALSE;
/* XP's implementation secures access to ppsmemCounters in SEH, we should behave
similar so we can return the proper error codes when bad pointers are passed
to this function! */
_SEH_TRY
{
if(cb < sizeof(PROCESS_MEMORY_COUNTERS))
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
_SEH_LEAVE;
}
/* ppsmemCounters->cb isn't checked at all! */
Status = NtQueryInformationProcess(Process,
ProcessVmCounters,
&vmc,
sizeof(vmc),
NULL);
if(!NT_SUCCESS(Status))
{
SetLastErrorByStatus(Status);
_SEH_LEAVE;
}
/* fill the structure with the collected information, in case of bad pointers
SEH will catch the exception and set the appropriate error code */
ppsmemCounters->cb = sizeof(PROCESS_MEMORY_COUNTERS);
ppsmemCounters->PageFaultCount = vmc.PageFaultCount;
ppsmemCounters->PeakWorkingSetSize = vmc.PeakWorkingSetSize;
ppsmemCounters->WorkingSetSize = vmc.WorkingSetSize;
ppsmemCounters->QuotaPeakPagedPoolUsage = vmc.QuotaPeakPagedPoolUsage;
ppsmemCounters->QuotaPagedPoolUsage = vmc.QuotaPagedPoolUsage;
ppsmemCounters->QuotaPeakNonPagedPoolUsage = vmc.QuotaPeakNonPagedPoolUsage;
ppsmemCounters->QuotaNonPagedPoolUsage = vmc.QuotaNonPagedPoolUsage;
ppsmemCounters->PagefileUsage = vmc.PagefileUsage;
ppsmemCounters->PeakPagefileUsage = vmc.PeakPagefileUsage;
Ret = TRUE;
}
_SEH_HANDLE
{
SetLastErrorByStatus(_SEH_GetExceptionCode());
}
_SEH_END;
return Ret;
}
/*
* @implemented
*/
BOOL
STDCALL
QueryWorkingSet(HANDLE hProcess,
PVOID pv,
DWORD cb)
{
NTSTATUS Status;
Status = NtQueryVirtualMemory(hProcess,
NULL,
MemoryWorkingSetList,
pv,
cb,
NULL);
if(!NT_SUCCESS(Status))
{
SetLastErrorByStatus(Status);
return FALSE;
}
return TRUE;
}
/* EOF */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -