rendered paste bodyunit NTProcess;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, PsAPI;
type
//PHInst = ^HInst;
TWowModule = class
end;
TWoWTask = class
private
fThreadID : DWORD;
fHMod16 : WORD;
fHTask16 : WORD;
fModName : string;
fFileName : string;
public
property ThreadID : DWORD read fThreadID;
property HMod16 : WORD read fHMOD16;
property HTask16 : WORD read fHTask16;
property ModName : string read fModName;
property FileName : string read fFileName;
end;
TNTProcess = class (TComponent)
private
fPID : Integer;
fModuleList : PDWORD;
fModuleCount : Integer;
fWOWTaskList : TList;
procedure SetPID (value : Integer);
function GetBaseName : string;
procedure GetModuleList;
function GetModuleCount : Integer;
function GetModule (index : Integer) : DWORD;
function GetModulebaseName (index : Integer) : string;
function GetModuleFileName (index : Integer) : string;
procedure GetWOWTaskList;
function GetWOWTaskCount : Integer;
function GetWOWTask (index : Integer) : TWowTask;
public
destructor Destroy; override;
property PID : Integer read fPID write SetPID;
property BaseName : string read GetBaseName;
property ModuleCount : Integer read GetModuleCount;
property Module [index : Integer] : HInst read GetModule;
property ModuleBaseName [index : Integer] : string read GetModuleBaseName;
property ModuleFileName [index : Integer] : string read GetModuleFileName;
function IsVDM : boolean;
property WOWTaskCount : Integer read GetWOWTaskCount;
property WOWTask [index : Integer] : TWOWTask read GetWowTask;
procedure ResetWOWTaskList;
end;
TNTProcessList = class(TComponent)
private
fPIDList : LPDWORD;
fPIDCount : Integer;
function GetPID (index : Integer) : DWORD;
protected
public
constructor Create (AOwner : TComponent); override;
destructor Destroy; override;
procedure Refresh;
procedure GetProcess (n : WORD; var process : TNTProcess);
procedure FindProcess (PID : DWORD; var process : TNTProcess);
property Count : Integer read fPIDCount;
property PID [index : Integer] : DWORD read GetPID;
published
end;
procedure Register;
implementation
uses unitNTException;
constructor TNTProcessList.Create (AOwner : TComponent);
begin
inherited Create (AOwner);
Refresh;
end;
destructor TNTProcessList.Destroy;
begin
ReallocMem (fPIDList, 0);
inherited;
end;
procedure TNTProcessList.Refresh;
var cbNeeded : DWORD;
begin
ReallocMem (fPIDList, 65536);
if not EnumProcesses (fPIDList, 65536, cbNeeded) then cbNeeded := 0;
ReallocMem (fPIDList, cbNeeded);
fPIDCount := cbNeeded div sizeof (DWORD);
end;
function TNTProcessList.GetPID (index : Integer) : DWORD;
begin
if (index >= 0) and (index < Count) then
result := PDWORD (PChar (fPIDList) + index * sizeof (DWORD))^
else
raise ERangeError.Create ('PID index out of range');
end;
procedure TNTProcessList.GetProcess (n : WORD; var process : TNTProcess);
begin
process.PID := PID [n]
end;
procedure TNTProcessList.FindProcess (PID : DWORD; var process : TNTProcess);
var
p : LPDWORD;
i : Integer;
begin
p := fPIDList;
for i := 0 to count - 1 do
begin
if p^ = PID then
begin
GetProcess (i, process);
exit
end
end;
raise Exception.CreateFmt ('PID %d not found', [pid])
end;
destructor TNTProcess.Destroy;
begin
ReallocMem (fModuleList, 0);
ResetWOWTaskList;
inherited
end;
procedure TNTProcess.SetPID (value : Integer);
begin
if fPID <> value then
begin
fPID := value;
ReallocMem (fModuleList, 0);
end
end;
function TNTProcess.GetBaseName : string;
var
handle : THandle;
szName : array [0..MAX_PATH - 1] of char;
begin
handle := OpenProcess (PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, PID);
if handle <> 0 then
try
if psapi.GetModuleBaseName (handle, 0, szName, sizeof (szName)) > 0 then
result := szName
else
result := 'System'
finally
CloseHandle (handle)
end
else
if PID = 0 then
result := 'Idle'
else
raise ENTException.CreateLastError
end;
procedure TNTProcess.GetModuleList;
var
handle : THandle;
cbNeeded : DWORD;
begin
handle := OpenProcess (PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, PID);
fModuleCount := 0;
if handle <> 0 then
begin
ReallocMem (fModuleList, 65536);
if not EnumProcessModules (handle, fModuleList, 65536, cbNeeded) then cbNeeded := 0;
ReallocMem (fModuleList, cbNeeded);
fModuleCount := cbNeeded div sizeof (hInst)
end
else ReallocMem (fModuleList, 0);
end;
function TNTProcess.GetModuleCount : Integer;
begin
if fModuleList = Nil then
GetModuleList;
result := fModuleCount
end;
function TNTProcess.GetModule (index : Integer) : DWORD;
begin
if (index >= 0) and (index < ModuleCount) then
result := PDWORD (PChar (fModuleList) + index * sizeof (DWORD))^
else
raise ERangeError.Create ('Module index out of range');
end;
function TNTProcess.GetModuleBaseName (index : Integer) : string;
var
inst : HInst;
handle : THandle;
szName : array [0..MAX_PATH - 1] of char;
begin
inst := Module [index];
handle := OpenProcess (PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, PID);
if handle <> 0 then
if psapi.GetModuleBaseName (handle, inst, szName, sizeof (szName)) > 0 then
result := szName
else
result := 'System'
else
if PID = 0 then
result := 'Idle'
else
raise ENTException.CreateLastError
end;
function TNTProcess.GetModuleFileName (index : Integer) : string;
var
inst : HInst;
handle : THandle;
szName : array [0..MAX_PATH - 1] of char;
begin
inst := Module [index];
handle := OpenProcess (PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, PID);
if handle <> 0 then
if psapi.GetModuleFileNameEx (handle, inst, szName, sizeof (szName)) > 0 then
result := szName
else
result := 'System'
else
if PID = 0 then
result := 'Idle'
else
raise ENTException.CreateLastError
end;
function TNTProcess.IsVDM : boolean;
var
s : string;
p : Integer;
begin
s := BaseName;
p := pos ('.', s);
if p > 0 then s := Copy (s, 1, p - 1);
result := LowerCase (s) = 'ntvdm'
end;
type
TaskEnumProcEx = function (threadID : DWORD; hMod16 : WORD; hTask16 : WORD; modName : PChar; fileName : PChar; param : DWORD) : BOOL; stdcall;
function VDMEnumTaskWOWEx (pid : DWORD; callback : TaskEnumProcEx; param : DWORD) : Integer; stdcall; external 'vdmdbg.dll';
function EnumTaskCallback (threadID : DWORD; hMod16 : WORD; hTask16 : WORD; modName : PChar; fileName : PChar; param : DWORD) : BOOL; stdcall;
var
WOWProcess : TWowTask;
begin
WowProcess := TWowTask.Create;
WowProcess.fThreadID := threadID;
WowProcess.fHMod16 := hMod16;
WowProcess.fHTask16 := hTask16;
WowProcess.fModName := modName;
WowProcess.fFileName := fileName;
TNTProcess (param).fWOWTaskList.Add (WOWProcess);
result := False;
end;
procedure TNTProcess.GetWOWTaskList;
begin
if fWOWTaskList = Nil then
begin
fWOWTaskList := TList.Create;
VDMEnumTaskWOWEx (pid, EnumTaskCallback, DWORD (self));
end
end;
function TNTProcess.GetWOWTaskCount : Integer;
begin
GetWOWTaskList;
result := fWOWTaskList.Count;
end;
function TNTProcess.GetWOWTask (index : Integer) : TWowTask;
begin
GetWOWTaskList;
result := TWOWTask (fWowTaskList [index])
end;
procedure TNTProcess.ResetWOWTaskList;
var
i : Integer;
begin
if fWOWTaskList <> Nil then
begin
for i := 0 to fWOWTaskList.Count - 1 do
TWOWTask (fWOWTaskList [i]).Free;
fWOWTaskList.Free;
fWOWTaskList := Nil;
end
end;
procedure Register;
begin
RegisterComponents('NT', [TNTProcessList, TNTProcess]);
end;
end.