February 2012
    Get Version

January 2007
    Bezier Text

December 2005
    Rotated Ellipses

December 2004
    PDF Page Count

January 2003
    Boolean Blues

March 2002
    Networked Drives

January 2002
    Treeview Troubles
» Appending to Exe's



Freeware Components
Appending to Exe's 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;

Copyright © 2002-2006 Angus Johnson