mirror of
https://github.com/cheat-engine/cheat-engine
synced 2026-08-15 02:26:08 -04:00
209 lines
5.6 KiB
ObjectPascal
Executable file
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.
|
|
|