1 unit reMainUnit; 2 3 {$mode objfpc}{$H+} 4 5 interface 6 7 uses 8 SysUtils, resource, LazUTF8, SynEdit, Forms, Controls, Dialogs, ComCtrls, 9 ActnList, Menus, ExtCtrls, Grids, bitmapresource, versionresource, 10 groupiconresource, Classes; 11 12 type 13 14 { TreMainForm } 15 16 TreMainForm = class(TForm) 17 fileSave: TAction; 18 HeaderControl1: THeaderControl; 19 hlpAbout: TAction; 20 fileExit: TAction; 21 fileOpen: TAction; 22 ActionList1: TActionList; 23 Image1: TImage; 24 ImageList1: TImageList; 25 MainMenu1: TMainMenu; 26 MenuItem1: TMenuItem; 27 MenuItem2: TMenuItem; 28 MenuItem3: TMenuItem; 29 MenuItem4: TMenuItem; 30 MenuItem5: TMenuItem; 31 MenuItem6: TMenuItem; 32 OpenDialog1: TOpenDialog; 33 PageControl1: TPageControl; 34 Splitter1: TSplitter; 35 StatusBar1: TStatusBar; 36 StringGrid1: TStringGrid; 37 SynEdit1: TSynEdit; 38 tabBinary: TTabSheet; 39 tabString: TTabSheet; 40 tabImage: TTabSheet; 41 ToolBar1: TToolBar; 42 ToolButton1: TToolButton; 43 ToolButton2: TToolButton; 44 ToolButton3: TToolButton; 45 ToolButton4: TToolButton; 46 TreeView1: TTreeView; 47 procedure fileExitExecute(Sender: TObject); 48 procedure fileOpenExecute(Sender: TObject); 49 procedure FormCreate(Sender: TObject); 50 procedure FormDestroy(Sender: TObject); 51 procedure HeaderControl1SectionResize(HeaderControl: TCustomHeaderControl; 52 Section: THeaderSection); 53 procedure hlpAboutExecute(Sender: TObject); 54 procedure Splitter1ChangeBounds(Sender: TObject); 55 procedure TreeView1SelectionChanged(Sender: TObject); 56 private 57 Res:TResources; 58 procedure ClearDisplay; 59 procedure LoadVersionResource(V:TVersionResource); 60 procedure LoadBitmapResource(B:TBitmapResource); 61 procedure LoadGroupIconResource(G:TGroupIconResource); 62 procedure LoadResourceAsBinary(R: TAbstractResource); 63 public 64 procedure OpenFile(const AFileName:string); 65 end; 66 67 var 68 reMainForm: TreMainForm; 69 70 implementation 71 72 {$R *.lfm} 73 74 uses 75 winpeimagereader, elfreader, resreader, reAboutUnit, reConstsUnit; 76 77 { TreMainForm } 78 79 procedure TreMainForm.fileExitExecute(Sender: TObject); 80 begin 81 Close; 82 end; 83 84 procedure TreMainForm.fileOpenExecute(Sender: TObject); 85 begin 86 if OpenDialog1.Execute then 87 OpenFile(UTF8ToSys(OpenDialog1.FileName)); 88 end; 89 90 procedure TreMainForm.FormCreate(Sender: TObject); 91 begin 92 Caption:=sResourceExplorer; 93 94 fileSave.Caption:=sSaveResource; //'Save resource...' 95 hlpAbout.Caption:=sAbout; //'About...' 96 fileExit.Caption:=sExit; //'Exit' 97 fileOpen.Caption:=sOpen; //'Open...' 98 MenuItem1.Caption:=sFile; 99 MenuItem2.Caption:=sHelp; 100 tabString.Caption:=sStrings; 101 tabImage.Caption:=sImage; 102 HeaderControl1.Sections[0].Text := sResources; 103 104 {$IFDEF Windows} 105 OpenDialog1.Filter := sAllFilesExcutableFilesExeExeDLLDllDll; 106 {$ELSE} 107 OpenDialog1.Filter := sAllFilesSharedLibSoSo; 108 {$ENDIF} 109 Splitter1ChangeBounds(nil); 110 SynEdit1.Gutter.Visible := False; 111 ClearDisplay; 112 end; 113 114 procedure TreMainForm.FormDestroy(Sender: TObject); 115 begin 116 if Assigned(Res) then Res.Free; 117 end; 118 119 procedure TreMainForm.HeaderControl1SectionResize( 120 HeaderControl: TCustomHeaderControl; Section: THeaderSection); 121 begin 122 TreeView1.Width:=HeaderControl1.Sections[0].Width; 123 HeaderControl1.Sections[1].Width:=Width - TreeView1.Width; 124 end; 125 126 procedure TreMainForm.hlpAboutExecute(Sender: TObject); 127 begin 128 reAboutForm:=TreAboutForm.Create(Application); 129 reAboutForm.ShowModal; 130 reAboutForm.Free; 131 end; 132 133 procedure TreMainForm.Splitter1ChangeBounds(Sender: TObject); 134 begin 135 HeaderControl1.Sections[0].Width:=TreeView1.Width; 136 HeaderControl1.Sections[1].Width:=Width - TreeView1.Width; 137 end; 138 139 procedure TreMainForm.TreeView1SelectionChanged(Sender: TObject); 140 var 141 ResItem:TAbstractResource; 142 begin 143 if Assigned(TreeView1.Selected) then ClearDisplay; 144 if Assigned(TreeView1.Selected) and Assigned(TreeView1.Selected.Data) then 145 begin 146 ResItem:=TAbstractResource(TreeView1.Selected.Data); 147 HeaderControl1.Sections[1].Text:=ResItem.ClassName + ' : ' + ResItem.Name.Name; 148 if ResItem is TVersionResource then 149 LoadVersionResource(ResItem as TVersionResource) 150 else 151 if ResItem is TBitmapResource then 152 LoadBitmapResource(ResItem as TBitmapResource) 153 else 154 if ResItem is TGroupIconResource then 155 LoadGroupIconResource(ResItem as TGroupIconResource) 156 else 157 LoadResourceAsBinary(ResItem); 158 end; 159 end; 160 161 162 procedure TreMainForm.ClearDisplay; 163 begin 164 StringGrid1.Clean; 165 StringGrid1.Visible := False; 166 Image1.Picture.Clear; 167 SynEdit1.Lines.Clear; 168 end; 169 170 procedure TreMainForm.LoadVersionResource(V: TVersionResource); 171 var 172 i,j, k:integer; 173 begin 174 PageControl1.ActivePage:=tabString; 175 StringGrid1.Visible := True; 176 k:=0; 177 StringGrid1.RowCount:=0; 178 StringGrid1.ColCount:=2; 179 for i:=0 to V.StringFileInfo.Count-1 do 180 begin 181 for j:=0 to V.StringFileInfo[i].Count-1 do 182 begin 183 StringGrid1.RowCount:=StringGrid1.RowCount + 1; 184 StringGrid1.Cells[0, k]:=SysToUTF8(V.StringFileInfo[i].Keys[j]); 185 StringGrid1.Cells[1, k]:=SysToUTF8(V.StringFileInfo[i].ValuesByIndex[j]); 186 inc(k); 187 end; 188 end; 189 end; 190 191 procedure TreMainForm.LoadBitmapResource(B: TBitmapResource); 192 begin 193 PageControl1.ActivePage:=tabImage; 194 B.BitmapData.Position:=0; 195 Image1.Picture.Bitmap.LoadFromStream(B.BitmapData); 196 // 197 end; 198 199 procedure TreMainForm.LoadGroupIconResource(G: TGroupIconResource); 200 begin 201 //ToDo: implement proper method to display 202 LoadResourceAsBinary(G); 203 end; 204 205 procedure TreMainForm.LoadResourceAsBinary(R: TAbstractResource); 206 var 207 Offset, Size, BytesRead: Int64; 208 Buf: Array[0..15] of Byte; 209 Line, BinLine, AscLine: ShortString; 210 i: Integer; 211 begin 212 PageControl1.ActivePage:=tabBinary; 213 //writeln('TreMainForm.LoadResourceAsBinary'); 214 //writeln(' ClassName = ',R.ClassName); 215 //writeln(' DataSize = ',R.DataSize); 216 //writeln(' R.RawData.Size = ',R.RawData.Size); 217 //writeln(' DataOffset = ',R.DataOffset); 218 //writeln(' DataVersion = ',R.DataVersion); 219 SynEdit1.Lines.BeginUpdate; 220 try 221 Offset := 0; 222 R.RawData.Position := 0; 223 Size := R.RawData.Size; 224 while (Offset < Size) do 225 begin 226 FillChar(Buf{%H-}, SizeOf(Buf), #0); 227 BytesRead := R.RawData.Read(Buf[0], SizeOf(Buf)); 228 //writeln(' BytesRead = ',BytesRead); 229 Line := ''; 230 BinLine := ''; 231 Ascline := ''; 232 for i := 0 to BytesRead - 1 do 233 begin 234 BinLine := BinLine + IntToHex(Buf[i],2) + #32; 235 if (Buf[i] in [32..127]) then 236 AscLine := AscLine + Char(Buf[i]) 237 else 238 AscLine := AscLine + #32; 239 end; 240 for i := (BytesRead + 1) to SizeOf(Buf) do 241 begin 242 BinLine := BinLine + ' '; 243 AscLine := AscLine + ' '; 244 end; 245 Line := IntToHex(Offset, 8) + #32; 246 Line := Line + BinLine + #32 + AscLine + LineEnding; 247 //writeln(' Line = ',Line); 248 SynEdit1.Lines.Add(Line); 249 Inc(Offset, SizeOf(Buf)); 250 end; 251 finally 252 SynEdit1.Lines.EndUpdate; 253 end; 254 end; 255 256 procedure TreMainForm.OpenFile(const AFileName: string); 257 var 258 Ext:string; 259 Reader:TAbstractResourceReader; 260 i:integer; 261 Root, ResNode:TTreeNode; 262 begin 263 if not FileExists(AFileName) then exit; 264 Ext:=LowerCase(ExtractFileExt(AFileName)); 265 if (Ext = '.exe') or (Ext = '.dll') then 266 Reader:=TWinPEImageResourceReader.Create 267 else 268 if (Ext = '.res')then 269 Reader:=TResResourceReader.Create 270 else 271 if (Ext = '.o')then 272 Reader:=TResResourceReader.Create 273 else 274 if (Ext = '')then 275 Reader:=TElfResourceReader.Create; 276 277 TreeView1.Items.Clear; 278 ClearDisplay; 279 if Assigned(Res) then 280 FreeAndNil(Res); 281 282 if not Assigned(Reader) then exit; 283 284 Res:=TResources.Create; 285 try 286 Res.LoadFromFile(AFileName, Reader); 287 288 for i:=0 to Res.Count-1 do 289 begin 290 Root:=TreeView1.Items.FindTopLvlNode(Res[i].ClassName); 291 if not Assigned(Root) then 292 Root:=TreeView1.Items.AddChild(nil, Res[i].ClassName); 293 ResNode:=TreeView1.Items.AddChild(Root, Res[i].Name.Name); 294 ResNode.Data:=Res[i]; 295 end; 296 finally 297 Reader.Free; 298 end; 299 300 StatusBar1.SimpleText:=AFileName; 301 end; 302 303 end. 304 305