home *** CD-ROM | disk | FTP | other *** search
/ POINT Software Programming / PPROG1.ISO / pascal / swag / exec.swg / 0015_Appending to EXE Files.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1994-01-27  |  5.2 KB  |  168 lines

  1. {
  2. >Hmmm.... how about this.... I want to put a 75k MOD file into the EXE...
  3. >I've heard that you use pointers and appending the MOD to end of your
  4. >compiled program and stuff like that... I'm not too sure how to go about
  5. >it.
  6.  
  7. In short, the easiest way is to append to to your .EXE file. The
  8. following code will search the current .exe for data appended to
  9. the end of the .exe file.
  10. }
  11.  
  12. Uses
  13.   DOS;
  14.  
  15. TYPE              { .exe file header }
  16.   EXEH = RECORD
  17.     id,            { .exe signature }
  18.     Lpage,         { .exe file size mod 512 bytes; < 512 bytes }
  19.     Fpages,        { .exe file size div 512 bytes; + 1 if Lpage > 0 }
  20.     relocitems,    { number of relocation table items }
  21.     size,          { .exe header size in 16-byte paragraphs }
  22.     minalloc,      { min heap required in additional to .exe image }
  23.     maxalloc,      { extra heap desired beyond that required
  24.                      to hold .exe's image }
  25.     ss,            { displacement of stack segment }
  26.     sp,            { initial SP register value }
  27.     chk_sum,       { complemented checksum }
  28.     ip,            { initial IP register value }
  29.     cs,            { displacement of code segment }
  30.     ofs_rtbl,      { offset to first relocation item }
  31.     ovr_num : word; { overlay numbers }
  32.   END;
  33.  
  34. CONST
  35.   MAX_BLOCK_SIZE = 65528; {maximum allowable size of data block in
  36.                             TP}
  37. TYPE
  38.   pdata = ^data_array;
  39.   data_array = array[0..MAX_BLOCK_SIZE] of byte;
  40.  
  41.   pMODblock = ^MODblock;
  42.   MODblock = RECORD
  43.     data     :pdata;
  44.     datasize :word;
  45.   end;
  46.  
  47. VAR
  48.   exefile : file;
  49.   exehdr  : exeh;
  50.   blocks  : word;
  51.  
  52.   exesize,
  53.   imgsize : longint;
  54.  
  55.   path    : dirstr;
  56.   name    : namestr;
  57.   ext     : extstr;
  58.   EXEName : pathstr;
  59.   n       : byte;
  60.  
  61.   dirfile : searchrec;
  62.  
  63.   M       : pMODblock;
  64.  
  65. {Determines the exe filename, opens the file for read-only, and
  66.  determines the actual .exe code image size by reading the
  67.  standard .exe header that is in front of every .exe file. The .MOD
  68.  data will be in the file *after* the end of the code image.}
  69. Procedure ReadHdr;
  70.  
  71.   {this "finds" your exe filename}
  72.   Function CalcEXEName : string;
  73.   var
  74.     Dir  : DirStr;
  75.     Name : NameStr;
  76.     Ext  : ExtStr;
  77.   begin
  78.     if Lo(DosVersion) >= 3 then
  79.       EXEName := ParamStr(0)
  80.     else
  81.       EXEName := FSearch('progname.EXE', GetEnv('PATH'));
  82.                          {  ^^^^^^^^ } { change this to intended EXE name }
  83.     FSplit(EXEName, Dir, Name, Ext);
  84.     CalcEXEName := Name;
  85.   end;
  86.  
  87. begin
  88.   Name := CalcEXEName;
  89.  
  90.   findfirst(EXEName, anyfile, dirfile);
  91.   while (doserror=0) do
  92.   BEGIN
  93.     Assign(exefile, EXEName);
  94.     Reset(exefile, 1);         { reset for 1 byte records }
  95.     BlockRead(exefile, exehdr, SizeOf(exehdr), blocks);
  96.     if blocks<SizeOf(exehdr) then
  97.     begin
  98.       Writeln('File read error!');
  99.       Halt(1);
  100.     end;
  101.     exesize := dirfile.size;     { the total file size of exe+data }
  102.     with exehdr do
  103.     begin
  104.       imgsize := FPages; {exe img size div 512 bytes, +1 if Lpage>0}
  105.       if LPage > 0 then
  106.         dec(imgsize);
  107.       imgsize := (imgsize*512) + LPage; {final image size}
  108.     end;
  109.   END;
  110. end;
  111.  
  112. { this function reads the 64k-8 byte sized block, numbered
  113.   "blocknum" from the end of the file exefile (already opened in
  114.   ReadHdr proc above), allocates a new pMODblock structure and
  115.   passes it back to the caller. "blocknum" is 0-based - ie, data
  116.   offset starts at 0. If the remaining data is less than 64k, the
  117.   data record will be sized to the remaining data.}
  118. Function ReadBlockFromMOD(blocknum):pMODblock;
  119. var
  120.   filepos : longint;
  121.   mod     : pMODblock;
  122. begin
  123.   filepos := imgsize + (blocknum*MAX_BLOCK_SIZE);
  124.   if filepos > exesize then {block position asked for exceeds filesize}
  125.   begin
  126.     ReadBlockFromMOD := NIL; { return error signal }
  127.     EXIT;                    {...and return}
  128.   end;
  129.   New(mod);
  130.  
  131.   if (filepos+MAX_BLOCK_SIZE>exesize) then
  132.     mod^.datasize := exesize-filepos
  133.         { data left in this block is less than 64k }
  134.   else
  135.     mod^.datasize := MAX_BLOCK_SIZE;
  136.         { data block is a full 64k }
  137.   GetMem(mod^.data, mod^.datasize); {get the memory for the data buffer}
  138.  
  139.   Seek(exefile, filepos); { position dos's filepointer to beginning of block}
  140.   BlockRead(exefile, mod^.data^, mod^.datasize, blocks);
  141.  
  142.   if blocks<mod^.datasize then { make sure we got all the data }
  143.   begin
  144.     Writeln('File read error!');
  145.     FreeMem(mod^.data, mod^.datasize);
  146.     Dispose(mod);
  147.     ReadBlockFromMOD := NIL;
  148.     EXIT;
  149.   end;
  150.  
  151.   ReadBlockFromMOD := mod;
  152. end;
  153.  
  154. {
  155.    This will read in the .MOD from the "back" of the .exe 64k-8
  156.    bytes at a time. As written, you manually have to pass a block
  157.    number to the "read" function.
  158.  
  159.    A couple of caveats - doing it as written is error-prone. Using
  160.    this code "barebones" in a finished application is not advisable,
  161.    but it does demonstrate the concept and gives you a starting
  162.    point. THIS CODE HAS NOT BEEN TESTED! If you have problems with
  163.    it, let me know and I'll help you out.
  164.  
  165.    After you have digest the code, ask some more questions and we
  166.    can discuss streams and OOP techniques to do this in a less
  167.    dangerous manner.
  168. }