cheat-engine/Cheat Engine/FoundCodeUnit.pas
cheatengine@gmail.com 766b989c56 fix breakpoints that aren't an exact address match
find what accesses/writes now handles exceptions and debugreg (get previous opcode)
2013-05-02 16:29:30 +00:00

750 lines
25 KiB
ObjectPascal

unit FoundCodeUnit;
{$MODE Delphi}
interface
uses
windows, LCLIntf, LResources, Messages, SysUtils, Variants, Classes, Graphics,
Controls, Forms, Dialogs, StdCtrls, disassembler, ExtCtrls, Menus,
NewKernelHandler, clipbrd, ComCtrls;
type Tcoderecord = class
public
address: ptrUint;
size: integer;
opcode: string;
description: string;
// eax,ebx,ecx,edx,esi,edi,ebp,esp,eip: dword;
context: TContext;
stack: record
savedsize: dword;
stack: pbyte;
end;
hitcount: integer;
procedure savestack;
destructor destroy; override;
end;
type
{ TFoundCodeDialog }
TFoundCodeDialog = class(TForm)
FoundCodeList: TListView;
mInfo: TMemo;
Panel1: TPanel;
Description: TLabel;
Panel4: TPanel;
pmOptions: TPopupMenu;
ReplacewithcodethatdoesnothingNOP1: TMenuItem;
Showthisaddressinthedisassembler1: TMenuItem;
Addtothecodelist1: TMenuItem;
MoreInfo1: TMenuItem;
Panel2: TPanel;
btnOK: TButton;
Panel3: TPanel;
btnExtraInfo: TButton;
btnAddToCodeList: TButton;
btnOpenDisassembler: TButton;
btnReplacewithnops: TButton;
N1: TMenuItem;
Copyselectiontoclipboard1: TMenuItem;
Splitter1: TSplitter;
procedure FormCreate(Sender: TObject);
procedure FormDeactivate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormResize(Sender: TObject);
procedure FoundCodeListChange(Sender: TObject; Item: TListItem;
Change: TItemChange);
procedure FoundcodeListClick(Sender: TObject);
procedure btnOKClick(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure btnReplacewithnopsClick(Sender: TObject);
procedure btnOpenDisassemblerClick(Sender: TObject);
procedure btnAddToCodeListClick(Sender: TObject);
procedure FoundcodeListDblClick(Sender: TObject);
procedure btnExtraInfoClick(Sender: TObject);
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
procedure FoundCodeListSelectItem(Sender: TObject; Item: TListItem;
Selected: Boolean);
procedure pmOptionsPopup(Sender: TObject);
procedure Copyselectiontoclipboard1Click(Sender: TObject);
private
{ Private declarations }
procedure addInfo(Coderecord: TCoderecord);
procedure moreinfo;
public
{ Public declarations }
useexceptions: boolean;
usesdebugregs: boolean;
procedure AddRecord;
end;
resourcestring
strClose='Close';
//var
// FoundCodeDialog: TFoundCodeDialog;
implementation
uses CEFuncProc, CEDebugger,debughelper, debugeventhandler,
MemoryBrowserFormUnit,
{$ifdef net}unit2,ceclient,{$else}MainUnit,kerneldebugger,{$endif}
AdvancedOptionsUnit ,formFoundcodeListExtraUnit,MainUnit2;
destructor TCodeRecord.Destroy;
begin
if stack.stack<>nil then
freemem(stack.stack);
inherited destroy;
end;
procedure TCodeRecord.savestack;
var base: qword;
begin
getmem(stack.stack, savedStackSize);
base:=qword(context.{$ifdef cpu64}Rsp{$else}esp{$endif});
if ReadProcessMemory(processhandle, pointer(base), stack.stack, savedStackSize, stack.savedsize)=false then
begin
//for some reason this sometimes returns 0 bytes read even if some of the bytes are readable.
stack.savedsize:=4096-(base mod 4096);
ReadProcessMemory(processhandle, pointer(base), stack.stack, stack.savedsize, stack.savedsize);
end;
end;
procedure TFoundCodedialog.AddRecord;
{
Invoked by the debugger thread
It takes the data from the current thread and stores it in the processlist
}
var currentthread: TDebugThreadHandler;
opcode: string;
address,address2: ptrUint;
desc: string;
coderecord: TCodeRecord;
i: integer;
li: tlistitem;
begin
//the debuggerthread is idle at this point
currentThread:=debuggerthread.CurrentThread;
if currentthread<>nil then
begin
address:=currentThread.context.{$ifdef cpu64}Rip{$else}eip{$endif};
if usesdebugregs or useexceptions then //find out the previous opcode
address:=previousopcode(address);
//disassemble to get the opcode and size
address2:=address;
opcode:=disassemble(address2,desc);
//check if address is inside the list
for i:=0 to foundcodelist.Items.Count-1 do
if TCodeRecord(foundcodelist.Items[i].data).address=address then
begin
//it's already in the list
inc(TCodeRecord(foundcodelist.Items[i].data).hitcount);
FoundcodeList.items[i].caption:=inttostr(TCodeRecord(foundcodelist.Items[i].data).hitcount);
exit;
end;
coderecord:=TCoderecord.create;
coderecord.address:=address;
coderecord.size:=address2-address;
coderecord.opcode:=opcode;
coderecord.description:=desc;
coderecord.context:=currentthread.context^;
coderecord.savestack;
coderecord.hitcount:=1;
li:=FoundCodeList.Items.Add;
li.caption:='1';
li.SubItems.add(opcode);
li.data:=coderecord;
end;
end;
procedure TFoundCodedialog.addInfo(Coderecord: TCoderecord);
var
address: ptruint;
disassembled: array[1..5] of string;
firstchar: char;
hexcount: integer;
temp: string;
begin
if processhandler.is64Bit then
hexcount:=16
else
hexcount:=8;
address:=Coderecord.address;
address:=previousopcode(address);
address:=previousopcode(address);
disassembled[1]:=disassemble(address,temp);
disassembled[2]:=disassemble(address,temp);
if address<>coderecord.address then
begin
disassembled[1]:='';
disassembled[2]:='';
disassembled[3]:=coderecord.opcode;
disassembled[4]:='';
disassembled[5]:='';
end
else
begin
disassembled[3]:=disassemble(address,temp);
disassembled[4]:=disassemble(address,temp);
disassembled[5]:=disassemble(address,temp);
end;
minfo.Lines.Add(disassembled[1]);
minfo.Lines.Add(disassembled[2]);
minfo.Lines.Add(disassembled[3]+' <<');
minfo.Lines.Add(disassembled[4]);
minfo.Lines.Add(disassembled[5]);
minfo.Lines.Add('');
if processhandler.is64bit then
firstchar:='R' else firstchar:='E';
minfo.Lines.Add(firstchar+'AX='+IntToHex(coderecord.context.{$ifdef cpu64}Rax{$else}Eax{$endif},hexcount));
minfo.Lines.Add(firstchar+'BX='+IntToHex(coderecord.context.{$ifdef cpu64}Rbx{$else}Ebx{$endif},hexcount));
minfo.Lines.Add(firstchar+'CX='+IntToHex(coderecord.context.{$ifdef cpu64}Rcx{$else}Ecx{$endif},hexcount));
minfo.Lines.Add(firstchar+'DX='+IntToHex(coderecord.context.{$ifdef cpu64}Rdx{$else}Edx{$endif},hexcount));
minfo.Lines.Add(firstchar+'SI='+IntToHex(coderecord.context.{$ifdef cpu64}Rsi{$else}Esi{$endif},hexcount));
minfo.Lines.Add(firstchar+'DI='+IntToHex(coderecord.context.{$ifdef cpu64}Rdi{$else}Edi{$endif},hexcount));
minfo.Lines.Add(firstchar+'SP='+IntToHex(coderecord.context.{$ifdef cpu64}Rsp{$else}Esp{$endif},hexcount));
minfo.Lines.Add(firstchar+'BP='+IntToHex(coderecord.context.{$ifdef cpu64}Rbp{$else}Ebp{$endif},hexcount));
minfo.Lines.Add(firstchar+'IP='+IntToHex(coderecord.context.{$ifdef cpu64}Rip{$else}Eip{$endif},hexcount));
{$ifdef cpu64}
if processhandler.is64bit then
begin
minfo.Lines.Add('R8='+IntToHex(coderecord.context.r8,16));
minfo.Lines.Add('R9='+IntToHex(coderecord.context.r9,16));
minfo.Lines.Add('R10='+IntToHex(coderecord.context.r10,16));
minfo.Lines.Add('R11='+IntToHex(coderecord.context.r11,16));
minfo.Lines.Add('R12='+IntToHex(coderecord.context.r12,16));
minfo.Lines.Add('R13='+IntToHex(coderecord.context.r13,16));
minfo.Lines.Add('R14='+IntToHex(coderecord.context.r14,16));
minfo.Lines.Add('R15='+IntToHex(coderecord.context.r15,16));
end;
{$endif}
minfo.lines.add('');
minfo.lines.add('');
end;
procedure TFoundCodedialog.moreinfo;
var disassembled: array[1..5] of string;
address: ptrUint;
itemindex: integer;
temp,temp2: string;
maxregistervalue: ptrUint;
p: ptrUint;
i: integer;
coderecord: TCodeRecord;
firstchar: string;
w: integer;
FormFoundCodeListExtra: TFormFoundCodeListExtra;
begin
itemindex:=foundcodelist.ItemIndex;
if itemindex<>-1 then
begin
FormFoundCodeListExtra:=TFormFoundCodeListExtra.Create(application);
if useexceptions then
FormFoundCodeListExtra.Label18.Visible:=false
else
FormFoundCodeListExtra.Label18.Visible:=true;
coderecord:=TCodeRecord(foundcodelist.items[itemindex].data);
address:=coderecord.address;
address:=previousopcode(address);
address:=previousopcode(address);
disassembled[1]:=disassemble(address,temp);
disassembled[2]:=disassemble(address,temp);
if address<>coderecord.address then
begin
disassembled[1]:='';
disassembled[2]:='';
disassembled[3]:=coderecord.opcode;
disassembled[4]:='';
disassembled[5]:='';
end
else
begin
disassembled[3]:=disassemble(address,temp);
disassembled[4]:=disassemble(address,temp);
disassembled[5]:=disassemble(address,temp);
end;
//convert disassembled strings to address+opcode only (no bytes)
//xxxxxxxx - xx xx xx - opcode
temp:=copy(disassembled[1],pos('-',disassembled[1])+2,length(disassembled[1]));
temp:=copy(temp,pos('-',temp)+2,length(temp));
disassembled[1]:=copy(disassembled[1],1,pos('-',disassembled[1]))+' '+temp;
temp:=copy(disassembled[2],pos('-',disassembled[2])+2,length(disassembled[2]));
temp:=copy(temp,pos('-',temp)+2,length(temp));
disassembled[2]:=copy(disassembled[2],1,pos('-',disassembled[2]))+' '+temp;
temp:=copy(disassembled[3],pos('-',disassembled[3])+2,length(disassembled[3]));
temp:=copy(temp,pos('-',temp)+2,length(temp));
disassembled[3]:=copy(disassembled[3],1,pos('-',disassembled[3]))+' '+temp;
temp:=copy(disassembled[4],pos('-',disassembled[4])+2,length(disassembled[4]));
temp:=copy(temp,pos('-',temp)+2,length(temp));
disassembled[4]:=copy(disassembled[4],1,pos('-',disassembled[4]))+' '+temp;
temp:=copy(disassembled[5],pos('-',disassembled[5])+2,length(disassembled[5]));
temp:=copy(temp,pos('-',temp)+2,length(temp));
disassembled[5]:=copy(disassembled[5],1,pos('-',disassembled[5]))+' '+temp;
with FormFoundCodeListExtra do
begin
Label1.Caption:=disassembled[1];
Label2.Caption:=disassembled[2];
Label3.Caption:=disassembled[3];
Label4.Caption:=disassembled[4];
Label5.Caption:=disassembled[5];
if processhandler.is64bit then
firstchar:='R' else firstchar:='E';
lblRAX.caption:=firstchar+'AX='+IntToHex(coderecord.context.{$ifdef cpu64}Rax{$else}Eax{$endif},8);
lblRBX.caption:=firstchar+'BX='+IntToHex(coderecord.context.{$ifdef cpu64}Rbx{$else}Ebx{$endif},8);
lblRCX.caption:=firstchar+'CX='+IntToHex(coderecord.context.{$ifdef cpu64}Rcx{$else}Ecx{$endif},8);
lblRDX.caption:=firstchar+'DX='+IntToHex(coderecord.context.{$ifdef cpu64}Rdx{$else}Edx{$endif},8);
lblRSI.caption:=firstchar+'SI='+IntToHex(coderecord.context.{$ifdef cpu64}Rsi{$else}Esi{$endif},8);
lblRDI.caption:=firstchar+'DI='+IntToHex(coderecord.context.{$ifdef cpu64}Rdi{$else}Edi{$endif},8);
lblRSP.caption:=firstchar+'SP='+IntToHex(coderecord.context.{$ifdef cpu64}Rsp{$else}Esp{$endif},8);
lblRBP.caption:=firstchar+'BP='+IntToHex(coderecord.context.{$ifdef cpu64}Rbp{$else}Ebp{$endif},8);
lblRIP.caption:=firstchar+'IP='+IntToHex(coderecord.context.{$ifdef cpu64}Rip{$else}Eip{$endif},8);
{$ifdef cpu64}
if processhandler.is64bit then
begin
lblR8:=tlabel.Create(FormFoundCodeListExtra);
lblR8.font:=lblRCX.font;
lblR8.Top:=lblRCX.top+(lblRCX.top-lblRBX.top);
lblR8.left:=lblRCX.left;
lblR8.caption:=' R8='+IntToHex(coderecord.context.r8,8);
lblR8.parent:=FormFoundCodeListExtra.panel6;
lblR8.OnMouseDown:=registerMouseDown;
lblR8.OnDblClick:=RegisterDblClick;
lblR8.Align:=lblrcx.Align;
lblR9:=tlabel.Create(FormFoundCodeListExtra);
lblR9.font:=lblRCX.font;
lblR9.Top:=lblRCX.top+(lblRCX.top-lblRBX.top);
lblR9.left:=lblRDI.left;
lblR9.caption:=' R9='+IntToHex(coderecord.context.r9,8);
lblR9.parent:=FormFoundCodeListExtra.panel6;
lblR9.OnMouseDown:=registerMouseDown;
lblR9.OnDblClick:=RegisterDblClick;
lblR9.Align:=lblrcx.Align;
lblR10:=tlabel.Create(FormFoundCodeListExtra);
lblR10.font:=lblRCX.font;
lblR10.Top:=lblRCX.top+(lblRCX.top-lblRBX.top);
lblR10.left:=lblRIP.left;
lblR10.caption:='R10='+IntToHex(coderecord.context.r10,8);
lblR10.parent:=FormFoundCodeListExtra.panel6;
lblR10.OnMouseDown:=registerMouseDown;
lblR10.OnDblClick:=RegisterDblClick;
lblR10.Align:=lblrcx.Align;
lblR11:=tlabel.Create(FormFoundCodeListExtra);
lblR11.font:=lblRCX.font;
lblR11.Top:=lblR8.top+(lblR8.top-lblRCX.top);
lblR11.left:=lblRCX.left;
lblR11.caption:='R11='+IntToHex(coderecord.context.r11,8);
lblR11.parent:=FormFoundCodeListExtra.panel6;
lblR11.OnMouseDown:=registerMouseDown;
lblR11.OnDblClick:=RegisterDblClick;
lblR11.Align:=lblrcx.Align;
lblR12:=tlabel.Create(FormFoundCodeListExtra);
lblR12.font:=lblRCX.font;
lblR12.Top:=lblR8.top+(lblR8.top-lblRCX.top);
lblR12.left:=lblRDI.left;
lblR12.caption:='R12='+IntToHex(coderecord.context.r12,8);
lblR12.parent:=FormFoundCodeListExtra.panel6;
lblR12.OnMouseDown:=registerMouseDown;
lblR12.OnDblClick:=RegisterDblClick;
lblR12.Align:=lblrcx.Align;
lblR13:=tlabel.Create(FormFoundCodeListExtra);
lblR13.font:=lblRCX.font;
lblR13.Top:=lblR8.top+(lblR8.top-lblRCX.top);
lblR13.left:=lblRIP.left;
lblR13.caption:='R13='+IntToHex(coderecord.context.r13,8);
lblR13.parent:=FormFoundCodeListExtra.panel6;
lblR13.OnMouseDown:=registerMouseDown;
lblR13.OnDblClick:=RegisterDblClick;
lblR13.Align:=lblrcx.Align;
lblR14:=tlabel.Create(FormFoundCodeListExtra);
lblR14.font:=lblRCX.font;
lblR14.Top:=lblR11.top+(lblR11.top-lblR8.top);
lblR14.left:=lblRCX.left;
lblR14.caption:='R14='+IntToHex(coderecord.context.r14,8);
lblR14.parent:=FormFoundCodeListExtra.panel6;
lblR14.OnMouseDown:=registerMouseDown;
lblR14.OnDblClick:=RegisterDblClick;
lblR14.Align:=lblrcx.Align;
lblR15:=tlabel.Create(FormFoundCodeListExtra);
lblR15.font:=lblRCX.font;
lblR15.Top:=lblR11.top+(lblR11.top-lblR8.top);
lblR15.left:=lblRDI.left;
lblR15.caption:='R15='+IntToHex(coderecord.context.r15,8);
lblR15.parent:=FormFoundCodeListExtra.panel6;
lblR15.OnMouseDown:=registerMouseDown;
lblR15.OnDblClick:=RegisterDblClick;
lblR15.Align:=lblrcx.Align;
Constraints.MinHeight:=panel6.top+(lblR15.top+lblR15.height)+16+panel5.height;
if height<Constraints.MinHeight then
height:=Constraints.MinHeight;
// if panel6.clientheight<lblR15.top+lblR15.height then //make room
// height:=height+(lblR15.top+lblR15.height)-(lblRDI.top+lblRDI.height);
end;
{$endif}
label6.Caption:=coderecord.description;
end;
//parse the disassembled[3] string to help the user find the pointer
//first find the [xxx]
temp:=lowercase(copy(disassembled[3],pos('[',disassembled[3])+1,(pos(']',disassembled[3])-1)-(pos('[',disassembled[3]))));
firstchar:=lowercase(firstchar);
maxregistervalue:=0;
if temp<>'' then
begin
//parse
//find the biggest value, registers or exact value
if pos(firstchar+'ax',temp)>0 then maxregistervalue:=MaxX(maxregistervalue, coderecord.context.{$ifdef cpu64}Rax{$else}Eax{$endif});
if pos(firstchar+'bx',temp)>0 then maxregistervalue:=MaxX(maxregistervalue, coderecord.context.{$ifdef cpu64}Rbx{$else}Ebx{$endif});
if pos(firstchar+'cx',temp)>0 then maxregistervalue:=MaxX(maxregistervalue, coderecord.context.{$ifdef cpu64}Rcx{$else}Ecx{$endif});
if pos(firstchar+'dx',temp)>0 then maxregistervalue:=MaxX(maxregistervalue, coderecord.context.{$ifdef cpu64}Rdx{$else}Edx{$endif});
if pos(firstchar+'di',temp)>0 then maxregistervalue:=MaxX(maxregistervalue, coderecord.context.{$ifdef cpu64}Rdi{$else}Edi{$endif});
if pos(firstchar+'si',temp)>0 then maxregistervalue:=MaxX(maxregistervalue, coderecord.context.{$ifdef cpu64}Rsi{$else}Esi{$endif});
if pos(firstchar+'bp',temp)>0 then maxregistervalue:=MaxX(maxregistervalue, coderecord.context.{$ifdef cpu64}Rbp{$else}Ebp{$endif});
if pos(firstchar+'sp',temp)>0 then maxregistervalue:=MaxX(maxregistervalue, coderecord.context.{$ifdef cpu64}Rsp{$else}Esp{$endif});
{$ifdef cpu64}
if processhandler.is64Bit then
begin
if pos('r8',temp)>0 then maxregistervalue:=MaxX(maxregistervalue, coderecord.context.r8);
if pos('r9',temp)>0 then maxregistervalue:=MaxX(maxregistervalue, coderecord.context.r9);
if pos('r0',temp)>0 then maxregistervalue:=MaxX(maxregistervalue, coderecord.context.r10);
if pos('r1',temp)>0 then maxregistervalue:=MaxX(maxregistervalue, coderecord.context.r11);
if pos('r2',temp)>0 then maxregistervalue:=MaxX(maxregistervalue, coderecord.context.r12);
if pos('r3',temp)>0 then maxregistervalue:=MaxX(maxregistervalue, coderecord.context.r13);
if pos('r4',temp)>0 then maxregistervalue:=MaxX(maxregistervalue, coderecord.context.r14);
if pos('r5',temp)>0 then maxregistervalue:=MaxX(maxregistervalue, coderecord.context.r15);
end;
{$endif}
//the offset is always at the end, so read from back to front
temp2:='';
for i:=length(temp) downto 1 do
if temp[i] in ['0'..'9','a'..'f'] then temp2:=temp[i]+temp2 else break;
if temp2<>'' then //I know this isn't completly correct e.g: [eax*4] but even then the 4 will NEVER be bigger than eax (unless it's to cause a crash)
begin
p:=StrToQWordEx('$'+temp2);
if p>maxregistervalue then maxregistervalue:=p;
end;
formfoundcodelistextra.probably:=maxregistervalue;
end else formfoundcodelistextra.label17.caption:='';
w:=formfoundcodelistextra.width;
w:=max(w,formfoundcodelistextra.label1.width);
w:=max(w,formfoundcodelistextra.label2.width);
w:=max(w,formfoundcodelistextra.label3.width);
w:=max(w,formfoundcodelistextra.label4.width);
w:=max(w,formfoundcodelistextra.label5.width);
if w<>formfoundcodelistextra.Width then
formfoundcodelistextra.Width:=w+5;
//copy the context and the stack to the more info window. the foundcode unit might get destroyed
formfoundcodelistextra.context:=coderecord.context;
if coderecord.stack.stack<>nil then
begin
getmem(formfoundcodelistextra.stack.stack, coderecord.stack.savedsize);
formfoundcodelistextra.stack.savedsize:=coderecord.stack.savedsize;
CopyMemory(formfoundcodelistextra.stack.stack, coderecord.stack.stack, coderecord.stack.savedsize);
end;
FormFoundCodeListExtra.Show;
// FormFoundCodeListExtra.free;
end;
end;
procedure TFoundCodeDialog.FoundcodeListClick(Sender: TObject);
begin
end;
procedure TFoundCodeDialog.FormCreate(Sender: TObject);
var x: array of integer;
begin
btnOk.caption:=strStop;
setlength(x,0);
loadformposition(self,x);
end;
procedure TFoundCodeDialog.FormDeactivate(Sender: TObject);
begin
end;
procedure TFoundCodeDialog.FormDestroy(Sender: TObject);
var i: integer;
cr: Tcoderecord;
begin
for i:=0 to FoundCodeList.Items.count-1 do
begin
cr:=Tcoderecord(FoundCodeList.Items[i].data);
cr.free;
end;
saveformposition(self,[]);
end;
procedure TFoundCodeDialog.FormResize(Sender: TObject);
begin
FoundCodeList.Column[1].AutoSize:=false;
FoundCodeList.Column[1].AutoSize:=true;
end;
procedure TFoundCodeDialog.FoundCodeListChange(Sender: TObject;
Item: TListItem; Change: TItemChange);
begin
end;
procedure TFoundCodeDialog.btnOKClick(Sender: TObject);
var original: dword;
i: integer;
begin
if btnOK.caption=strStop then
begin
if debuggerthread<>nil then
debuggerthread.CodeFinderStop(self);
btnOK.caption:=strClose;
end
else close;
end;
procedure TFoundCodeDialog.FormClose(Sender: TObject;
var Action: TCloseAction);
begin
if btnOK.caption=strStop then
if debuggerthread<>nil then
debuggerthread.CodeFinderStop(self);
action:=caFree;
end;
procedure TFoundCodeDialog.btnReplacewithnopsClick(Sender: TObject);
var codelength: dword;
written: dword;
i,j: integer;
nops: array of byte;
a: dword;
original: dword;
mbi : _MEMORY_BASIC_INFORMATION;
coderecord: TCodeRecord;
begin
with foundcodelist do
begin
for j:=0 to foundcodelist.items.Count-1 do
begin
if foundcodelist.items[j].Selected then
begin
coderecord:=TcodeRecord(foundcodelist.items[j].data);
codelength:=coderecord.size;
//add it to the codelist
if advancedoptions.AddToCodeList(coderecord.address,coderecord.size,true, foundcodelist.SelCount>1) then
begin
setlength(nops,codelength);
for i:=0 to codelength-1 do
nops[i]:=$90; // $90=nop
zeromemory(@mbi,sizeof(mbi));
RewriteCode(processhandle,coderecord.address,@nops[0],codelength);
end;
end;
end;
end;
end;
procedure TFoundCodeDialog.btnOpenDisassemblerClick(Sender: TObject);
var coderecord: TCodeRecord;
begin
if foundcodelist.itemindex<>-1 then
begin
coderecord:=TcodeRecord(foundcodelist.items[foundcodelist.itemindex].data);
memorybrowser.disassemblerview.SelectedAddress:=coderecord.address;
memorybrowser.panel1.visible:=true;
memorybrowser.show;
end;
end;
procedure TFoundCodeDialog.btnAddToCodeListClick(Sender: TObject);
var i: integer;
coderecord: TCodeRecord;
begin
for i:=0 to foundcodelist.items.count-1 do
begin
if foundcodelist.items[i].Selected then
begin
coderecord:=TcodeRecord(foundcodelist.items[i].data);
advancedoptions.AddToCodeList(coderecord.address,coderecord.size,false, foundcodelist.SelCount>1);
end;
end;
advancedoptions.Show;
end;
procedure TFoundCodeDialog.FoundcodeListDblClick(Sender: TObject);
begin
MoreInfo;
end;
procedure TFoundCodeDialog.btnExtraInfoClick(Sender: TObject);
begin
moreinfo;
end;
procedure TFoundCodeDialog.FormCloseQuery(Sender: TObject;
var CanClose: Boolean);
begin
if btnOK.caption=strStop then btnOK.Click;
CanClose:=true;
end;
procedure TFoundCodeDialog.FoundCodeListSelectItem(Sender: TObject;
Item: TListItem; Selected: Boolean);
var coderecord: TCodeRecord;
selectedRecord: integer;
i: integer;
begin
minfo.clear;
if foundcodelist.Selected<>nil then
begin
btnReplacewithnops.enabled:=true;
btnOpenDisassembler.enabled:=true;
btnAddToCodeList.enabled:=true;
btnExtraInfo.Enabled:=true;
coderecord:=TCodeRecord(foundcodelist.Selected.data);
description.Caption:=coderecord.description;
for i:=0 to FoundCodeList.Items.Count-1 do
begin
if foundcodelist.items[i].Selected then
begin
coderecord:=TCodeRecord(foundcodelist.items[i].data);
addinfo(coderecord);
end;
end;
//minfo.VertScrollBar.Position:=0;
minfo.SelStart:=0;
minfo.SelLength:=0;
end
else
begin
btnReplacewithnops.enabled:=false;
btnOpenDisassembler.enabled:=false;
btnAddToCodeList.enabled:=false;
btnExtraInfo.Enabled:=false;
if foundcodelist.Items.Count=0 then
description.caption:=rsUseTheGameApplicationForAWhile
else
description.caption:=rsSelectAnItemFromTheListForASmallDescription;
end;
end;
procedure TFoundCodeDialog.pmOptionsPopup(Sender: TObject);
begin
ReplacewithcodethatdoesnothingNOP1.Enabled:=foundcodelist.selcount>0;
Showthisaddressinthedisassembler1.enabled:=foundcodelist.itemindex<>-1;
Addtothecodelist1.enabled:=foundcodelist.selcount>0;
MoreInfo1.Enabled:=foundcodelist.itemindex<>-1;
Copyselectiontoclipboard1.enabled:=foundcodelist.selcount>0;
end;
procedure TFoundCodeDialog.Copyselectiontoclipboard1Click(Sender: TObject);
var
i: integer;
s: string;
begin
s:='';
for i:=0 to FoundcodeList.Items.count-1 do
if FoundcodeList.items[i].selected then
s:=s+FoundcodeList.Items[i].subitems[0]+#13#10;
clipboard.AsText:=s;
end;
initialization
{$i FoundCodeUnit.lrs}
end.