Author: Jonas Bilinkevicius
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.
1 unit uBinaryData;
2
3 interface
4
5 uses
6 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
7 DsgnIntf;
8
9 type
10 TBinaryData = class(TComponent)
11 private
12 MemStream: TStream;
13 TempFileName: string;
14 procedure WriteData(Stream: TStream);
15 procedure ReadData(Stream: TStream);
16 procedure SetStream(Stream: TStream);
17 function GetDataSize: Longint;
18 procedure SetDataSize(ASize: Longint);
19 protected
20 procedure DefineProperties(Filer: TFiler); override;
21 public
22 constructor Create(AOwner: TComponent); override;
23 destructor Destroy; override;
24 function GetTempFile(const Ext: string): string;
25 procedure DeleteTempFile;
26 procedure SaveToFile(const FName: string);
27 property Stream: TStream read MemStream write SetStream;
28 published
29 property DataSize: Longint read GetDataSize write SetDataSize;
30 end;
31
32 TBinaryDataEditor = class(TComponentEditor)
33 protected
34 function GetVerbCount: Integer; override;
35 function GetVerb(index: Integer): string; override;
36 procedure ExecuteVerb(index: Integer); override;
37 procedure Edit; override;
38 end;
39
40 procedure register;
41
42 implementation
43
44 { TBinaryData }
45
46 constructor TBinaryData.Create;
47 begin
48 inherited;
49 MemStream := TMemoryStream.Create;
50 end;
51
52 destructor TBinaryData.Destroy;
53 begin
54 MemStream.Free;
55 if TempFileName <> '' then
56 DeleteTempFile;
57 inherited;
58 end;
59
60 function TBinaryData.GetDataSize;
61 begin
62 Result := MemStream.Size;
63 end;
64
65 procedure TBinaryData.SetDataSize;
66 begin
67 (MemStream as TMemoryStream).SetSize(ASize);
68 end;
69
70 procedure TBinaryData.DefineProperties;
71 begin
72 inherited;
73 Filer.DefineBinaryProperty('TheData', ReadData, WriteData, true);
74 end;
75
76 procedure TBinaryData.ReadData;
77 var
78 ASize: Longint;
79 begin
80 Stream.read(ASize, sizeof(ASize));
81 if ASize > 0 then
82 begin
83 (MemStream as TMemoryStream).SetSize(ASize);
84 Stream.read((MemStream as TMemoryStream).Memory^, ASize);
85 end;
86 end;
87
88 procedure TBinaryData.WriteData;
89 var
90 ASize: Longint;
91 begin
92 ASize := MemStream.Size;
93 Stream.write(ASize, sizeof(ASize));
94 if ASize > 0 then
95 Stream.write((MemStream as TMemoryStream).Memory^, ASize);
96 end;
97
98 procedure TBinaryData.SetStream;
99 begin
100 if Stream <> nil then
101 (MemStream as TMemoryStream).LoadFromStream(Stream)
102 else
103 (MemStream as TMemoryStream).SetSize(0);
104 end;
105
106 function TBinaryData.GetTempFile;
107 const
108 FirstChars: PChar = 'AAA';
109 var
110 PathBuffer: array[0..255] of char;
111 FileName: array[0..MAX_PATH] of char;
112 FileStream: TFileStream;
113 begin
114 GetTempPath(256, PathBuffer);
115 if GetTempFileName(PathBuffer, FirstChars, 0, FileName) = 0 then
116 raise Exception.Create('No se pudo crear el archivo temporal');
117 Result := StrPas(FileName);
118 DeleteFile(Result);
119 Result := ChangeFileExt(Result, Ext);
120 TempFileName := Result;
121 FileStream := TFileStream.Create(Result, fmCreate);
122 try
123 MemStream.Seek(0, 0);
124 FileStream.CopyFrom(MemStream, MemStream.Size);
125 finally
126 FileStream.Free;
127 end;
128 end;
129
130 procedure TBinaryData.DeleteTempFile;
131 begin
132 DeleteFile(TempFileName);
133 TempFileName := '';
134 end;
135
136 procedure TBinaryData.SaveToFile;
137 var
138 s: TFileStream;
139 begin
140 s := TFileStream.Create(FName, fmCreate);
141 try
142 Stream.Seek(0, 0);
143 s.CopyFrom(Stream, Stream.Size);
144 finally
145 s.Free;
146 end;
147 end;
148
149 { TBinaryDataEditor }
150
151 function TBinaryDataEditor.GetVerbCount;
152 begin
153 Result := 1;
154 end;
155
156 function TBinaryDataEditor.GetVerb;
157 begin
158 Result := 'Load File...';
159 end;
160
161 procedure TBinaryDataEditor.ExecuteVerb;
162 begin
163 Edit;
164 end;
165
166 procedure TBinaryDataEditor.Edit;
167 var
168 OpenDialog: TOpenDialog;
169 FileStream: TFileStream;
170 begin
171 OpenDialog := TOpenDialog.Create(Application);
172 try
173 OpenDialog.Filter := '*.*';
174 if OpenDialog.Execute then
175 if FileExists(OpenDialog.Filename) then
176 begin
177 FileStream := TFileStream.Create(OpenDialog.Filename, fmOpenRead);
178 try
179 (Component as TBinaryData).Stream := FileStream;
180 Designer.Modified;
181 finally
182 FileStream.Free;
183 end;
184 end;
185 finally
186 OpenDialog.Free;
187 end;
188 end;
189
190 procedure register;
191 begin
192 RegisterComponents('Misc', [TBinaryData]);
193 RegisterComponentEditor(TBinaryData, TBinaryDataEditor);
194 end;
195
196 end.
|