unit frmStructureLinkerUnit; {$mode delphi} interface uses Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, Grids, ExtCtrls, symbolhandler, StructuresFrm2, cefuncproc, newkernelhandler; 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; 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.