Appending to Exe's http://angusj.com/delphitips/appendtoexe.php
24 Jan 2002
Have you ever wanted to add something extra onto the end of an EXE file and then be able to find it easily from within the EXE's code?
A typical example of this is a self-extracting EXE file, where the EXE stub has an appended compressed archive . When the stub is executed, the code needs to know the size of the stub in order to find the offset to the beginning of the archive. The size of the stub is commonly "hard coded" (inserted into the code as a constant) once it has been determined by compiling the stub and then viewing its file properties in Explorer. To access an appended file, the stub loads itself (stub with appended archive) into a filestream and sets the stream's position to this hard coded offset.
The problem with this "hard coded" approach is that any change to the EXE's code is likely to change the size of the EXE. The following code snippet, solves this problem by examining the EXE's header to determine its size. A close examination of the numerous PE fileheader structures would help fully understand this code but, as I imagine most readers wouldn't find this interesting, you wont be bored with the details. However, one thing which may be useful to know is the hInstance handle is actually a pointer to the base of the file image once it has been loaded into memory.
Code snippet ...
{$IFDEF VER100}
{TImageDosHeader isn't defined in Delphi 3 so here's an
an abbreviated structure definition...}
type
PImageDosHeader = ^TImageDosHeader;
TImageDosHeader = packed record
e_magic : WORD;
e_ignore : packed array [0..28] of WORD;
_lfanew : Longint;
end;
{$ENDIF}
function GetExeSize: cardinal;
var
p: pchar;
i, NumSections: integer;
begin
result := 0; // if error then result = 0
p := pointer(hinstance);
inc(p, PImageDosHeader(p)._lfanew + sizeof(dword));
NumSections := PImageFileHeader(p).NumberOfSections;
inc(p,sizeof(TImageFileHeader)+ sizeof(TImageOptionalHeader));
for i := 1 to NumSections do
begin
with PImageSectionHeader(p)^ do
if PointerToRawData+SizeOfRawData > result then
result := PointerToRawData+SizeOfRawData;
inc(p, sizeof(TImageSectionHeader));
end;
end;