233 lines
8.8 KiB
ObjectPascal
233 lines
8.8 KiB
ObjectPascal
{*******************************************************}
|
|
{ MiTeC Common Routines }
|
|
{ Windows Process Status Helper }
|
|
{ }
|
|
{ }
|
|
{ Copyright (c) 1997-2021 Michal Mutl }
|
|
{ }
|
|
{*******************************************************}
|
|
|
|
{$INCLUDE Compilers.inc}
|
|
|
|
unit MiTeC_PSAPI;
|
|
|
|
interface
|
|
|
|
uses {$IFDEF RAD9PLUS}
|
|
WinAPI.Windows, System.SysUtils, System.Classes, WinAPI.ShellAPI,
|
|
{$ELSE}
|
|
Windows, SysUtils, Classes, ShellAPI,
|
|
{$ENDIF}
|
|
MiTeC_Windows;
|
|
|
|
const
|
|
LIST_MODULES_DEFAULT = 0;
|
|
LIST_MODULES_32BIT = 1;
|
|
LIST_MODULES_64BIT = 2;
|
|
LIST_MODULES_ALL = 3;
|
|
|
|
type
|
|
PHInst = ^HInst;
|
|
TModuleInfo = record
|
|
lpBaseOfDll: pointer;
|
|
SizeOfImage: Integer;
|
|
EntryPoint: pointer;
|
|
end;
|
|
|
|
TPSAPIWsWatchInformation = record
|
|
FaultingPc: pointer;
|
|
FaultingVa: pointer;
|
|
end;
|
|
|
|
TProcessMemoryCounters = record
|
|
cb: Cardinal;
|
|
PageFaultCount: Cardinal;
|
|
PeakWorkingSetSize: SIZE_T;
|
|
WorkingSetSize: SIZE_T;
|
|
QuotaPeakPagedPoolUsage: SIZE_T;
|
|
QuotaPagedPoolUsage: SIZE_T;
|
|
QuotaPeakNonPagedPoolUsage: SIZE_T;
|
|
QuotaNonPagedPoolUsage: SIZE_T;
|
|
PagefileUsage: SIZE_T;
|
|
PeakPagefileUsage: SIZE_T;
|
|
end;
|
|
PProcessMemoryCounters = ^TProcessMemoryCounters;
|
|
|
|
TProcessMemoryCountersEx = record
|
|
cb: Cardinal;
|
|
PageFaultCount: Cardinal;
|
|
PeakWorkingSetSize: SIZE_T;
|
|
WorkingSetSize: SIZE_T;
|
|
QuotaPeakPagedPoolUsage: SIZE_T;
|
|
QuotaPagedPoolUsage: SIZE_T;
|
|
QuotaPeakNonPagedPoolUsage: SIZE_T;
|
|
QuotaNonPagedPoolUsage: SIZE_T;
|
|
PagefileUsage: SIZE_T;
|
|
PeakPagefileUsage: SIZE_T;
|
|
PrivateUsage: SIZE_T;
|
|
end;
|
|
PProcessMemoryCountersEx = ^TProcessMemoryCountersEx;
|
|
|
|
PSAPI_WORKING_SET_BLOCK = record
|
|
Flags: ULONG_PTR;
|
|
end;
|
|
|
|
PSAPI_WORKING_SET_INFORMATION = record
|
|
NumberOfEntries: ULONG_PTR;
|
|
WorkingSetInfo: array[0..0] of PSAPI_WORKING_SET_BLOCK;
|
|
end;
|
|
|
|
PSAPI_WORKING_SET_EX_BLOCK = record
|
|
Flags: ULONG_PTR;
|
|
end;
|
|
|
|
PSAPI_WORKING_SET_EX_INFORMATION = record
|
|
VirtualAddress: PVOID;
|
|
VirtualAttributes: PSAPI_WORKING_SET_EX_BLOCK;
|
|
end;
|
|
|
|
TaskEnumProcEx = function(threadID: Cardinal; hMod16: WORD; hTask16: WORD; modName: PChar; fileName: PChar; param: Cardinal): BOOL; stdcall;
|
|
|
|
function InitPSAPI: Boolean;
|
|
procedure FreePSAPI;
|
|
|
|
function InitVDM: Boolean;
|
|
procedure FreeVDM;
|
|
|
|
type
|
|
TVDMEnumTaskWOWEx = function (pid: Cardinal; callback: TaskEnumProcEx; param: Cardinal): Integer; stdcall;
|
|
|
|
TEnumProcesses = function (pidList: PInteger; cb: Integer; var cbNeeded: Cardinal): boolean; stdcall;
|
|
TEnumProcessModules = function (hProcess: THandle; moduleList: PHInst; cb: Integer; var cbNeeded: Cardinal): boolean; stdcall;
|
|
TEnumProcessModulesEx = function (hProcess: THandle; moduleList: PHInst; cb: Integer; var cbNeeded: Cardinal; dwFilterFlag: Cardinal): boolean; stdcall;
|
|
TGetModuleBaseName = function (hProcess: THandle; module: HInst; BaseName: PChar; size: Integer): Integer; stdcall;
|
|
TGetModuleFileNameEx = function (hProcess: THandle; module: HInst; FileName: PChar; size: Integer): Integer; stdcall;
|
|
TGetModuleInformation = function (hProcess: THandle; module: HInst; var info: TModuleInfo; size: Integer): boolean; stdcall;
|
|
TEmptyWorkingSet = function (hProcess: THandle): boolean; stdcall;
|
|
TQueryWorkingSet = function (hProcess: THandle; var pv; size: Integer): boolean; stdcall;
|
|
TQueryWorkingSetEx = function (hProcess: THandle; var pv; size: Integer): boolean; stdcall;
|
|
TInitializeProcessForWsWatch = function (hProcess: THandle): boolean; stdcall;
|
|
TGetWsChanges = function (hProcess: THandle; var WatchInfo: TPSAPIWsWatchInformation; size: Integer): boolean; stdcall;
|
|
TGetMappedFileName = function (hProcess: THandle; pv: pointer; FileName: PChar; size: Integer): Integer; stdcall;
|
|
TEnumDeviceDrivers = function (ImageBase: PInteger; cb: Cardinal; var cbNeeded: Cardinal): boolean; stdcall;
|
|
TGetDeviceDriverBaseName = function (ImageBase: Integer; BaseName: PChar; size: Cardinal): Integer; stdcall;
|
|
TGetDeviceDriverFileName = function (ImageBase: Integer; FileName: PChar; size: Cardinal): Integer; stdcall;
|
|
TGetProcessMemoryInfo = function (hProcess: THandle; ProcessMemoryCounters: PProcessMemoryCounters; size: Integer): boolean; stdcall;
|
|
|
|
var
|
|
modulelist :PHInst;
|
|
PSAPILoaded :Boolean;
|
|
|
|
VDMEnumTaskWOWEx :TVDMEnumTaskWOWEx = nil;
|
|
|
|
EnumProcesses: TEnumProcesses = nil;
|
|
EnumProcessModules: TEnumProcessModules = nil;
|
|
EnumProcessModulesEx: TEnumProcessModulesEx = nil;
|
|
GetModuleBaseName: TGetModuleBaseName = nil;
|
|
GetModuleFileNameEx: TGetModuleFileNameEx = nil;
|
|
GetModuleInformation: TGetModuleInformation = nil;
|
|
EmptyWorkingSet: TEmptyWorkingSet = nil;
|
|
QueryWorkingSet: TQueryWorkingSet = nil;
|
|
QueryWorkingSetEx: TQueryWorkingSetEx = nil;
|
|
InitializeProcessForWsWatch: TInitializeProcessForWsWatch = nil;
|
|
GetWsChanges: TGetWsChanges = nil;
|
|
GetMappedFileName: TGetMappedFileName = nil;
|
|
EnumDeviceDrivers: TEnumDeviceDrivers = nil;
|
|
GetDeviceDriverBaseName: TGetDeviceDriverBaseName = nil;
|
|
GetDeviceDriverFileName: TGetDeviceDriverFileName = nil;
|
|
GetProcessMemoryInfo: TGetProcessMemoryInfo = nil;
|
|
|
|
implementation
|
|
|
|
const
|
|
PSAPI_DLL = 'psapi.dll';
|
|
VDM_DLL = 'vdmdbg.dll';
|
|
|
|
var
|
|
PSAPIHandle, VDMHandle: THandle;
|
|
UnloadPSAPI, UnloadVDM: Boolean;
|
|
|
|
function InitPSAPI: Boolean;
|
|
var
|
|
KernelHandle: THandle;
|
|
begin
|
|
KernelHandle:=GetModuleHandle('kernel32.dll');
|
|
PSAPIHandle:=GetModuleHandle(PSAPI_DLL);
|
|
UnloadPSAPI:=PSAPIHandle=0;
|
|
if PSAPIHandle = 0 then
|
|
PSAPIHandle:=LoadLibrary(psapi_dll);
|
|
if PSAPIHandle<>0 then begin
|
|
@EnumProcesses:=GetProcAddress(PSAPIHandle,PChar('EnumProcesses'));
|
|
@EnumProcessModules:=GetProcAddress(PSAPIHandle,PChar('EnumProcessModules'));
|
|
@EnumProcessModulesEx:=GetProcAddress(PSAPIHandle,PChar('EnumProcessModulesEx'));
|
|
if not Assigned(EnumProcessModulesEx) then
|
|
@EnumProcessModulesEx:=GetProcAddress(KernelHandle,PChar('EnumProcessModulesEx'));
|
|
{$IFDEF UNICODE}
|
|
@GetModuleBaseName:=GetProcAddress(PSAPIHandle,PChar('GetModuleBaseNameW'));
|
|
@GetModuleFileNameEx:=GetProcAddress(PSAPIHandle,PChar('GetModuleFileNameExW'));
|
|
@GetMappedFileName:=GetProcAddress(PSAPIHandle,PChar('GetMappedFileNameW'));
|
|
@GetDeviceDriverBaseName:=GetProcAddress(PSAPIHandle,PChar('GetDeviceDriverBaseNameW'));
|
|
@GetDeviceDriverFileName:=GetProcAddress(PSAPIHandle,PChar('GetDeviceDriverFileNameW'));
|
|
{$ELSE}
|
|
@GetModuleBaseName:=GetProcAddress(PSAPIHandle,PChar('GetModuleBaseNameA'));
|
|
@GetModuleFileNameEx:=GetProcAddress(PSAPIHandle,PChar('GetModuleFileNameExA'));
|
|
@GetMappedFileName:=GetProcAddress(PSAPIHandle,PChar('GetMappedFileNameA'));
|
|
@GetDeviceDriverBaseName:=GetProcAddress(PSAPIHandle,PChar('GetDeviceDriverBaseNameA'));
|
|
@GetDeviceDriverFileName:=GetProcAddress(PSAPIHandle,PChar('GetDeviceDriverFileNameA'));
|
|
{$ENDIF}
|
|
@GetModuleInformation:=GetProcAddress(PSAPIHandle,PChar('GetModuleInformation'));
|
|
@EmptyWorkingSet:=GetProcAddress(PSAPIHandle,PChar('EmptyWorkingSet'));
|
|
@QueryWorkingSet:=GetProcAddress(PSAPIHandle,PChar('QueryWorkingSet'));
|
|
@QueryWorkingSetEx:=GetProcAddress(PSAPIHandle,PChar('QueryWorkingSetEx'));
|
|
@InitializeProcessForWsWatch:=GetProcAddress(PSAPIHandle,PChar('InitializeProcessForWsWatch'));
|
|
@GetWsChanges:=GetProcAddress(PSAPIHandle,PChar('GetWsChanges'));
|
|
@EnumDeviceDrivers:=GetProcAddress(PSAPIHandle,PChar('EnumDeviceDrivers'));
|
|
@GetProcessMemoryInfo:=GetProcAddress(PSAPIHandle,PChar('GetProcessMemoryInfo'));
|
|
if not Assigned(GetPerformanceInfo) then
|
|
@GetPerformanceInfo:=GetProcAddress(PSAPIHandle,PChar('GetPerformanceInfo'));
|
|
if not Assigned(GetPerformanceInfo) then
|
|
@GetPerformanceInfo:=GetProcAddress(PSAPIHandle,PChar('K32GetPerformanceInfo'));
|
|
end;
|
|
result:=(PSAPIHandle<>0) and Assigned(EnumProcesses);
|
|
end;
|
|
|
|
procedure FreePSAPI;
|
|
begin
|
|
if (PSAPIHandle<>0) and UnloadPSAPI then begin
|
|
if not FreeLibrary(PSAPIHandle) then
|
|
raise Exception.Create(Format('Unload Error: %s - 0x%x',[PSAPI_DLL,GetModuleHandle(PSAPI_DLL)]))
|
|
else
|
|
PSAPIHandle:=0;
|
|
end;
|
|
end;
|
|
|
|
function InitVDM: Boolean;
|
|
begin
|
|
VDMHandle:=GetModuleHandle(VDM_DLL);
|
|
UnloadVDM:=VDMHandle=0;
|
|
if VDMHandle = 0 then
|
|
VDMHandle:=loadlibrary(VDM_DLL);
|
|
if VDMHandle<>0 then begin
|
|
@VDMEnumTaskWOWEx:=GetProcAddress(VDMHandle,PChar('VDMEnumTaskWOWEx'));
|
|
end;
|
|
result:=(VDMHandle<>0) and Assigned(VDMEnumTaskWOWEx);
|
|
end;
|
|
|
|
procedure FreeVDM;
|
|
begin
|
|
if (VDMHandle<>0) and UnloadVDM then begin
|
|
if not FreeLibrary(VDMHandle) then
|
|
raise Exception.Create(Format('Unload Error: %s - 0x%x',[VDM_DLL,GetModuleHandle(VDM_DLL)]))
|
|
else
|
|
VDMHandle:=0;
|
|
end;
|
|
end;
|
|
|
|
initialization
|
|
InitPSAPI;
|
|
finalization
|
|
FreePSAPI;
|
|
FreeVDM;
|
|
end.
|
|
|