(* GABE KRUPA > I need to add some information to the end of an EXE file and be able > Say a PCX image for example. I'm concerned about the EXE file alread > open due to being executed. Does info tacked to the end of an EXE ge > into memory automatically, etc. I haven't tried this yet but am abou > hoping someone who has tried it can assist me to avoid some of the pi > they may have encountered. Thanks. (BTW, I am experienced in Pas & Well, I made a unit for that purpose, but my unit only tacks on 1K of storage space... You can make it as large as you want it, but it'll be a REAL time consumer and it might push your text editor to the limits (I'm not sure if the IDE has a file size limit). Here it is (in a VERY shortened version ) } unit inject1k; interface implementation const doesnt_matter_what_this_is_called : boolean = false; procedure never_really_call_this_procedure; begin if doesnt_matter_what_this_is_called then inline( 228/229/230/231/231/233/234/ { this I use for a ID string } 234/234/234/234/234/234/234/ 234/234/234/234/243/234/234/ { repeat as many times until you get enough .. each '234/' is 1 byte } 234/234/234/234/234/234/234/ 234/234/234/234/234/234/234/ { this is the actual 'junk' } ); { inline } end; { procedure } end. { unit } { I only inject 1024 into my EXE file... If you want, you can make identical units like that, but the DATA area will NOT be in one long string unless all the bytes are in one unit. I use the ID string to correctly place the file pointer. Just open the EXE, read in bytes until you get a 228. Read another, if it's a 229 etc.. Keep looping until you get a 228-229-230-231-232-233-234 and then you can start reading/writing. It's by no means the easiest way, but I prefer it over trying to append to the end. I tried that, but I kept getting errors and such. As long as the PCX file is fairly small, you won't have too much of a problem. I'm not sure what the chances are, they must be pretty slim to find a string (228-234) one after the other in an EXE. If you think they are higher, or whatever, just put your own in. You could probably even put text in like this: } inline('D'/'A'/'T'/'A'/' '/'S'/'T'/'A'/'R'/'T'/'S'/' '/'H'/'E'/'R'/'E'/ 111/111/111/111 { etc... } ); { I hope this helps, or gives you some ideas. Note, the unit will be about TWICE as large as the number of bytes you inject (maybe 1000 more), but the EXE will only increse by the number you add. I'm pretty sure that the extra bytes are just data/debug info in the TPU file. *) { MARK LEWIS > I need to add some information to the end of an EXE file and be able > Say a PCX image for example. I'm concerned about the EXE file alread [... trim ...] > Well, I made a unit for that purpose, but my unit only tacks on > 1K of storage space... You can make it as large as you want it, > but it'll be a REAL time consumer and it might push your text > editor to the limits (I'm not sure if the IDE has a file size > limit). Here it is (in a VERY shortened version ) > unit inject1k; [... trim ...] interesting<>... i never thought of doing it like that.. hehe.. here's a unit i got from this echo or the other PASCAL echo several years ago.. i've used it in self-limiting programs (ones that only run a certain number of times) and other programs that may be subject to hacking of various forms... i've modified it slightly for my purposes... } unit selfmod; { Allows a program to self modify a typed constant in the .exe file. It } { also performs an automatic checksum type .exe file integrity check. } { A longint value is added to the end of the exe file. This can be read by } { a separate configuration program to enable it to determine the start of } { the programs configuration data area. To use this the configuration } { typed constant should be added immediately following the declaration of } { ExeData. } { Where this unit is used, it should always be the FIRST unit listed in the } { uses declaration area of the main program. } { Requires DOS 3.3 or later. Program must not be used with PKLite or LZExe } { or any similar exe file compression programs. } { The stack size needed is at least 9,000 bytes. } interface type ExeDatatype = record IDStr : string[8]; FirstTime : boolean; Hsize : word; ExeSize : longint; CheckSum : longint; StartConst : longint; end; const ExeData : ExeDatatype = (IDStr : 'IDSTRING'; FirstTime : true; Hsize : 0; ExeSize : 0; CheckSum : 0; StartConst: 0); { IMPORTANT: Put any config data typed constants here } procedure Write2Exec(var data; size: word); {============================================================================} implementation procedure InitConstants; var f : file; tbuff : array[0..1] of word; function GetCheckSum : longint; { Performs a checksum calculation on the exe file } var finished : boolean; x, CSum : longint; BytesRead : word; buffer : array[0..4095] of word; begin {$I-} seek(f,0); finished := false; CSum := 0; x := 0; BlockRead(f,buffer,sizeof(buffer),BytesRead); while not finished do begin { do the checksum calculations } repeat { until file has been read up to start of config area } inc(CSum,buffer[x mod 4096]); inc(x); finished := ((x shl 1) >= ExeData.StartConst); until ((x mod 4096) = 0) or finished; if not finished then { data area has not been reached } BlockRead(f,buffer,sizeof(buffer),BytesRead); end; GetCheckSum := CSum; end; begin assign(f, ParamStr(0)); {$I-} Reset(f,1); with ExeData do begin if FirstTime and (IOResult = 0) then begin Seek(f,2); { this location has the executable size } BlockRead(f,tbuff,4); ExeSize := tbuff[0]+(pred(tbuff[1]) shl 9); seek(f,8); { get the header size } BlockRead(f,hsize,2); FirstTime := false; StartConst := longint(hsize+Seg(ExeData)-PrefixSeg) shl 4 + Ofs(ExeData) - 256; CheckSum := GetCheckSum; Seek(f,StartConst); BlockWrite(f,ExeData,sizeof(ExeData)); seek(f,FileSize(f)); BlockWrite(f,StartConst,4); end else if GetCheckSum <> CheckSum then begin writeln; writeln(#7,#7,'Program file has been UNLAWFULLY modified!',#7,#7); writeln; writeln('It may have a Virus attached or someone may have made'); writeln('an attempt to HACK it. You should check your system for'); writeln('virus'' before continuing....'); writeln; writeln('Please reinstall the .EXE file from the original archive.'); writeln('Aborting....'); halt(255); end else begin writeln; writeln('Integrity Validated.'); end; end; { with } Close(f); {$I+} if IOResult <> 0 then begin writeln('Unable to initialise program'); halt; end; end; { InitConstants } procedure Write2Exec(var data; size: word); { writes a new typed constant into the executable file. } var f : file; begin assign(f, ParamStr(0)); {$I-} Reset(f,1); Seek(f,longint(ExeData.Hsize+Seg(data)-PrefixSeg) shl 4 + Ofs(data)- 256); BlockWrite(f,data,size); Close(f); {$I+} if IOResult <> 0 then; end; { Write2Exec } begin writeln('Please Standby...'); InitConstants; end.