123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399 |
- program restool;
- {$R program.res}
- uses
- custapp, sysutils, classes, resource, elfreader, resreader, coffreader, machoreader, dfmreader,
- bitmapresource, stringtableresource, versionresource, groupiconresource, groupcursorresource,
- acceleratorsresource, groupresource;
- Type
- TRunMode = (rmList,rmExtract);
- { TRestool }
- TRestool = Class(TCustomApplication)
- private
- FRunMode : TRunMode;
- FResfile : TResources;
- FinputFile : String;
- FDestFile : String;
- FResName,FResType : String;
- FResIndex : integer;
- FStructured : Boolean;
- procedure DumpAllResources(var aDest: Text);
- procedure DumpResource(var aDest: Text; Res: TAbstractResource; Idx: integer; const Prefix: String='');
- function ProcessOptions: Boolean;
- procedure Usage(const aErr: String);
- procedure DumpOwnedResource(var aDest: Text; aOwner: TAbstractResource; const Prefix: String);
- procedure WriteResource(Res: TAbstractResource; const aDestFile: String);
- Protected
- procedure doRun; override;
- procedure dumpresourcefile(const aFileName: String; var aDest: Text);
- procedure ExtractResource(const aDestFile: String; aIdx: Integer);
- procedure ExtractResource(const aDestFile, aType, aName: String);
- public
- constructor Create(aOwner : TComponent); override;
- destructor destroy; override;
- class function restypename(aID: Integer; AddNumeric: Boolean): string;
- class function KnownTypeNameToID(aType : String) : Integer;
- end;
- constructor TRestool.Create(aOwner: TComponent);
- begin
- inherited Create(aOwner);
- FResfile:=TResources.Create;
- end;
- destructor TRestool.destroy;
- begin
- FreeAndNil(FResfile);
- inherited destroy;
- end;
- class function TRestool.restypename(aID : Integer; AddNumeric : Boolean) : string;
- begin
- case aID of
- RT_CURSOR : Result:='RT_CURSOR'; //Hardware-dependent cursor resource.
- RT_BITMAP : Result:='RT_BITMAP'; //Bitmap resource.
- RT_ICON : Result:='RT_ICON'; //Hardware-dependent icon resource.
- RT_MENU : Result:='RT_MENU'; //Menu resource.
- RT_DIALOG : Result:='RT_DIALOG'; //Dialog box.
- RT_STRING : Result:='RT_STRING'; //String-table entry.
- RT_FONTDIR : Result:='RT_FONTDIR'; //Font directory resource.
- RT_FONT : Result:='RT_FONT'; //Font resource.
- RT_ACCELERATOR : Result:='RT_ACCELERATOR'; //Accelerator table.
- RT_RCDATA : Result:='RT_RCDATA'; //Application-defined resource (raw data).
- RT_MESSAGETABLE : Result:='RT_MESSAGETABLE'; //Message-table entry.
- RT_GROUP_CURSOR : Result:='RT_GROUP_CURSOR'; //Hardware-independent cursor resource.
- RT_GROUP_ICON : Result:='RT_GROUP_ICON'; //Hardware-independent icon resource.
- RT_VERSION : Result:='RT_VERSION'; //Version resource.
- RT_DLGINCLUDE : Result:='RT_DLGINCLUDE'; //Never present in compiled form
- RT_PLUGPLAY : Result:='RT_PLUGPLAY'; //Plug and Play resource.
- RT_VXD : Result:='RT_VXD'; //VXD.
- RT_ANICURSOR : Result:='RT_ANICURSOR'; //Animated cursor.
- RT_ANIICON : Result:='RT_ANIICON'; //Animated icon.
- RT_HTML : Result:='RT_HTML'; //HTML.
- RT_MANIFEST : Result:='RT_MANIFEST'; //Microsoft Windows XP: Side-by-Side Assembly XML Manifest.
- RT_DLGINIT : Result:='RT_DLGINIT'; //Never present in compiled form
- else
- Result:='';
- end;
- if Result='' then
- Result:=IntToStr(aID)
- else if AddNumeric then
- Result:=Result+' ('+IntToStr(aId)+')';
- end;
- class function TRestool.KnownTypeNameToID(aType: String): Integer;
- begin
- case aType of
- 'RT_CURSOR' : Result:=RT_CURSOR; //Hardware-dependent cursor resource.
- 'RT_BITMAP' : Result:=RT_BITMAP; //Bitmap resource.
- 'RT_ICON' : Result:=RT_ICON; //Hardware-dependent icon resource.
- 'RT_MENU' : Result:=RT_MENU; //Menu resource.
- 'RT_DIALOG' : Result:=RT_DIALOG; //Dialog box.
- 'RT_STRING' : Result:=RT_STRING; //String-table entry.
- 'RT_FONTDIR' : Result:=RT_FONTDIR; //Font directory resource.
- 'RT_FONT' : Result:=RT_FONT; //Font resource.
- 'RT_ACCELERATOR' : Result:=RT_ACCELERATOR; //Accelerator table.
- 'RT_RCDATA' : Result:=RT_RCDATA; //Application-defined resource (raw data).
- 'RT_MESSAGETABLE' : Result:=RT_MESSAGETABLE; //Message-table entry.
- 'RT_GROUP_CURSOR' : Result:=RT_GROUP_CURSOR; //Hardware-independent cursor resource.
- 'RT_GROUP_ICON' : Result:=RT_GROUP_ICON; //Hardware-independent icon resource.
- 'RT_VERSION' : Result:=RT_VERSION; //Version resource.
- 'RT_DLGINCLUDE' : Result:=RT_DLGINCLUDE; //Never present in compiled form
- 'RT_PLUGPLAY' : Result:=RT_PLUGPLAY; //Plug and Play resource.
- 'RT_VXD' : Result:=RT_VXD; //VXD.
- 'RT_ANICURSOR' : Result:=RT_ANICURSOR; //Animated cursor.
- 'RT_ANIICON' : Result:=RT_ANIICON; //Animated icon.
- 'RT_HTML' : Result:=RT_HTML; //HTML.
- 'RT_MANIFEST' : Result:=RT_MANIFEST; //Microsoft Windows XP: Side-by-Side Assembly XML Manifest.
- 'RT_DLGINIT' : Result:=RT_DLGINIT; //Never present in compiled form
- else
- Result:=-1;
- end;
- end;
- procedure TRestool.DumpResource(var aDest : Text; Res : TAbstractResource; Idx : integer; const Prefix : String = '');
- var
- aType,aName : string;
- begin
- aName:=Res.Name.Name;
- if res.name.DescType=dtID then
- aName:='#'+aName;
- aType:=ResTypeName(res._Type.ID,True);
- Writeln(aDest,Prefix,Idx:3,' : Type: ',aType,' name: ',aName);
- end;
- procedure TRestool.DumpOwnedResource(var aDest : Text; aOwner : TAbstractResource; const Prefix : String);
- Var
- res : TAbstractResource;
- i : Integer;
- begin
- For I:=0 to FResFile.Count-1 do
- begin
- Res:=FResFile.Items[i];
- if Res.Owner=aOwner then
- begin
- DumpResource(aDest,Res,I,Prefix);
- if Res is TGroupResource then
- DumpOwnedResource(aDest,Res,' '+Prefix);
- end;
- end;
- end;
- procedure TRestool.DumpAllResources(var aDest : Text);
- Var
- res : TAbstractResource;
- i : Integer;
- begin
- For I:=0 to FResFile.Count-1 do
- begin
- Res:=FResFile.Items[i];
- DumpResource(aDest,Res,I);
- end;
- end;
- procedure TRestool.dumpresourcefile(const aFileName: String; var aDest : Text);
- begin
- FResFile.LoadFromFile(aFileName);
- Writeln(aDest,'File ',aFileName,' contains ',FResFile.Count,' resources:');
- if FStructured then
- DumpOwnedResource(aDest,Nil,'')
- else
- DumpAllResources(aDest);
- end;
- procedure TRestool.WriteResource(Res : TAbstractResource; const aDestFile : String);
- var
- aCount : Int64;
- S : TStream;
- begin
- if Res is TGroupCursorResource then
- S:=TGroupIconResource(Res).ItemData
- else if Res is TGroupIconResource then
- S:=TGroupIconResource(Res).ItemData
- else if Res is TBitmapResource then
- S:=TBitmapResource(Res).BitmapData
- else
- S:=Res.RawData;
- With TFileStream.Create(aDestFile,fmCreate) do
- try
- aCount:=CopyFrom(S,S.Size);
- Writeln(stdErr,'Write ',aCount,' bytes from resource data to file: ',aDestFile);
- finally
- Free;
- end;
- end;
- function TRestool.ProcessOptions: Boolean;
- const
- Short = 'h:i:n:t:m:xlo:s';
- Long : Array of string = ('help','index:','name:','type:','mode:','extract','output:','list','structured');
- var
- RM,Idx,Err : String;
- S : Array of string;
- begin
- Result:=False;
- Err:=CheckOptions(Short,Long);
- if (Err<>'') or HasOption('h','help') then
- begin
- Usage(Err);
- Exit;
- end;
- S:=GetNonOptions(Short,long);
- FDestFile:=GetOptionValue('o','output');
- FStructured:=HasOption('s','structured');
- if Length(S)>0 then
- FinputFile:=S[0]
- else if Length(S)>1 then
- FDestFile:=S[1];
- if HasOption('x','extract') then
- FRunMode:=rmExtract
- else if HasOption('l','list') then
- FRunMode:=rmList;
- if HasOption('m','mode') then
- begin
- rm:=GetOptionValue('m','mode');
- case RM of
- 'list' : FRunMode:=rmList;
- 'extract' : FRunMode:=rmExtract;
- else
- Usage('Invalid run mode: '+RM);
- Exit;
- end;
- end;
- if FRunMode=rmExtract then
- begin
- if HasOption('i','index') then
- begin
- Idx:=GetOptionValue('i','index');
- FResIndex:=StrToIntDef(Idx,-1);
- if FResIndex=-1 then
- begin
- Usage('Invalid (not numerical) value for index: '+Idx);
- Exit;
- end;
- end
- else
- begin
- FResIndex:=-1;
- FResName:=GetOptionValue('n','name');
- FResType:=GetOptionValue('t','type');
- if (FResName='') or (FResType='') then
- begin
- Usage(Format('Need both type (got: "%s") and name (got: "%s") for extracting a resource. ',[fResType,fresName]));
- Exit;
- end;
- end;
- if FDestFile='' then
- if FResIndex>0 then
- FDestFile:=ChangeFileExt(FInputFile,Format('-resource-%d.dat',[FResIndex]))
- else
- begin
- RM:=FResName;
- if RM[1]='#' then
- RM:=Copy(RM,2);
- FDestFile:=ChangeFileExt(FInputFile,Format('-resource-%s-%s.dat',[FResType,RM]))
- end;
- end;
- Result:=True;
- end;
- procedure TRestool.Usage(const aErr: String);
- begin
- If (aErr<>'') then
- Writeln('Error: ',aErr);
- Writeln('Usage : ',ExtractFileName(ParamStr(0)),' [options] [inputfile [outputfile]]');
- Writeln('Where options is one or more of:');
- Writeln('-h --help This message');
- Writeln('-i --index=IDX Index of resource to extract.');
- Writeln('-n --name=NAME Name of resource to extract');
- Writeln('-t --type=TYPE Type of resource to extract. Known type names (RT_RCDATA etc.) can be used.');
- Writeln('-l --list List resources in file (equivalent to -m list).');
- Writeln('-x --extract Extract a resource from file. Specify -i or -n and -t options. (equivalent to -m extract)');
- Writeln('-m --mode=MODE set mode to extract or list.');
- Writeln('-o --output=FILE Filename to extract a resource to (or specify the name as the second non-option argument.');
- Writeln(' If no filename is given, a default name is constructed from either index or Filename to extract a resource to (or specify the name as the second non-option argument.');
- Writeln('-s --structured List resources in structured form: resources are listed under their group.');
- ExitCode:=Ord(aErr<>'');
- end;
- procedure TRestool.doRun;
- var
- FOut : Text;
- begin
- Terminate;
- FInputFile:=ParamStr(0);
- if not ProcessOptions then
- Exit;
- Case FRunMode of
- rmList :
- begin
- if (FDestFile='') then
- dumpresourcefile(FInputFile,Output)
- else
- begin
- AssignFile(Fout,FDestFile);
- Rewrite(Fout);
- dumpresourcefile(FInputFile,Fout);
- CloseFile(Fout);
- end
- end;
- rmExtract:
- begin
- FResfile.LoadFromFile(FInputFile);
- if FResIndex>=0 then
- ExtractResource(FDestFile,FResIndex)
- else
- ExtractResource(FDestFile,FResType,FresName)
- end;
- end;
- end;
- procedure TRestool.ExtractResource(const aDestFile: String; aIdx: Integer);
- var
- Res : TAbstractResource;
- begin
- if (aIdx<0) or (aIdx>=FresFile.Count) then
- begin
- ExitCode:=2;
- Writeln(stdErr,'Resource with index ',aIdx,' not found. Max value for index: ',FresFile.Count-1);
- Exit;
- end;
- Res:=FResfile.Items[aIdx];
- WriteResource(Res,aDestFile);
- end;
- procedure TRestool.ExtractResource(const aDestFile, aType, aName: String);
- var
- I : integer;
- aTypeId,aID : TResID;
- Res : TAbstractResource;
- begin
- aTypeID:=0;
- aID:=0;
- I:=StrToIntDef(aType,-1);
- if (I<0) then
- I:=KnownTypeNameToID(aType);
- if I>=0 then
- aTypeID:=I;
- I:=StrToIntDef(aName,-1);
- if (I>=0) then
- aID:=I;
- if aTypeID>0 then
- begin
- if aID>0 then
- Res:=FResfile.Find(aTypeID,aID)
- else
- Res:=FResfile.Find(aTypeID,aName)
- end
- else
- begin
- if aID>0 then
- Res:=FResfile.Find(aType,aID)
- else
- Res:=FResfile.Find(aType,aName);
- end;
- if not Assigned(Res) then
- begin
- ExitCode:=2;
- Writeln(stdErr,'Resource with type ',aType,' and name ',aName,' not found.');
- end;
- WriteResource(Res,aDestFile);
- end;
- Var
- Application : TResTool;
- begin
- Application:=TResTool.Create(Nil);
- Application.Initialize;
- Application.Run;
- Application.Free;
- end.
|