How to embed binary data in an executable (Views: 708)
Problem/Question/Abstract: I have a very specialized script language which requires an executable program (The Engine) to load and process scripts. This works on the basis that each script requires its own copy of the executable processing engine (for reasons about to be explained). I want to take this a step further by embedding a script inside the executable at runtime. This will be done from my existing script editor. Something like a compile script function. How can I open an executable file, safely add a block of binary data which can then be read when the executable is running? I know this can be done. If virus writers can put additional executable code into an *.exe file, then I must be able to put binary data in. Answer: I wrote this component to embed data in forms or datamodules. Drop the component in the form, double click it and select the file to embed. I have written a version that compresses the data also, but I lost it, anyway, is not complicated to do so if you want compressed data. unit uBinaryData; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, DsgnIntf; type TBinaryData = class(TComponent) private MemStream: TStream; TempFileName: string; procedure WriteData(Stream: TStream); procedure ReadData(Stream: TStream); procedure SetStream(Stream: TStream); function GetDataSize: Longint; procedure SetDataSize(ASize: Longint); protected procedure DefineProperties(Filer: TFiler); override; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; function GetTempFile(const Ext: string): string; procedure DeleteTempFile; procedure SaveToFile(const FName: string); property Stream: TStream read MemStream write SetStream; published property DataSize: Longint read GetDataSize write SetDataSize; end; TBinaryDataEditor = class(TComponentEditor) protected function GetVerbCount: Integer; override; function GetVerb(index: Integer): string; override; procedure ExecuteVerb(index: Integer); override; procedure Edit; override; end; procedure Register; implementation { TBinaryData } constructor TBinaryData.Create; begin inherited; MemStream := TMemoryStream.Create; end; destructor TBinaryData.Destroy; begin MemStream.Free; if TempFileName <> '' then DeleteTempFile; inherited; end; function TBinaryData.GetDataSize; begin Result := MemStream.Size; end; procedure TBinaryData.SetDataSize; begin (MemStream as TMemoryStream).SetSize(ASize); end; procedure TBinaryData.DefineProperties; begin inherited; Filer.DefineBinaryProperty('TheData', ReadData, WriteData, true); end; procedure TBinaryData.ReadData; var ASize: Longint; begin Stream.Read(ASize, sizeof(ASize)); if ASize > 0 then begin (MemStream as TMemoryStream).SetSize(ASize); Stream.Read((MemStream as TMemoryStream).Memory^, ASize); end; end; procedure TBinaryData.WriteData; var ASize: Longint; begin ASize := MemStream.Size; Stream.Write(ASize, sizeof(ASize)); if ASize > 0 then Stream.Write((MemStream as TMemoryStream).Memory^, ASize); end; procedure TBinaryData.SetStream; begin if Stream <> nil then (MemStream as TMemoryStream).LoadFromStream(Stream) else (MemStream as TMemoryStream).SetSize(0); end; function TBinaryData.GetTempFile; const FirstChars: PChar = 'AAA'; var PathBuffer: array[0..255] of char; FileName: array[0..MAX_PATH] of char; FileStream: TFileStream; begin GetTempPath(256, PathBuffer); if GetTempFileName(PathBuffer, FirstChars, 0, FileName) = 0 then raise Exception.Create('No se pudo crear el archivo temporal'); Result := StrPas(FileName); DeleteFile(Result); Result := ChangeFileExt(Result, Ext); TempFileName := Result; FileStream := TFileStream.Create(Result, fmCreate); try MemStream.Seek(0, 0); FileStream.CopyFrom(MemStream, MemStream.Size); finally FileStream.Free; end; end; procedure TBinaryData.DeleteTempFile; begin DeleteFile(TempFileName); TempFileName := ''; end; procedure TBinaryData.SaveToFile; var s: TFileStream; begin s := TFileStream.Create(FName, fmCreate); try Stream.Seek(0, 0); s.CopyFrom(Stream, Stream.Size); finally s.Free; end; end; { TBinaryDataEditor } function TBinaryDataEditor.GetVerbCount; begin Result := 1; end; function TBinaryDataEditor.GetVerb; begin Result := 'Load File...'; end; procedure TBinaryDataEditor.ExecuteVerb; begin Edit; end; procedure TBinaryDataEditor.Edit; var OpenDialog: TOpenDialog; FileStream: TFileStream; begin OpenDialog := TOpenDialog.Create(Application); try OpenDialog.Filter := '*.*'; if OpenDialog.Execute then if FileExists(OpenDialog.Filename) then begin FileStream := TFileStream.Create(OpenDialog.Filename, fmOpenRead); try (Component as TBinaryData).Stream := FileStream; Designer.Modified; finally FileStream.Free; end; end; finally OpenDialog.Free; end; end; procedure Register; begin RegisterComponents('Misc', [TBinaryData]); RegisterComponentEditor(TBinaryData, TBinaryDataEditor); end; end. |