unit frmEnumerateDLLsUnit; {$MODE Delphi} interface uses windows, LCLIntf, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,CEFuncProc,imagehlp, StdCtrls, ComCtrls, ExtCtrls, ActnList, Menus, LResources,symbolhandler, FindDialogFix, commonTypeDefs; type tenumthread=class(tthread) public symbolcount: integer; moduletext: string; symbolname: array [1..25] of string; x: TTreenode; procedure AddModule; procedure AddSymbol; procedure Done; procedure execute; override; end; type { TfrmEnumerateDLLs } TfrmEnumerateDLLs = class(TForm) Label2: TLabel; TreeView1: TTreeView; Panel1: TPanel; Button1: TButton; Button2: TButton; FindDialog1: TFindDialog; ActionList1: TActionList; Find: TAction; pmSymbol: TPopupMenu; Find1: TMenuItem; procedure Button1Click(Sender: TObject); procedure FindDialog1Close(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure FormShow(Sender: TObject); procedure TreeView1DblClick(Sender: TObject); procedure Button2Click(Sender: TObject); procedure FindExecute(Sender: TObject); procedure FindDialog1Find(Sender: TObject); private { Private declarations } enumthread: tenumthread; findpos: tpoint; public { Public declarations } procedure Enumerate; end; var frmEnumerateDLLs: TfrmEnumerateDLLs; implementation uses MemoryBrowserFormUnit, Parsers; resourcestring rsNothingFound = 'nothing found'; var canceled: boolean; //global var for only this unit procedure tenumthread.Done; begin if frmEnumerateDLLs<>nil then begin frmEnumerateDLLs.button2.visible:=false; if x<>nil then frmEnumerateDLLs.treeview1.EndUpdate; end else canceled:=true; end; procedure tenumthread.addsymbol; var i: integer; begin if frmEnumerateDLLs<>nil then begin for i:=1 to symbolcount do frmEnumerateDLLs.treeview1.items.addchild(x,symbolname[i]); end else canceled:=true; symbolcount:=0; end; procedure tenumthread.AddModule; begin if frmEnumerateDLLs<>nil then begin if x<>nil then frmEnumerateDLLs.treeview1.EndUpdate; x:=frmEnumerateDLLs.treeview1.items.add(nil,moduletext); frmEnumerateDLLs.treeview1.BeginUpdate; end else canceled:=true; end; procedure tenumthread.execute; var ml: Tstringlist; i,j: integer; mi: TModuleInfo; sl: Tstringlist; begin freeonterminate:=true; symbolcount:=0; Priority:=tpLower; // symhandler.waitforsymbolsloaded; if not canceled then begin sl:=tstringlist.create; ml:=tstringlist.create; try symhandler.getModuleList(ml); for i:=0 to ml.count-1 do begin if symhandler.getmodulebyaddress(ptruint(ml.Objects[i]), mi) then begin moduletext:=IntToHex(mi.baseaddress,8)+' - '+mi.modulename; Synchronize(addmodule); end; sl.clear; symhandler.GetSymbolList(mi.baseaddress, sl); for j:=0 to sl.count-1 do begin inc(symbolcount); symbolname[symbolcount]:=IntToHex(ptruint(sl.objects[j]),8)+' - '+sl[j]; if canceled then break; if symbolcount=25 then Synchronize(addsymbol); end; if canceled then break; if symbolcount>0 then synchronize(addsymbol); end; finally ml.free; sl.free; end; end; if symbolcount>0 then synchronize(addsymbol); synchronize(done); end; procedure TfrmEnumerateDLLs.Enumerate; var crashcount: integer; begin treeview1.items.Clear; canceled:=false; enumthread:=tenumthread.create(false); frmEnumerateDLLs.TreeView1.SortType:=stText; end; procedure TfrmEnumerateDLLs.Button1Click(Sender: TObject); begin close; end; procedure TfrmEnumerateDLLs.FindDialog1Close(Sender: TObject); begin findpos.x:=finddialog1.left; findpos.y:=finddialog1.top; end; procedure TfrmEnumerateDLLs.FormClose(Sender: TObject; var Action: TCloseAction); begin canceled:=true; action:=cafree; frmEnumerateDLLS:=nil; end; procedure TfrmEnumerateDLLs.FormCreate(Sender: TObject); var x: TWindowPosArray; begin LoadFormPosition(self,x); if length(x)>=2 then begin findpos.x:=x[0]; findpos.y:=x[1]; end; end; procedure TfrmEnumerateDLLs.FormDestroy(Sender: TObject); var x: TWindowPosArray; begin setlength(x,2); x[0]:=findpos.x; x[1]:=findpos.y; SaveFormPosition(self,x); end; procedure TfrmEnumerateDLLs.FormShow(Sender: TObject); begin button2.autosize:=true; button2.height:=canvas.TextHeight(button2.caption)+4; treeview1.font.height:=GetFontData(font.Handle).Height; end; procedure TfrmEnumerateDLLs.TreeView1DblClick(Sender: TObject); var address: ptrUint; i: integer; s: string; begin if Treeview1.Selected<>nil then begin if treeview1.Selected.Level=1 then begin //showmessage('dblclick: '+treeview1.Selected.Text); s:=''; for i:=1 to length(treeview1.Selected.Text)-1 do if not (treeview1.Selected.Text[i] in ['0'..'9','a'..'f','A'..'F'] ) then begin s:=copy(treeview1.Selected.Text,1,i-1); break; end; if s='' then //should never happen s:=treeview1.Selected.Text; address:=StrToQWordEx('$'+s); { val('$'+s,address,i); fpc 2.4.1 doesn't handle this correctly } //showmessage('s='+s+' address='+inttohex(address,8)); memorybrowser.disassemblerview.SelectedAddress:=address; end; end; end; procedure TfrmEnumerateDLLs.Button2Click(Sender: TObject); begin canceled:=true; end; procedure TfrmEnumerateDLLs.FindExecute(Sender: TObject); var p: TPoint; begin finddialog1.Execute; if (findpos.x<>0) or (findpos.y<>0) then begin finddialog1.left:=findpos.x; finddialog1.top:=findpos.y; end else begin finddialog1.Left:=left+((width div 2)-(finddialog1.width div 2)); finddialog1.Top:=top+((height div 2)-(finddialog1.height div 2)); end; end; procedure TfrmEnumerateDLLs.FindDialog1Find(Sender: TObject); var current: ttreenode; i,j: integer; begin if treeview1.Selected=nil then current:=treeview1.Items.GetFirstNode else current:=treeview1.Selected; i:=current.AbsoluteIndex; if frFindNext in finddialog1.Options then inc(i); for j:=i to treeview1.Items.Count-1 do begin if pos(uppercase(finddialog1.FindText),uppercase(treeview1.Items[j].Text))>0 then begin treeview1.Selected:=treeview1.Items[j]; exit; end; end; showmessage(rsNothingFound); end; initialization {$i frmEnumerateDLLsUnit.lrs} end.