cheat-engine/Cheat Engine/frmStructureLinkerUnit.pas
2020-12-10 23:39:40 +01:00

209 lines
5.6 KiB
ObjectPascal
Executable file

unit frmStructureLinkerUnit;
{$mode delphi}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
Grids, ExtCtrls, symbolhandler, StructuresFrm2, cefuncproc, newkernelhandler, betterControls;
type
Tstructinfo=record
s: TDissectedStruct;
address: ptruint;
end;
pstructinfo=^Tstructinfo;
{ TfrmStructureLinker }
TfrmStructureLinker = class(TForm)
btnCancel: TButton;
btnLink: TButton;
cbNoExactMatches: TCheckBox;
cbOverrideLocal: TCheckBox;
cbFillLocal: TCheckBox;
Label1: TLabel;
Panel1: TPanel;
Panel2: TPanel;
Panel3: TPanel;
sgStructureAddress: TStringGrid;
procedure btnLinkClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure Panel1Resize(Sender: TObject);
private
{ private declarations }
struct: array of Tstructinfo;
function FindStructWithAddress(address: ptruint): pstructinfo;
procedure fillInStruct(s: Tstructinfo);
public
{ public declarations }
end;
implementation
{$R *.lfm}
{ TfrmStructureLinker }
uses ProcessHandlerUnit{$ifdef darwin},macport{$endif};
resourcestring
strIsNotAValidAddress = '%s is not a valid address';
procedure TfrmStructureLinker.Panel1Resize(Sender: TObject);
begin
btnLink.left:=(panel1.ClientWidth div 2) - (btnLink.Width - 2);
btnCancel.left:=(panel1.ClientWidth div 2) + 2;
end;
procedure TfrmStructureLinker.FormCreate(Sender: TObject);
var i,j: integer;
begin
//fill the list with structures
setlength(struct, DissectedStructs.Count);
sgStructureAddress.RowCount:=DissectedStructs.Count+1;
for i:=0 to DissectedStructs.Count-1 do
begin
struct[i].s:=TDissectedStruct(DissectedStructs[i]);
sgStructureAddress.Cells[0,i+1]:=TDissectedStruct(DissectedStructs[i]).name;
//go through the frmStructure list and see if it is already defined
for j:=0 to frmStructures2.count-1 do
if TfrmStructures2(frmStructures2[j]).mainStruct=TDissectedStruct(DissectedStructs[i]) then
begin
//get the first address
if TfrmStructures2(frmStructures2[j]).columnCount>0 then //should always be true, but check anyhow
begin
sgStructureAddress.Cells[1,i+1]:=IntToHex(TfrmStructures2(frmStructures2[j]).columns[0].Address,8);
break;
end;
end;
end;
end;
procedure TfrmStructureLinker.FormShow(Sender: TObject);
begin
sgStructureAddress.Update; //fix graphical bug
end;
procedure TfrmStructureLinker.btnLinkClick(Sender: TObject);
var i: integer;
e: boolean;
value: string;
begin
for i:=0 to length(struct)-1 do
begin
value:=sgStructureAddress.Cells[1,i+1];
if value<>'' then
begin
struct[i].address:=symhandler.getAddressFromName(value,false, e);
if e then raise exception.create(format(strIsNotAValidAddress, [struct[i].s.name+' : '+sgStructureAddress.Cells[1,i+1]]));
end
else
struct[i].address:=0;
end;
//addressparsing passed, fill in the links
for i:=0 to length(struct)-1 do
fillInStruct(struct[i]);
modalresult:=mrOk;
end;
function TfrmStructureLinker.FindStructWithAddress(address: ptruint): pstructinfo;
var i: integer;
begin
result:=nil;
for i:=0 to length(struct)-1 do
begin
if (struct[i].s.count>0) then
begin
if ((cbNoExactMatches.checked=false) and (address=struct[i].address)) or (InRangeX(address, struct[i].address, struct[i].address+struct[i].s[struct[i].s.count-1].Offset)) then
begin
result:=@struct[i];
exit;
end;
end;
end;
end;
procedure TfrmStructureLinker.fillInStruct(s: Tstructinfo);
var i: integer;
newStruct: pstructinfo;
temps: Tstructinfo;
pvalue: ptruint;
x: ptruint;
begin
s.s.beginUpdate;
try
for i:=0 to s.s.count-1 do
begin
if s.s.element[i].isPointer then
begin
pvalue:=0;
if ReadProcessMemory(processhandle, pointer(s.address+s.s.element[i].Offset), @pvalue, processhandler.pointersize, x) then
begin
if s.s.element[i].ChildStruct<>nil then
begin
//already filled in
if s.s.element[i].ChildStruct.isInGlobalStructList then continue; //it's already a pointer to a defined struct
//'Local' struct
if cbOverrideLocal.checked then
begin
newStruct:=FindStructWithAddress(pvalue);
if newstruct<>nil then
begin
s.s.element[i].ChildStruct:=newStruct.s;
s.s.element[i].ChildStructStart:=pvalue-newStruct.address;
continue;
end;
end;
//still here so not redefined
if cbFillLocal.checked then
begin
temps.s:=s.s.element[i].ChildStruct;
temps.address:=s.address+s.s.element[i].Offset;
if ReadProcessMemory(processhandle, pointer(temps.address), @temps.address, processhandler.pointersize,x) then
fillInStruct(temps);
end;
end
else
begin
newStruct:=FindStructWithAddress(pvalue);
if newstruct<>nil then //found a match
begin
s.s.element[i].ChildStruct:=newStruct.s;
s.s.element[i].ChildStructStart:=pvalue-newStruct.address;
end;
end;
end;
end; //else not a pointer and not interesting enough to fill in
end;
finally
s.s.endUpdate;
end;
end;
end.