All pastes #1578705 Raw Edit

NTProcess

public text v1 · immutable
#1578705 ·published 2009-09-25 02:28 UTC
rendered paste body
unit 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.