[Back to FILES SWAG index]  [Back to Main SWAG index]  [Original]

===========================================================================
 BBS: Canada Remote Systems
Date: 07-03-93 (11:56)             Number: 29412
From: KELD R. HANSEN               Refer#: NONE
  To: JON JASIUNAS                  Recvd: NO  
Subj: Re: Self-modifying .EXEs       Conf: (1221) F-PASCAL
---------------------------------------------------------------------------
In a message dated 28 Jun 93, Jon Jasiunas (1:273/216.0) wrote:

 > Here's the code I use for my self-modifying .EXEs.  I've used it
 > successfully in several applications.

It works fine (I have one similar of my own), but it doesn't take care of DPMI
programs and won't work if your "customer" PKLITEs the program.

TYPE
  ExeHeaderDOS          = RECORD
                { 00 }      Signature           : ARRAY[1..2] OF CHAR;
                { 02 }      LastPageSize        : WORD;
                { 04 }      Pages               : WORD;
                { 06 }      RelocItems          : WORD;
                { 08 }      HeaderSizePara      : WORD;
                { 0A }      MinMemPara          : WORD;
                { 0C }      MaxMemPara          : WORD;
                { 0E }      EntrySS             : WORD;
                { 10 }      EntrySP             : WORD;
                { 12 }      CheckSum            : WORD;
                { 14 }      EntryIP             : WORD;
                { 16 }      EntryCS             : WORD;
                { 18 }      FirstRelocItemOfs   : WORD;
                { 1A }      OverlayNumber       : WORD;
                            Reserved            : ARRAY[$1C..$23] OF BYTE;
                { 24 }      IdentifierOEM       : WORD;
                { 26 }      InformationOEM      : WORD;
                            ReservedToo         : ARRAY[$28..$3B] OF BYTE;
                { 3C }      NewExeHeaderOfs     : LONGINT
                          END;
  ExeHeaderOS2          = RECORD
                            Signature           : ARRAY[1..2] OF CHAR;
                            LinkerMajorVers     : BYTE;
                            LinkerMinorVers     : BYTE;
                            EntryTableOfs       : WORD;
                            EntryTableSize      : WORD;
                            CRC                 : LONGINT;
                            ModuleFlags         : WORD;
                            SegmentNoDGROUP     : WORD;
                            HeapSize            : WORD;
                            StackSize           : WORD;
                            EntryIP             : WORD;
                            EntryCS             : WORD;
                            EntrySP             : WORD;
                            EntrySS             : WORD;
                            SegmentTableEntries : WORD;
                            ModuleRefEntries    : WORD;
                            NonResNameTableSize : WORD;
                            SegTableOfs         : WORD;
                            ResourceTableOfs    : WORD;
                            ResNamesTableOfs    : WORD;
                            ModuleRefTableOfs   : WORD;
                            ImpNamesTableOfs    : WORD;
                            NonResNamesTableOfs : LONGINT;
                            MovableEntryPoints  : WORD;
                            AlignmentUnitPower  : WORD;
                            ResourceTableEntries: WORD;
                            TargetOS            : BYTE;
                            WindowsFlags        : BYTE;
                            FastLoadStart       : WORD;
                            FastLoadSize        : WORD;
                            Reserved            : WORD;
                            WindowsVers         : WORD
                          END;
  SegTableRec           = RECORD
                            Start               : WORD;
                            Size                : WORD;
                            Flags               : WORD;
                            MinSize             : WORD
                          END;
  FileOffset            = LONGINT;

PROCEDURE ReadOnly;
  INLINE($C6/$06/FileMode/$A0);

PROCEDURE ReadWrite;
  INLINE($C6/$06/FileMode/$02);

{ ExeOfs returns the offset of the item V in the .EXE file of the currently   }
{ running program. Use this to get the offset of a configuration record that  }
{ is located in the .EXE file (remember that you must declare it as a typed   }
{ constant to include it in the .EXE file)                                    }

{$IFDEF DPMI }
FUNCTION ExeOfs(CONST V) : FileOffset;
  VAR
    HeaderDOS   : ExeHeaderDOS;
    HeaderOS2   : ExeHeaderOS2;
    FIL         : FILE;
    CodeSeg,Seg : WORD;
    SegTab      : SegTableRec;

  BEGIN
    ReadOnly;
    ASSIGN(FIL,ParamStr(0)); RESET(FIL,1);
    BLOCKREAD(FIL,HeaderDOS,SizeOf(ExeHeaderDOS));
    IF HeaderDOS.Signature<>'MZ' THEN
      ExeOfs:=-1
    ELSE BEGIN
      SEEK(FIL,HeaderDOS.NewExeHeaderOfs);
      BLOCKREAD(FIL,HeaderOS2,SizeOf(ExeHeaderOS2));
      IF HeaderOS2.Signature<>'NE' THEN
        ExeOfs:=-1
      ELSE BEGIN
        ASM
                MOV     BX,WORD PTR V+2
                MOV     CX,SS
                CMP     BX,CX
                JE      @STACK
                XOR     AX,AX
                VERW    BX
                JZ      @OUT
                MOV     ES,BX
                MOV     AX,ES:[0000h]
                JMP     @OUT
        @STACK: MOV     AX,HeaderOS2.EntrySS
        @OUT:   MOV     CodeSeg,AX
        END;
        IF CodeSeg<>0 THEN BEGIN
          SEEK(FIL,HeaderDOS.NewExeHeaderOfs+HeaderOS2.SegTableOfs+
            PRED(CodeSeg)*SizeOf(SegTableRec));
          BLOCKREAD(FIL,SegTab,SizeOf(SegTableRec)) END
        ELSE BEGIN
          SEEK(FIL,HeaderDOS.NewExeHeaderOfs+HeaderOS2.SegTableOfs);
          FOR Seg:=1 TO HeaderOS2.SegmentTableEntries DO BEGIN
            BLOCKREAD(FIL,SegTab,SizeOf(SegTableRec));
            IF (SegTab.Start>0) AND (SegTab.Flags AND $0001=$0001) THEN BREAK
          END
        END;
        ExeOfs:=SegTab.Start SHL HeaderOS2.AlignmentUnitPower+OFS(V)
      END
    END;
    CLOSE(FIL);
    ReadWrite
  END;
{$ELSE }
FUNCTION ExeOfs(CONST V) : FileOffset;
  VAR
    HeaderDOS   : ExeHeaderDOS;
    FIL         : FILE;

  BEGIN
    ReadOnly;
    ASSIGN(FIL,ParamStr(0)); RESET(FIL,1);
    BLOCKREAD(FIL,HeaderDOS,SizeOf(ExeHeaderDOS));
    CLOSE(FIL);
    ExeOfs:=(HeaderDOS.HeaderSizePara+(SEG(V)-(PrefixSeg+$0010)))*16+OFS(V)
  END;
{$ENDIF }

[Back to FILES SWAG index]  [Back to Main SWAG index]  [Original]