root/Cheat Engine/frmReferencedStringsUnit.pas @ 312

Revision 312, 7.6 kB (checked in by dark_byte, 7 months ago)
Line 
1unit frmReferencedStringsUnit;
2
3interface
4
5uses
6  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
7  Dialogs, ComCtrls, ExtCtrls, StdCtrls, syncobjs, cefuncproc, newkernelhandler,
8  math, Menus;
9
10type
11  TfrmReferencedStrings=class;
12  TDelayedStringfiller = class(TThread)
13  private
14  public
15    s: tstringlist;
16    csList: TCriticalSection;
17    procedure execute; override;
18    constructor create(suspended: boolean);
19    destructor destroy; override;
20  end;
21
22  TfrmReferencedStrings = class(TForm)
23
24    lvStringlist: TListView;
25    lbReflist: TListBox;
26    Splitter1: TSplitter;
27    MainMenu1: TMainMenu;
28    Search1: TMenuItem;
29    Find1: TMenuItem;
30    FindNext1: TMenuItem;
31    FindDialog1: TFindDialog;
32    procedure FormShow(Sender: TObject);
33    procedure lvStringlistData(Sender: TObject; Item: TListItem);
34    procedure FormClose(Sender: TObject; var Action: TCloseAction);
35    procedure lvStringlistDblClick(Sender: TObject);
36    procedure lvStringlistSelectItem(Sender: TObject; Item: TListItem;
37      Selected: Boolean);
38    procedure lbReflistDblClick(Sender: TObject);
39    procedure Find1Click(Sender: TObject);
40    procedure FindDialog1Find(Sender: TObject);
41    procedure FindNext1Click(Sender: TObject);
42  private
43    { Private declarations }
44    stringlist: TStringlist; //fitting name...
45    stringfiller: TDelayedStringfiller;
46    procedure LoadStringlist;
47  public
48    { Public declarations }
49  end;
50
51var
52  frmReferencedStrings: TfrmReferencedStrings;
53
54implementation
55
56uses DissectCodeunit, DissectCodeThread, memorybrowserformunit;
57
58{$R *.dfm}
59
60function getStringFromAddress(address: dword): string;
61{Reads the string at the given address}
62var
63  c: pchar;
64  wc: pwidechar absolute c;
65
66  s: string;
67  ws: widestring;
68  x: dword;
69  i: integer;
70
71  notascii: boolean;
72
73begin
74  result:='-';
75  getmem(c,512);
76  try
77    if ReadProcessMemory(processhandle, pointer(address), c, 512, x) then
78    begin
79      //evaluate the string (is it widestring or ascii) , and place a 0 terminator when invalid char
80
81      //test for ascii
82      notascii:=false;
83      for i:=0 to 511 do
84        if not (c[i] in [#32..#127]) then
85        begin
86          if i>=4 then //long enough ascii string
87          begin
88            c[i]:=#0;
89            s:=c;
90            result:=s;
91            exit;
92          end;
93
94          notascii:=true;
95          break; //still here, so not an ascii string
96        end;
97
98      if not notascii then //it IS a ascii string (big one)
99      begin
100        c[511]:=#0;
101        s:=c;
102        result:=c;
103        exit;
104      end;
105
106      for i:=0 to 255 do
107        if not (word(wc[i]) in [32..127]) then
108        begin
109          wc[i]:=#0;
110          ws:=wc;
111          result:=ws;
112          exit;
113        end;
114
115
116    end;
117
118  finally
119    freemem(c);
120  end;
121end;
122
123constructor TDelayedStringfiller.create(suspended: boolean);
124begin
125  csList:=TCriticalSection.Create;
126
127  inherited create(suspended);
128end;
129
130destructor TDelayedStringfiller.destroy;
131begin
132  if csList <> nil then
133    cslist.free;
134
135  inherited destroy;
136end;
137
138procedure TDelayedStringfiller.execute;
139var
140  i: integer;
141  x: TStringReference;
142  start: integer;
143begin
144  start:=0;
145
146  while (not terminated) and (start<s.count) do
147  begin
148    cslist.Enter;
149    try
150      for i:=start to min(s.Count,start+512)-1 do
151      begin
152        x:=TStringReference(s.Objects[i]);
153        if x.s='' then
154          x.s:=getStringFromAddress(x.address);
155      end;
156    finally
157      cslist.Leave;
158    end;
159
160    sleep(10);
161    inc(start,512);
162  end;
163
164end;
165
166
167procedure TfrmReferencedStrings.LoadStringlist;
168//checks the dissectcodethread object for the string addresses
169var
170  i: integer;
171  x: TStringReference;
172begin
173  if stringlist<>nil then
174  begin
175    for i:=0 to stringlist.Count-1 do
176    begin
177      x:=TStringReference(stringlist.Objects[i]);
178      x.free;
179      stringlist.Objects[i]:=nil;
180    end;
181    stringlist.Free;
182  end;
183
184  stringlist:=tstringlist.Create;
185  frmdissectcode.dissectcode.getstringlist(stringlist);
186
187  if stringfiller<>nil then
188  begin
189    stringfiller.Terminate;
190    stringfiller.WaitFor;
191    stringfiller.Free;
192  end;
193
194  stringfiller:=tdelayedstringfiller.create(true);
195  stringfiller.s:=stringlist;
196  stringfiller.Resume;
197
198  lvStringlist.Items.Count:=stringlist.Count;
199end;
200
201procedure TfrmReferencedStrings.FormShow(Sender: TObject);
202begin
203  //cleanup the stringlist
204  lbRefList.items.clear;
205  lvStringlist.Items.Clear;
206  lvStringlist.Items.Count:=0;
207
208  LoadStringlist;
209end;
210
211procedure TfrmReferencedStrings.lvStringlistData(Sender: TObject;
212  Item: TListItem);
213var x: TStringReference;
214begin
215  if item.index<stringlist.Count then
216  begin
217    item.Caption:=stringlist[item.Index];
218    x:=TStringReference(stringlist.objects[item.index]);
219
220    item.SubItems.Add(inttostr(length(x.references)));
221
222    stringfiller.csList.Enter;
223    try
224      if x.s='' then
225        x.s:=getstringfromaddress(x.address);
226    finally
227      stringfiller.csList.Leave;
228    end;
229
230
231    item.SubItems.Add(x.s);
232
233  end;
234end;
235
236procedure TfrmReferencedStrings.FormClose(Sender: TObject;
237  var Action: TCloseAction);
238var i: integer;
239    x: TStringReference;
240begin
241  lbRefList.items.clear;
242  lvStringlist.Items.Clear;
243  lvStringlist.Items.Count:=0;
244
245  if stringfiller<>nil then
246  begin
247    stringfiller.Terminate;
248    stringfiller.WaitFor;
249    stringfiller.free;
250    stringfiller:=nil;
251  end;
252
253  if stringlist<>nil then
254  begin
255    for i:=0 to stringlist.Count-1 do
256    begin
257      x:=TStringReference(stringlist.Objects[i]);
258      x.free;
259      stringlist.Objects[i]:=nil;
260    end;
261    freeandnil(stringlist);
262  end;
263
264
265end;
266
267procedure TfrmReferencedStrings.lvStringlistDblClick(Sender: TObject);
268var
269  x: TStringReference;
270begin
271  if lvstringlist.Selected<>nil then
272  begin
273    x:=TStringReference(stringlist.Objects[lvstringlist.Selected.Index]);
274    memorybrowser.memoryaddress:=x.address;
275    memorybrowser.RefreshMB;
276  end;
277end;
278
279procedure TfrmReferencedStrings.lvStringlistSelectItem(Sender: TObject;
280  Item: TListItem; Selected: Boolean);
281var i: integer;
282    x: TStringReference;
283begin
284  if selected then
285  begin
286    lbreflist.Clear;
287    x:=TStringReference(stringlist.Objects[item.Index]);
288    for i:=0 to length(x.references)-1 do
289      lbreflist.Items.Add(inttohex(x.references[i],8));
290  end;
291end;
292
293procedure TfrmReferencedStrings.lbReflistDblClick(Sender: TObject);
294begin
295  if lbreflist.ItemIndex<>-1 then
296    memorybrowser.disassemblerview.SelectedAddress:=strtoint('$'+lbreflist.Items[lbreflist.ItemIndex]);
297end;
298
299procedure TfrmReferencedStrings.Find1Click(Sender: TObject);
300begin
301  finddialog1.Execute;
302end;
303
304procedure TfrmReferencedStrings.FindNext1Click(Sender: TObject);
305begin
306  if finddialog1.FindText='' then
307    finddialog1.Execute
308  else
309    FindDialog1Find(finddialog1); //next scan
310end;
311
312procedure TfrmReferencedStrings.FindDialog1Find(Sender: TObject);
313var i,startindex: integer;
314begin
315  startindex:=lvstringlist.ItemIndex;
316  if startindex=-1 then startindex:=0;
317
318  if frFindNext in finddialog1.Options then //start from next index
319    inc(startindex);
320
321  for i:=startindex to lvStringlist.Items.Count-1 do
322  begin
323    if pos(lowercase(finddialog1.FindText), lowercase(lvstringlist.Items[i].SubItems[1]))>0 then
324    begin
325      lvstringlist.Items[i].Selected:=true;
326      lvstringlist.ItemIndex:=i;
327      lvstringlist.Items[i].MakeVisible(false);
328      exit;
329    end;
330  end;
331
332  beep; //not found
333end;
334
335end.
Note: See TracBrowser for help on using the browser.