lazarus/examples/lazresexplorer/remainunit.pas

305 lines
7.9 KiB
ObjectPascal

unit reMainUnit;
{$mode objfpc}{$H+}
interface
uses
SysUtils, resource, LazUTF8, SynEdit, Forms, Controls, Dialogs, ComCtrls,
ActnList, Menus, ExtCtrls, Grids, bitmapresource, versionresource,
groupiconresource, Classes;
type
{ TreMainForm }
TreMainForm = class(TForm)
fileSave: TAction;
HeaderControl1: THeaderControl;
hlpAbout: TAction;
fileExit: TAction;
fileOpen: TAction;
ActionList1: TActionList;
Image1: TImage;
ImageList1: TImageList;
MainMenu1: TMainMenu;
MenuItem1: TMenuItem;
MenuItem2: TMenuItem;
MenuItem3: TMenuItem;
MenuItem4: TMenuItem;
MenuItem5: TMenuItem;
MenuItem6: TMenuItem;
OpenDialog1: TOpenDialog;
PageControl1: TPageControl;
Splitter1: TSplitter;
StatusBar1: TStatusBar;
StringGrid1: TStringGrid;
SynEdit1: TSynEdit;
tabBinary: TTabSheet;
tabString: TTabSheet;
tabImage: TTabSheet;
ToolBar1: TToolBar;
ToolButton1: TToolButton;
ToolButton2: TToolButton;
ToolButton3: TToolButton;
ToolButton4: TToolButton;
TreeView1: TTreeView;
procedure fileExitExecute(Sender: TObject);
procedure fileOpenExecute(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure HeaderControl1SectionResize(HeaderControl: TCustomHeaderControl;
Section: THeaderSection);
procedure hlpAboutExecute(Sender: TObject);
procedure Splitter1ChangeBounds(Sender: TObject);
procedure TreeView1SelectionChanged(Sender: TObject);
private
Res:TResources;
procedure ClearDisplay;
procedure LoadVersionResource(V:TVersionResource);
procedure LoadBitmapResource(B:TBitmapResource);
procedure LoadGroupIconResource(G:TGroupIconResource);
procedure LoadResourceAsBinary(R: TAbstractResource);
public
procedure OpenFile(const AFileName:string);
end;
var
reMainForm: TreMainForm;
implementation
{$R *.lfm}
uses
winpeimagereader, elfreader, resreader, reAboutUnit, reConstsUnit;
{ TreMainForm }
procedure TreMainForm.fileExitExecute(Sender: TObject);
begin
Close;
end;
procedure TreMainForm.fileOpenExecute(Sender: TObject);
begin
if OpenDialog1.Execute then
OpenFile(UTF8ToSys(OpenDialog1.FileName));
end;
procedure TreMainForm.FormCreate(Sender: TObject);
begin
Caption:=sResourceExplorer;
fileSave.Caption:=sSaveResource; //'Save resource...'
hlpAbout.Caption:=sAbout; //'About...'
fileExit.Caption:=sExit; //'Exit'
fileOpen.Caption:=sOpen; //'Open...'
MenuItem1.Caption:=sFile;
MenuItem2.Caption:=sHelp;
tabString.Caption:=sStrings;
tabImage.Caption:=sImage;
HeaderControl1.Sections[0].Text := sResources;
{$IFDEF Windows}
OpenDialog1.Filter := sAllFilesExcutableFilesExeExeDLLDllDll;
{$ELSE}
OpenDialog1.Filter := sAllFilesSharedLibSoSo;
{$ENDIF}
Splitter1ChangeBounds(nil);
SynEdit1.Gutter.Visible := False;
ClearDisplay;
end;
procedure TreMainForm.FormDestroy(Sender: TObject);
begin
if Assigned(Res) then Res.Free;
end;
procedure TreMainForm.HeaderControl1SectionResize(
HeaderControl: TCustomHeaderControl; Section: THeaderSection);
begin
TreeView1.Width:=HeaderControl1.Sections[0].Width;
HeaderControl1.Sections[1].Width:=Width - TreeView1.Width;
end;
procedure TreMainForm.hlpAboutExecute(Sender: TObject);
begin
reAboutForm:=TreAboutForm.Create(Application);
reAboutForm.ShowModal;
reAboutForm.Free;
end;
procedure TreMainForm.Splitter1ChangeBounds(Sender: TObject);
begin
HeaderControl1.Sections[0].Width:=TreeView1.Width;
HeaderControl1.Sections[1].Width:=Width - TreeView1.Width;
end;
procedure TreMainForm.TreeView1SelectionChanged(Sender: TObject);
var
ResItem:TAbstractResource;
begin
if Assigned(TreeView1.Selected) then ClearDisplay;
if Assigned(TreeView1.Selected) and Assigned(TreeView1.Selected.Data) then
begin
ResItem:=TAbstractResource(TreeView1.Selected.Data);
HeaderControl1.Sections[1].Text:=ResItem.ClassName + ' : ' + ResItem.Name.Name;
if ResItem is TVersionResource then
LoadVersionResource(ResItem as TVersionResource)
else
if ResItem is TBitmapResource then
LoadBitmapResource(ResItem as TBitmapResource)
else
if ResItem is TGroupIconResource then
LoadGroupIconResource(ResItem as TGroupIconResource)
else
LoadResourceAsBinary(ResItem);
end;
end;
procedure TreMainForm.ClearDisplay;
begin
StringGrid1.Clean;
StringGrid1.Visible := False;
Image1.Picture.Clear;
SynEdit1.Lines.Clear;
end;
procedure TreMainForm.LoadVersionResource(V: TVersionResource);
var
i,j, k:integer;
begin
PageControl1.ActivePage:=tabString;
StringGrid1.Visible := True;
k:=0;
StringGrid1.RowCount:=0;
StringGrid1.ColCount:=2;
for i:=0 to V.StringFileInfo.Count-1 do
begin
for j:=0 to V.StringFileInfo[i].Count-1 do
begin
StringGrid1.RowCount:=StringGrid1.RowCount + 1;
StringGrid1.Cells[0, k]:=SysToUTF8(V.StringFileInfo[i].Keys[j]);
StringGrid1.Cells[1, k]:=SysToUTF8(V.StringFileInfo[i].ValuesByIndex[j]);
inc(k);
end;
end;
end;
procedure TreMainForm.LoadBitmapResource(B: TBitmapResource);
begin
PageControl1.ActivePage:=tabImage;
B.BitmapData.Position:=0;
Image1.Picture.Bitmap.LoadFromStream(B.BitmapData);
//
end;
procedure TreMainForm.LoadGroupIconResource(G: TGroupIconResource);
begin
//ToDo: implement proper method to display
LoadResourceAsBinary(G);
end;
procedure TreMainForm.LoadResourceAsBinary(R: TAbstractResource);
var
Offset, Size, BytesRead: Int64;
Buf: Array[0..15] of Byte;
Line, BinLine, AscLine: ShortString;
i: Integer;
begin
PageControl1.ActivePage:=tabBinary;
//writeln('TreMainForm.LoadResourceAsBinary');
//writeln(' ClassName = ',R.ClassName);
//writeln(' DataSize = ',R.DataSize);
//writeln(' R.RawData.Size = ',R.RawData.Size);
//writeln(' DataOffset = ',R.DataOffset);
//writeln(' DataVersion = ',R.DataVersion);
SynEdit1.Lines.BeginUpdate;
try
Offset := 0;
R.RawData.Position := 0;
Size := R.RawData.Size;
while (Offset < Size) do
begin
FillChar(Buf{%H-}, SizeOf(Buf), #0);
BytesRead := R.RawData.Read(Buf[0], SizeOf(Buf));
//writeln(' BytesRead = ',BytesRead);
Line := '';
BinLine := '';
Ascline := '';
for i := 0 to BytesRead - 1 do
begin
BinLine := BinLine + IntToHex(Buf[i],2) + #32;
if (Buf[i] in [32..127]) then
AscLine := AscLine + Char(Buf[i])
else
AscLine := AscLine + #32;
end;
for i := (BytesRead + 1) to SizeOf(Buf) do
begin
BinLine := BinLine + ' ';
AscLine := AscLine + ' ';
end;
Line := IntToHex(Offset, 8) + #32;
Line := Line + BinLine + #32 + AscLine + LineEnding;
//writeln(' Line = ',Line);
SynEdit1.Lines.Add(Line);
Inc(Offset, SizeOf(Buf));
end;
finally
SynEdit1.Lines.EndUpdate;
end;
end;
procedure TreMainForm.OpenFile(const AFileName: string);
var
Ext:string;
Reader:TAbstractResourceReader;
i:integer;
Root, ResNode:TTreeNode;
begin
if not FileExists(AFileName) then exit;
Ext:=LowerCase(ExtractFileExt(AFileName));
if (Ext = '.exe') or (Ext = '.dll') then
Reader:=TWinPEImageResourceReader.Create
else
if (Ext = '.res')then
Reader:=TResResourceReader.Create
else
if (Ext = '.o')then
Reader:=TResResourceReader.Create
else
if (Ext = '')then
Reader:=TElfResourceReader.Create;
TreeView1.Items.Clear;
ClearDisplay;
if Assigned(Res) then
FreeAndNil(Res);
if not Assigned(Reader) then exit;
Res:=TResources.Create;
try
Res.LoadFromFile(AFileName, Reader);
for i:=0 to Res.Count-1 do
begin
Root:=TreeView1.Items.FindTopLvlNode(Res[i].ClassName);
if not Assigned(Root) then
Root:=TreeView1.Items.AddChild(nil, Res[i].ClassName);
ResNode:=TreeView1.Items.AddChild(Root, Res[i].Name.Name);
ResNode.Data:=Res[i];
end;
finally
Reader.Free;
end;
StatusBar1.SimpleText:=AFileName;
end;
end.